FlowingDev

XMLの解説:「たぶん」なんて答えは許さない言語

XML(Extensible Markup Language)は、カスタムタグを使ってデータを構造化するための、人間が読めるフォーマットです。これにより、データは自己記述的になり、機械によるパースも可能になります。

ツールを試す: XMLエディター

一言でいうと

XMLとは、人間とコンピュータが特別な「おまじない」なしに理解できる形でデータを構造化するために、独自のテキストベースフォーマットを作成するための一連の厳格なルールのことです。

どんな問題を解決するのか

90年代初頭のインターネットを想像してみてください。コンピュータ同士がデータを共有する必要がありましたが、その状況はまるでバベルの塔。すべてのシステムが独自の言語、つまりプロプライエタリなバイナリフォーマットのごちゃ混ぜで話していました。システムAがシステムBと話したければ、開発者はカスタムの翻訳機を書く必要がありました。そこにシステムCが登場すれば、さらに2つの翻訳機が必要になります。それは脆くて、スケールしない、めちゃくちゃな状態でした。

時を同じくして、私たちにはウェブページを構造化するための言語、HTMLがありました。ブラウザに「これは見出しだよ」(<h1>)とか「これは段落だよ」(<p>)と伝えるのには最適でした。でも、ウェブページ向けではないデータを記述したかったらどうでしょう?「これはISBN番号だ」とか「これは顧客の配送先住所だ」と言いたかったら?HTMLには、そういったタグはありませんでした。

そこに、1998年に正式に登場したXMLが現れます。HTMLと同じ親を持つSGMLという超複雑な学術的言語から生まれましたが、見事な妥協点を持って設計されました。SGMLの持つ「独自のタグを定義できる」という力はそのままに、ルールをずっとシンプルにしたのです。XMLの「X」は「eXtensible」(拡張可能)を表しており、まさにそれがポイントです。決まったタグのセットに縛られることはありません。独自のタグを発明して、言語を拡張できるのです。

すると突然、それ自体で意味を説明するデータフォーマットを作れるようになりました。ファイルの中にある123-456-7890,Doe,Johnのような謎めいた一行の代わりに、こんな風に書けるようになったのです。

<customer>
  <name>
    <first>John</first>
    <last>Doe</last>
  </name>
  <phone>123-456-7890</phone>
</customer>

誰でも、そしてどんなプログラムでも、これを見ればその意味を理解できます。XMLはデータ交換のための普遍的な文法を提供し、ウェブサービスから複雑な設定ファイルまで、あらゆるものへの道を開きました。

内部の仕組み

XMLの力は、そのシンプルかつ妥協のないルール群から来ています。多少めちゃくちゃでもブラウザが何とかして表示しようと頑張ってくれる、ゆるい従兄弟のHTMLとは違い、XMLパーサーは手厳しい批評家です。たった一つのルールを破っただけで、お手上げだとばかりに処理を止めてしまいます。この厳格さはバグではなく、仕様(フィーチャー)なのです。これによって、データが曖昧にならないことが保証されます。

XMLドキュメントの解剖学

すべてのXMLは、ツリー構造に従うドキュメントです。典型的な例を分解してみましょう。

<?xml version="1.0" encoding="UTF-8"?>
<!-- うちの本屋の在庫 -->
<bookstore>
  <book category="fiction" in_stock="true">
    <title lang="en">The Hitchhiker's Guide to the Galaxy</title>
    <author>Douglas Adams</author>
    <year>1979</year>
    <price>19.99</price>
  </book>
</bookstore>
  • プロローグ (Prolog): <?xml ... ?>は任意ですが、強く推奨される最初の行です。XMLのバージョン(ほとんど常に1.0)と文字エンコーディング(UTF-8がウェブ標準)を宣言します。ドキュメントの身分証明書のようなものです。
  • ルート要素 (Root Element): すべてのXMLドキュメントは、他のすべてを内包するトップレベルの要素をちょうど一つだけ持たなければなりません。この例では<bookstore>がそれです。木の幹だと考えてください。
  • 要素 (Element) (タグ): 要素とは、対になる開始タグ(<book>)と終了タグ(</book>)、そしてその間のコンテンツのことです。大文字と小文字を区別するため、<book>と<Book>は別物です。
  • ネスト (Nesting): 要素は互いに入れ子にされて、ツリー構造を作り出します。<title>は<book>の子であり、<book>は<bookstore>の子です。この親子階層がXMLの構造の中核です。
  • 属性 (Attribute): category="fiction"やin_stock="true"は属性です。開始タグの中にあるキーと値のペアで、要素に関するメタデータを提供します。属性を使うべきか、子要素を使うべきかはよくある議論です。経験則としては、次のように考えると良いでしょう。
    • 属性は、IDや言語コード、真偽値フラグなど、中核となるコンテンツの一部ではない、単純なメタデータや識別子に使いましょう。
    • 要素は、実際のコンテンツや、複雑であったり独自の構造を持つ可能性のあるデータに使いましょう。
  • 内容 (Content): 「Douglas Adams」のようにタグの間にあるものが実際のデータで、しばしば「テキストコンテント」と呼ばれます。
  • コメント: <!-- ... -->は人間向けのメモで、パーサーには無視されます。

