XML整形
XMLフォーマッターは、1パスのトークナイザーでXML文書のインデントをブラウザ内で整え直します。コメント、CDATAセクション、DOCTYPEの内部サブセット、山括弧を含む属性値は、すべてそのまま生き残ります。対応が壊れたタグや閉じられていないタグは、ツリーを黙って組み替える代わりに、行と桁の位置つきで報告します。
XML整形はどう動きますか?
ほとんどのXMLフォーマッターは正規表現の連なりです。コメントを剥がし、タグで分割し、インデントを付け直す。この順序は正しくなり得ません。各パスが互いに循環して依存しているからです。<!--がコメントの開始かどうかの判定には、CDATAセクションの内側にいるかどうかの知識が要ります。CDATAセクションがどこから始まるかの判定には、コメントの内側にいないという知識が要ります。>がタグの終わりかどうかの判定には、属性値の内側にいるかどうかの知識が要ります。どの順序を選んでも3つのうち1つが間違いになり、その失敗はエラーとしてではなく、黙った破壊として現れます。
そこでこのフォーマッターは、文書を正確に1回だけ走査してトークンストリームに変えます。宣言、処理命令、DOCTYPE、コメント、CDATA、開始タグ、終了タグ、空要素タグ、テキストです。その後の処理は、このトークン列を畳み込むだけです。トークナイザーは構造上ロスレスです。入力のすべてのバイトは必ずどれか1つのトークンに収まり、それらを連結すれば元の文書がバイト単位で再現されることを保証するテストもあります。
この設計があるからこそ、厄介なケースが特別扱いなしで正しく扱われます。内部サブセット付きのDOCTYPEは内部に>を含み得るため、走査は最初の閉じ山括弧ではなく括弧の深さを追跡します。属性値に>が入ることがあるため、タグの走査は引用符を追跡します。タグの開始ではない裸の<(不正なXMLですが、手書きのファイルにはよくあるもの)は、書き手が成功するはずだと見て取れる整形を止めてしまうのではなく、テキストとしてそのまま運ばれます。
インデントには1つだけ意図的な例外があります。唯一の子がテキストである要素は1行に収まります。2単語のために3行に展開されるのではなく、<name>Ada</name>のままです。すべての葉をばらばらにすることが、機械整形のXMLが手書きのものより読みにくくなる最大の理由です。
ツリーが正しく閉じていない場合、フォーマッターは停止して場所を伝えます。</b>があるべき場所で</c>が現れた場合は行と桁つきで報告し、ツリーの途中で終わる文書では、開いたままの要素の名前を挙げます。代案の、黙ってタグを閉じてあげる方式は、正しく見えてあなたのものではない文書を作ります。あり得る中で最悪の結果です。
最小化した入力
<r><a id="1"><b>x</b></a><!-- c --><d/></r>
整形した出力
<r>
<a id="1">
<b>x</b>
</a>
<!-- c -->
<d />
</r>XML整形が対応するオプションとエッジケースは?
| パラメータ | 型 | デフォルト | 動作とエッジケース |
|---|---|---|---|
| インデント | 2 | 4 | tab | 2スペース | ネスト1段階ごとに適用します。タブが正解なのは、ファイルを設定の異なるエディタで読む場合です。表示幅は読む側が制御できます。 |
| 空白を圧縮 | 真偽値 | true | テキストノード内の連続するスペースや改行を正規化します。テキスト内容が空白に依存する文書、たとえばCDATAセクションの外に埋め込まれたソースコードではオフにしてください。 |
| コメントを削除 | 真偽値 | false | <!-- … -->を丸ごと削除します。コメントはデフォルトで保持します。設定ファイルではコメントが唯一のドキュメントであることがよくあるからです。 |
| 属性を折り返し | 整数 | 0(折り返さない) | この数を超えると属性を1行に1つずつ並べます。SVGやXSLTで便利です。1つの要素が十数個の属性を持ち、折り返さない行は画面外へ消えていきます。 |
| CDATA | 保持 | — | 内部の空白も、マークアップに見える文字も含めてそのまま再現します。CDATAセクションの要点は、中身が解析されないことだからです。 |
| DOCTYPE | 保持 | — | >を含む内部サブセットも含めて完全に保ちます。最初の>までしか走査しないと宣言が途切れ、残りがテキスト扱いになります。 |
| 名前空間 | 保持 | — | プレフィックスとxmlns宣言はそのまま通します。これは整形ツールであって検証ツールではありません。プレフィックスが宣言済みかは確認しません。 |
| 不正な入力 | エラー | — | 閉じタグの不一致、途中で終わるコメントやCDATA、木の途中で終わる文書は、位置付きで報告されます。黙って修復した文書はもう元の文書ではないので、自動修正は一切行いません。 |
よくある質問
整形するとXMLの意味が変わりますか?
1点に限って、変わり得ます。テキストコンテンツ内の空白はXMLではデータであり、それを圧縮すればデータが変わります。だからこそCollapse whitespaceは常時オンではなくスイッチになっています。空白が意味を持つ文書ではオフにしてください。それ以外は、CDATAの中身、コメント、属性値、DOCTYPEを含めて一切変わらず、そのまま保持されます。
文書を直す代わりに、受け付けないのはなぜですか?
どのタグを閉じるつもりだったかを推測するのは、フォーマッターが安全にできることではないからです。<a><b></a>という入力に対して、こちらの代わりに<b>を閉じると、正しく見えてあなたが書いたものと異なるツリーを持つ文書が生まれます。エラーはタグと位置を名指しするので、あなたが判断できます。数秒で済み、間違いようがありません。
SVG、XSLT、RSS、SOAP、Androidのレイアウトは扱えますか?
扱えます。いずれもXMLであり、このツールはスキーマを一切見ません。特にSVGとXSLTは、属性の折り返しオプションが効きます。十数個の属性を持つ単一の要素はよくあることで、折り返さなければ画面の外へ大きくはみ出るからです。
HTMLはどうですか?
XHTMLの形をしたHTMLだけです。本物のHTMLには、閉じない空要素(<br>、<img>)、終了タグが省略できる要素(<li>、<td>)、内容がマークアップとして解釈されない<script>のようなraw-text要素があります。このトークナイザーは文書をXMLの規則で扱うため、閉じられていない<br>はエラーとして報告されます。XMLとしては正しく、HTMLとしては間違った挙動です。
サイズの上限はありますか?
8 MBです。整形はメインスレッドで動くため、この上限を超えるとタブを固める代わりに、ツールが処理を拒みます。トークン化も整形も、再帰ではなく反復で実装しているので、深くネストした文書(5000階層のテストがあります)でも、コールスタックを溢れさせずに結果を返します。
文書はアップロードされますか?
いいえ。トークン化もインデントの付け直しも、すでに開いているタブ内のJavaScriptが行います。Networkパネルを開いて文書を貼り付けてみてください。それを運ぶものは何も出て行きません。XMLの設定ファイルには、接続文字列、内部ホスト名、認証情報が常に入っています。整形のために未知のサーバーを通すべきではない素材そのものです。