XML ファイル形式
Extensible Markup Language。汎用の構造化テキスト形式。
- MIME タイプ
- application/xml
- 拡張子
- .xml
- カテゴリ
- テキスト・マークアップ
マジックナンバー(ファイル署名)
'<?xml' 宣言で始まるプレーンテキスト。
XML 形式について
XML は、バイトの並びではなく整形式であるための規則の集合で定義されたテキスト形式です。ルート要素は 1 つ、すべての要素を閉じる、属性値は引用符で囲む、そして少数の文字はエスケープする。ある XML 文書についてそれ以外のこと(要素の名前、許される入れ子、その意味)は標準の外で、スキーマか、たまたま XML を構文として使っている仕様が定めます。まったく無関係なものが同時に XML であるのはそのためです。Office の文書、EPUB、RSS や Atom のフィード、SVG、Android のレイアウト、XMP のメタデータ、サイトマップ、property list。どれも XML でありながら、互いを読めるものは 1 つもありません。
ヘッダーの構造(バイト単位)
| オフセット | 長さ | フィールド | 意味 |
|---|---|---|---|
| 0 | 3 | UTF-8 byte-order mark | EF BB BF で、省略可能です。標準が宣言の前に置くことを許している唯一のもので、最初の山括弧より前に他のバイトが 1 つでもあれば、その文書は整形式ではありません。覚えておく価値のある規則で、丸ごと 1 種類のバグが 2 秒の hex 確認で片付くようになります。 |
| 0 | 2 | UTF-16 byte-order mark | ビッグエンディアンなら FE FF、リトルエンディアンなら FF FE。UTF-8 の BOM と違い、こちらは省略できません。標準は「UTF-16 で符号化された実体は BOM で始まらなければならない」と定めており、UTF-8 の実体については「置いてもよい」に留めています。UTF-16 の XML は珍しく、1 文字 1 バイトを前提にしたツールは軒並み壊れます。 |
| 0 | 5 | XML declaration opener | 3C 3F 78 6D 6C、宣言を始める 5 文字です。位置はオフセット 0 か、UTF-8 の BOM の後ろのオフセット 3 のどちらかで、それ以外にはありません。UTF-8 の内容では省略可能なので、判定器がこれを必須にできないのも、多くの XML がルート要素で識別されるしかないのもそのためです。 |
| 0 | 4 | UTF-16 declaration without a mark | ビッグエンディアンなら 00 3C 00 3F、リトルエンディアンなら 3C 00 3F 00。標準の自動判定の付録がこれらのパターンを列挙しているのには味わい深い循環があって、パーサーはエンコーディングを述べている宣言を読めるだけのエンコーディングを、先に推測しなければならないのです。 |
| 5 | variable | Declaration pseudo-attributes | まず必須の version、次に省略可能な encoding、次に省略可能な standalone。この順序以外は許されません。encoding の値はバイトについての事実ではなく主張です。それを信じたパーサーは、矛盾する最初のバイトで中断しますし、その位置は間違いが起きた場所からはるか遠くになります。 |
| 0 | 5 | DOCTYPE opener | 3C 21 44 4F 43。オフセット 0 に来るのは、宣言も BOM も先頭の空白も無いときだけです。それ以外では prolog が終わったところ、としか言えません。これが正直な答えであり、これを探すのにバイトオフセットの表は道具として間違っていて、パーサーが正しい道具である理由でもあります。 |
似た形式との見分け方
| 紛らわしい形式 | 見分け方 |
|---|---|
| HTML | どちらも山括弧で、どちらもマジックナンバーを持ちませんが、ブラウザが従う sniffing の規則は両者を綺麗に分けます。XML は、任意の空白の後ろにバイト列 3C 3F 78 6D 6C がそのまま来るかどうか。HTML はタグ名のパターン表(DOCTYPE HTML、HTML、HEAD、SCRIPT、IFRAME、TITLE、BODY ほか十数個)との照合で、それぞれの後ろに空白か閉じ山括弧が必要です。より深い違いは、文書が壊れていたときに起きることです。XML のパーサーは止まり、HTML のパーサーは立て直します。 |
| SVG | SVG は XML です。オフセット 0 であれどこであれ、両者を分けるバイトは存在しません。違いはルート要素の名前が svg で、SVG の名前空間を持っていることだけ。あるファイルを svg と報告するツールと、同じファイルを xml と報告するツールは、どちらも正しいのです。どちらかを選ばなければならない判定器は、技術的な判断ではなく編集上の判断を下していることになります。 |
| Android binary XML | APK の中の AndroidManifest.xml は、そもそもテキストではありません。チャンク構造のバイナリ符号化で、先頭 4 バイトは 03 00 08 00(リトルエンディアンのチャンク型 3 とヘッダサイズ 8)、その後ろに文書の長さが続きます。テキストエディタで開いてもバイナリのノイズしか見えないのは、文書中の文字列がすべてファイル内の別の場所のプールへ移され、要素はそれをインデックスで参照しているからです。 |
| Word 文書(docx) | Office ファイルの中に探している XML は確かに実在しますが、ディスク上のファイルは 50 4B 03 04 で始まります。ZIP だからです。.docx も .xlsx も .pptx も、先頭に XML はありません。パーツはアーカイブ内のエントリで、そのうちの [Content_Types].xml という名前の 1 つが、そのパッケージを「たまたまマークアップを含む ZIP」ではなく Office 文書にしています。 |
よくある壊れ方
- prolog に紛れ込んだゴミ。XML は宣言の前にバイトオーダーマークだけを許し、それ以外は何も許しません。だから空行 1 つ、スクリプトが出した警告 1 行、あるいは前置きされた HTML のエラーページが、XML を扱う人なら誰もが見たことのあるエラーを生みます。content is not allowed in prolog。これが意味することはいつでも 1 つだけ、最初の山括弧より前に何かがある、ということです。hex ビューアなら数秒で見つかります。
- 嘘をついているエンコーディング。宣言は UTF-8 と言っているのに実際は Windows-1252、あるいはその逆。0x7F より上の文字が最初に現れるまではすべてパースでき、そこでパーサーは不正なバイト列を報告します。しかも指し示される行は画面上ではごく普通に見えます。その文字は、それを書いたエディタでは問題なく表示されるからです。
- 途中切れ。XML には長さフィールドもトレーラーも無いので、要素が開いたままパーサーが入力を使い果たすまで、切られたことに気づく術がありません。メッセージは premature end of data で、どれだけ失われたかはファイル自身からはまったく復元できません。
- エクスポートデータに混ざった制御文字。XML 1.0 は C0 領域からタブ、改行、復帰の 3 つだけを許し、残りは数値文字参照として書かれていても禁じています。0x00 や 0x0B を持ったデータベースのエクスポートは、整形式に見えて目視の確認も通り抜けるのに、仕様に準拠したパーサーは 1 つとして受け付けないファイルになります。
- エスケープされていないアンパサンドと山括弧。シリアライザではなく文字列連結で組み立てたマークアップは、値に & や < が入った瞬間に壊れます。パーサーは「実体参照にセミコロンが必要」といったエラーを、マークアップの中ではなくデータの中の位置で報告します。直すべき場所がエラーの指す位置とほぼ一致しないのはそのためです。
この形式の現在地
XML は 2005 年に握っていた地盤の大半を失い、本当に重要な地盤を守りました。ウェブ API と設定ファイルでは JSON に、続いて YAML と TOML に置き換えられ、SOAP は今も動いているところでもほぼレガシー扱いです。守ったのは文書です。テキストとマークアップが交互に現れて順序が意味を持つ、いわゆる mixed content を扱うなら、データ形式より XML のほうがはるかに向いています。Office も ODF も EPUB も DocBook も TTML の字幕も動かなかったし、これからも動かないのはそのためです。もう 1 つ守ったのは、検証こそが目的の場所です。XML Schema、XPath、XSLT に相当するものは JSON 側に存在しないので、処理の前に契約と照合しなければならない形式(行政への申告、請求書、フィード、Android のレイアウト)は、たいてい今も XML で届きます。hex エディタで開く対象としては珍しく、ヘッダというものが一切ありません。ファイルの 1 バイト目がもう中身です。
XML ファイルをこのサイトで開く
どれもブラウザ内で動きます。ファイルが端末から出ることはありません。
関連する形式
XML と混同しやすい形式です。先頭バイトを見比べてください。