ゲームのルール:整形式 vs. 妥当

この2つの用語はXMLの世界では非常に重要です。

整形式 (well-formed) のドキュメントは、すべての基本的な構文ルールに従っています。

  1. ルート要素が一つだけ存在する。
  2. すべての要素は閉じタグを持つ(または<br/>のように自己完結している)。
  3. タグは大文字と小文字を区別する。
  4. 要素は正しくネストされなければならない(<book><author></book></author>のようなことはできない)。
  5. 属性値はクォートで囲まなければならない。

もしXMLが整形式でなければ、それはXMLではありません。ただの壊れたテキストです。

妥当 (valid) なドキュメントは、さらに一歩進んでいます。それは整形式であり、かつスキーマ(XSD - XML Schema Definitionなど)やDTD(Document Type Definition)と呼ばれる特定の設計図に準拠しています。スキーマは、そのXMLの契約を定義する別のファイルです。例えば、こんなことが書かれています。

  • <bookstore>は1つ以上の<book>要素を含まなければならない。
  • すべての<book>は、1つの<title>と1つの<author>を持たなければならない。
  • <price>要素は正の数を含まなければならない。
  • <book>のcategory属性は「fiction」「non-fiction」「reference」のいずれかでなければならない。

妥当性検証とは、用心棒にチケットを持っているか(整形式であるか)をチェックされるだけでなく、そのチケットが今夜のショーのものであり、オペラハウスに猫を連れ込もうとしていないか(妥当であるか)までチェックされるようなものです。

マシンの中のツリー

プログラムがXMLファイルを読み込むとき、それは単なるテキストの壁を見ているわけではありません。それをパースし、**DOM(Document Object Model)**と呼ばれるメモリ上の表現を構築します。これは文字通りのツリーデータ構造です。ルート要素はツリーのルートノードとなり、その子は子ノードとなり、以下同様に続きます。

このツリーモデルこそが、XMLをプログラムで扱うのを非常に強力なものにしている理由です。ライブラリを使えば、次のようなことを言えます。

  • 「category属性が'fiction'であるすべての<book>要素を見つけて」
  • 「<author>が'Douglas Adams'である本の<price>要素のテキスト内容を取得して」
  • 「<bookstore>に新しい<book>要素を追加して」

XMLを、生のテキストとして、折りたたみ可能なツリーとして、あるいはスプレッドシートのようなテーブルとして見る様々な方法は、すべてこの同じ基礎となるDOMツリーを視覚的に解釈したものです。

実世界での事例

設定ファイルカオス事件

急成長中のスタートアップには数十のマイクロサービスがあり、それぞれが独自の設定ファイルを持っていました。.propertiesファイルを使うものもあれば、シンプルなJSONを使うもの、誰かが火曜日に作ったカスタムのキー・バリュー形式を使うものもありました。DevOpsチームは髪をかきむしるほどの状態でした。新しいサービスをデプロイするたびに新しい設定ファイルの「方言」を学ぶ必要があり、たった一つのタイポが謎めいたエラーで全てをクラッシュさせる可能性があったのです。

チームは標準化を決意しました。彼らがXMLを選んだのは、流行っていたからではなく、厳格だったからです。彼らはすべての設定ファイルのためのマスターとなるXML Schema Definition(XSD)を作成しました。このスキーマは、必須セクション(<database>、<logging>)、データ型(portは整数でなければならない)、許容値(log_levelはDEBUG、INFO、WARN、ERRORのいずれかでなければならない)などを定義しました。今では、開発者が新しい設定ファイルを書くと、コードエディタが即座に間違いを指摘してくれます。CI/CDパイプラインはデプロイ前にXMLをスキーマに対して検証し、エラーを早期に発見します。

教訓: XMLの厳格さとスキーマ検証は、一貫性が最重要である複雑な設定環境に秩序をもたらすためのスーパーパワーです。

