XML 整形

XML を 2 スペース・4 スペース・タブで整形、または 1 行に圧縮します。入力しながら整形式かを検証し、要素数とネスト深度を表示します。

壁のような XML を読める形に、あるいは元通りに詰め直す。 XML を貼り付けると、好みのインデントで整形し直せます。1 行への圧縮も可能です。入力しながら整形式かどうかを検証し、要素数とネストの深さをカウンターで表示します。

XML を壊さずに整形する

XML では空白も内容の一部

これが XML の整形を JSON の整形と分ける決定的な違いです。JSON ではトークン間の空白に意味はなく、削除は常に安全です。ところが XML では、<name>Ada のあいだの文字はその要素のテキストノードの一部です。インデントを付け直すことは、厳密には文書の中身を変えることを意味します。

実務上これが問題になることはほとんどありません。大多数の XML は「要素のみを含む内容」——要素の中に要素だけがあり、他には何も無い形——を採っており、その周囲の空白はどのスキーマにとっても無視してよいからです。本ツールはそうした要素の内部にだけインデントを加えます。要素が実際のテキストを持つ場合や、HTML のようにテキストと子要素が混在する場合は、その内容をそのまま残します。この 1 つの規則があるおかげで、<p>Hello <b>there</b></p>there の前後に空白が紛れ込むことはありません。

整形式であることと妥当であることは別物

ここで行う検査は「整形式(well-formed)」の確認で、XML 仕様がすべてのパーサーに要求している水準です。ルート要素が 1 つであること、すべてのタグが閉じられ正しく入れ子になっていること、属性値が引用符で囲まれていること、テキスト中の &< がエスケープされていること。どれか 1 つでも欠ければ文書はその場で拒否されます。HTML と違い、XML にエラー回復が無いのは有名な話です。

「妥当(valid)」はさらに先の話で、文書が DTD・XSD・RelaxNG のいずれかのスキーマに適合するかを問います。<invoice> が本当に <total> を含むか、日付が本当に日付か、といったことです。これにはスキーマ本体が必要ですが、それは貼り付けた文書には含まれていません。ここで通ることは、構文が健全でどのパーサーでも読めることを意味しますが、受け側システムが内容を正しいと認めることまでは保証しません。

圧縮と自己終了タグ

圧縮は要素間の無視可能な空白を取り除き、文書全体を 1 行にまとめます。その空白はもともと内容ではないため、要素のみで構成された出力は解析するとまったく同じツリーになります。

もう 1 つの削減は空要素から来ます。仕様上 <summary></summary><summary/> は同一と定義されており、出力では短いほうを使います。効果は本物ですが控えめです。XML のサイズの大半は繰り返されるタグ名——各要素が名前を 2 回書く——が占めているからです。本当に小さくしたいなら答えは gzip で、空白の削除よりはるかに効率よく重複した名前を処理します。なお、圧縮した XML は人にはほぼ読めないので、読む用の整形済みコピーは残しておいてください。

オープンソースに関する注記:バニラ JavaScript で実装。サードパーティライブラリは使用していません。

よくある質問

XML はどこかにアップロードされますか?
いいえ。ブラウザ内蔵の DOMParser で解析と直列化を行うため、サーバーへデータが送信されることはありません。
整形すると文書は変わりますか?
子要素だけを含む要素の内部にのみ空白が入ります。そこでは空白は無視可能です。テキストや混在内容を持つ要素はそのまま残されます。
スキーマに対する検証も行いますか?
いいえ。確認するのは整形式かどうか——タグの閉じと入れ子、ルートが 1 つ、文字のエスケープです。DTD や XSD の検証にはスキーマ本体が必要です。
文書が拒否されるのはなぜですか?
閉じ忘れや対応しないタグ、エスケープされていない & や <、引用符の無い属性値、ルート要素が複数——といった原因が典型です。XML に回復処理はありません。
要素数と深さは何を表していますか?
要素数は文書内の要素ノードの総数です。深さは入れ子の最長の連なりで、ルート要素を 1 段目として数えます。
空タグの形が変わったのはなぜですか?
XML 仕様では <a></a> と <a/> は同一と定義されているため、圧縮出力ではバイト数を節約できる自己終了形式を使います。