意外な出版界のヒーロー

ある大手出版社が、新しい技術マニュアルを3つの形式でリリースする必要がありました。印刷用の美しいハードカバー、電子書籍リーダー用のリフロー型EPUB、そしてウェブサイト用のHTML版です。従来の方法では、3つの別々のチームが手作業でレイアウトとフォーマットを行っており、時間がかかり、エラーも起きやすいプロセスでした。

彼らはDocBookと呼ばれる方言を使ったXMLベースのワークフローに切り替えました。著者はコンテンツを一度だけ書き、意味的にマークアップします:<chapter>、<section>、<programlisting>、<img>。このマスターXMLファイルには、純粋なコンテンツとその構造のみが含まれ、フォント、色、改ページに関する情報は一切ありません。そして、その単一のソースファイルに対して、自動化された「変換」(XSLTという技術を使用)を実行します。ある変換は印刷版のためにヘッダー、フッター、索引付きのPDFを生成します。別の変換はクリーンなHTMLファイルを生成します。さらに別の変換はEPUBパッケージを生成します。

教訓: XMLはコンテンツとプレゼンテーションを分離するための究極のツールであり、「一度書けば、どこにでも公開できる(write once, publish anywhere)」ワークフローを可能にし、膨大な時間を節約し、すべての出力で一貫性を保証します。

よくある間違いと落とし穴

  • 属性の肥大化: 初心者は複雑なデータを属性に詰め込みがちです。悪い例は<user data="name=John;age=30;city=NYC">のようなものです。これはパースや検証が困難です。経験則:属性は単純で不可分なメタデータに、要素はコンテンツに使いましょう。
  • 単一ルートを忘れる: すべての有効なXMLドキュメントは、ただ一つのトップレベル要素でラップされている必要があります。トップレベルに2つの<book>要素を並べようとするのはNGです。それらは<books>のようなものでラップされなければなりません。
  • 大文字・小文字の区別でハマる: HTMLから来た開発者は、<Name>と</name>がXMLでは致命的なエラーになることを忘れがちです。開始タグと終了タグは完全に一致しなければなりません。
  • 特殊文字をエンコードしない: テキストコンテンツにリテラルな<や&を含める必要がある場合、そのままタイプすることはできません。パースが壊れてしまいます。それらのエンティティ表現を使わなければなりません:&lt;(小なり)、&gt;(大なり)、&amp;(アンパサンド)、&quot;(ダブルクォート)、&apos;(シングルクォート)。
  • 名前空間を無視する: 異なるソースからのXMLを混ぜ始めると(例:XHTMLドキュメント内にSVGを埋め込む)、タグ名の衝突が起こり得ます。XMLはこの問題を名前空間(xmlns)で解決します。これは<svg:path>と<db:path>を区別するためのプレフィックスのように機能します。複雑なトピックですが、これを無視すると大規模なシステムではカオスにつながります。

なぜ知っておくべきなのか

JSONがそのシンプルさとJavaScriptオブジェクトへの直接的なマッピングのおかげで、ほとんどの現代的なWeb APIのデフォルトの選択肢となっていますが、XMLは決して死んでいません。次のような場合には、XMLを使ったり、遭遇したりすることを覚悟しておくべきです。

  • 契約が重要である場合: エンタープライズシステム(特にSOAP APIを使用するシステム)や、厳格なスキーマ定義されたデータ交換の契約が要件となる規制産業(金融、ヘルスケア)で作業している場合。
  • ドキュメントを扱っている場合: データがドキュメントのような構造を持ち、順序が重要で、混合コンテンツ(インラインマークアップ付きのテキストなど)がある場合。技術マニュアル、記事、本などを考えてみてください。
  • 設定を鉄壁にする必要がある場合: Javaアプリケーションサーバー、ビルドツール(Mavenのpom.xmlなど)、または.NETアプリケーションのようなシステムの複雑な設定を管理している場合。
  • ベクターグラフィックスを扱っている場合: ウェブでスケーラブルなベクターグラフィックスに使われるSVGフォーマットは、XMLの方言です。
  • レガシーシステムをサポートする必要がある場合: 世界のエンタープライズインフラの膨大な量がXML上に構築されており、それはすぐになくなることはありません。

XMLはもはや常にイケてる人気者というわけではありませんが、厳格さ、構造、そして誰もが全く同じ言語を話しているという保証が仕事で求められるときに呼び出す、頼れるベテランなのです。

もっと深く知るために

理論はOK。さあ手を動かそう — 100%ブラウザ内で。

ツールを試す: XMLエディター