FlowingDev

XMLの解説:スーツでビシッと決めた、堅物データフォーマット

XML(Extensible Markup Language)は、人間にもコンピュータにも読みやすいフォーマットでドキュメントをエンコードするための、ルールベースの言語です。

ツールを試す: XML ビューア

ひと言でいうと

XMLとは、カスタムタグを使ってデータを構造化する超厳格な方法。人間にもコンピュータにも読めるけど、どっちかと言えばコンピュータ向けだね。

こいつが解決する問題

コンピューティングの黎明期、異なるプログラム間でデータを共有するのはマジで悪夢でした。どの会社も「秘伝のタレ」みたいな独自ファイルフォーマットを持ってたんです。WordPerfectのドキュメントをMicrosoft Wordで開こうとするなんて、ちょっとした冒険でした。これは「ベンダーロックイン」と呼ばれ、もうメチャクチャだったんです。

インターネットブームで、この問題は10倍悪化しました。もはや1台のコンピュータ上の2つのプログラムだけの話じゃなく、世界中の何千もの異なるサーバーとクライアントが会話する必要が出てきたのです。

Webでこの問題を解決しようとする最初の試みがHTML(HyperText Markup Language)でした。HTMLはブラウザに情報をどう表示するかを伝えるのには素晴らしい言語です。これは見出し(<h1>)、これは段落(<p>)、これは太字(<b>)といった具合に。でも、その情報が何であるかを記述するのはからっきしダメなんです。その太字のテキストは製品名? 警告? それとも、ただ太字にしたらカッコいいと思っただけ? コンピュータにはさっぱり分かりません。

そこで90年代後半に登場したのがXML(eXtensible Markup Language)です。これはSGMLという、もっと古くて学術的な標準から派生しましたが、Webスケールで使えるように簡素化されたものでした。「eXtensible(拡張可能)」って部分が、こいつのキモなんです。HTMLの固定タグセットとは違い、XMLでは独自のタグを発明できます。

<p>の代わりに、<product_name>(製品名)、<price>(価格)、<shipping_address>(配送先住所)、あるいは<極秘の火山基地の座標>なんてタグも作れちゃうわけです。

突然、データ自体が意味を持つ形で交換する方法が生まれました。データが自己記述的になったのです。これは企業間取引からアプリケーションの設定ファイルまで、あらゆるものにとって画期的なことでした。ルールに従う限り、どんな2つのシステムでも話せる普遍的な言語が生まれたのです。

舞台裏の仕組み

XMLは山括弧の集まりにしか見えないかもしれませんが、そのトゲトゲした見た目の下には、パワフルで論理的なシステムが隠されています。いくつかのコアな概念の上に成り立っています。

基本構造:タグ、要素、属性

XMLの基本単位は**要素(element)**です。要素は開始タグ、内容、そして終了タグから構成されます。

<book>戦争と平和</book>
  • タグ: <book>が開始タグで、</book>が終了タグです。終了タグのスラッシュ/に注目。これは必須です。
  • 内容: 戦争と平和が要素の内容です。内容は単純なテキストでもいいし、さらに多くの要素でもOK! このネスト構造がXMLに構造を与えます。

要素は**属性(attribute)**を持つこともできます。これは開始タグの中に住む、ちょっとしたメタデータです。

<book language="en">
  <title>War and Peace</title>
  <author>Leo Tolstoy</author>
</book>

ここでlanguage="en"はbook要素の属性です。これは要素の主要な内容の一部というより、要素自体に関する追加情報を提供します。属性を使うか子要素を使うかは、開発者の間では古典的な論争ですが、良い経験則があります。もしそれが内容を説明するものなら要素、もしそれがコンテナ(入れ物)を説明するものなら属性です。

ツリー構造(DOM)

コンピュータがXMLファイルをパースするとき、それはただのテキストの壁を見ているわけではありません。ツリーとして見ています。この論理構造はDocument Object Model、略してDOMと呼ばれます。

家系図のように考えてみてください。

  • 一番上には常に単一のルート要素が1つだけあります(この例では<book>)。XMLドキュメントは2つのルートを持つことはできません。
  • 他のすべての要素はツリー内のノードです。
  • 他の要素の中にある要素は子ノードです(<title>は<book>の子です)。
  • それらを包含する要素は親ノードです(<book>は<title>と<author>の親です)。
  • 同じレベルにある要素は兄弟ノードです(<title>と<author>は兄弟です)。

XMLをツリーとして視覚化することが、それをナビゲートしたりクエリを投げたりする方法を理解する鍵です。パーサーに「book要素の中にあるauthor要素を探して」と頼めば、パーサーはツリーをどうたどればそこにたどり着けるか正確に知っています。

ルール:「整形式」 vs. 「妥当性」

ここが、XMLが厳格だという評判の所以です。「正しさ」には2つのレベルがあります。

1. 整形式(Well-Formed)XML: これは絶対に最低限守るべき要件です。正しい文法みたいなものです。

  • ルート要素は1つ、かつ1つだけでなければならない。
  • すべての開始タグには、対応する終了タグがなければならない。
  • タグは大文字と小文字を区別する:<Book>と<book>は別物。
  • 要素は正しくネストされていなければならない。<b><i>text</i></b>は正しいが、<b><i>text</b></i>は大惨事。
  • 属性値は引用符("か')で囲まなければならない。

XMLドキュメントが整形式でない場合、どんなパーサーも即座にエラーを吐き出し、それ以上は一切処理してくれません。例外はありません。

2. 妥当な(Valid)XML: これは次のレベルです。XMLドキュメントが「妥当」であるとは、整形式であり、かつスキーマと呼ばれる事前に定義された一連のルールに準拠している場合を指します。

スキーマは設計図や契約書みたいなものです。これは別のファイル(通常は.xsdや.dtd)で、次のようなことを定義します。

  • どの要素が許可されているか?
  • それらはどの順番で現れなければならないか?
  • どの要素が必須で、どれが任意か?
  • 要素はどんな属性を持つことができるか?
  • 要素の内容は数値、文字列、それとも日付であるべきか?

例えば、我々の本の例のスキーマはこう言うかもしれません:「すべての<book>要素は、1つの<title>と少なくとも1つの<author>を必ず持たなければならない。language属性を持ってもよい。<price>要素が存在する場合、それは必ず正の数を含まなければならない。」

これこそがXMLの真骨頂です。これにより、2つのシステム(例えば買い手と売り手)が厳格なデータ契約に合意できます。契約に違反するデータは自動的に拒否され、数え切れないほどのバグや誤解を防ぐことができるのです。

実世界でのストーリー

失敗が許されない銀行API

ある大手銀行が、大口の法人顧客が支払い指示を自動的に送信するためのシステムを構築していました。取引あたり数百万ドルという規模です。エラーの余地はゼロ。通貨記号の欠落や小数点の位置ズレは大惨事になりかねません。チームは厳格なXMLスキーマ定義(XSD)を持つXMLを選択しました。支払い指示がコアバンキングシステムによって見られる前に、まずスキーマに対して検証されました。もしクライアントが<amount>100000.00</amount>の代わりに<amount>100,000</amount>と送ったり、<currency>USD</currency>の代わりに<currency>usd</currency>と送ったりしたら、APIはスキーマ違反を指摘する明確なエラーとともに即座にそれを拒否しました。 教訓: 曖昧さが破滅的なコストにつながるミッションクリティカルなデータ交換において、検証済みXMLドキュメントの厳格さはバグではなく、仕様(フィーチャー)なのです。

ただのテキストだったベクター画像

あるWeb開発者が、新しいサイトのために複雑なロゴを必要としていました。デザイナーが.svgファイルを送ってきました。好奇心旺盛な開発者はそのファイルをテキストエディタで開いて、それがピクセルのバイナリ塊ではないことに驚きました。それはXMLだったのです! <svg>、<path>、<circle>のようなタグが形、色、座標を記述していました。彼は、グラフィックソフトを一切開かずに、XMLの属性値を探して置換するだけでプログラム的にロゴの色を変更できることに気づきました。彼はさらに、JavaScriptでXMLノードを操作してアニメーションまでさせたのです。 教訓: SVG(スケーラブル・ベクター・グラフィックス)のように、あなたが日常的に使う多くの強力なファイルフォーマットは、実はXMLの特定の方言であり、調査、編集、そしてスクリプトによる操作が可能になっています。

いにしえの巨大設定ファイル

あるジュニア開発者が、15年前のエンタープライズJavaアプリケーションのバグ修正を任されました。問題の原因は設定のどこかにありました。恐怖に震えながら彼が見たのは、単純なテキストファイルではなく、config.xmlという名の、25,000行にも及ぶ単一のXMLファイルでした。それはごちゃごちゃでインデントもないめちゃくちゃな代物。読むのは不可能でした。しかし、それをXMLビューアに読み込ませてみると、ツールは即座にそれをフォーマットし、色分けを追加し、ツリーの巨大なセクションを折りたためるようにしてくれました。彼は関連するセクション(<databaseConnectionPool>)を検索し、関連する設定のブランチ全体を見て、サーバー名のタイポを即座に発見することができました。 教訓: XMLは brutally verbose(残酷なほど冗長)になりがちですが、適切なツールで見れば、その固有のツリー構造は、最も怪物的に複雑なファイルでさえ管理可能にしてくれます。

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

  • HTMLとごっちゃにすること。 見た目はイトコ同士のようですが、仕事が違います。HTMLはプレゼンテーション(どう見えるか)のため。XMLはデータ記述(それが何か)のため。ブラウザは雑なHTMLを許してくれますが、XMLパーサーは雑なXMLを許してはくれません。
  • 属性 vs. 要素の悩み。 初心者は、あるデータを属性(<book isbn="123">)にすべきか、子要素(<book><isbn>123</isbn></book>)にすべきかでよく悩みます。唯一の正解はありませんが、一般的なガイドラインとして、要素は内容を保持し、属性はその内容に関するメタデータを保持する、というものがあります。あまり悩みすぎず、でも一貫性は保つことが大事です。
  • 正規表現でパースしようとすること。 やめて。お願いだからやめて。単純なケースでは魅力的に見えるかもしれませんが、XMLはネストされた再帰的な構造なので、単純な正規表現は些細でないファイルでは見事に失敗します。これはプログラミング界の古典的なホラーストーリーです。必ず、お使いの言語に適したちゃんとしたXMLパーサーライブラリを使いましょう。
  • 大文字と小文字を区別することを忘れる。 スキーマが<name>を期待しているのに<Name>を送ると、検証エラーになります。これは、もっと緩いフォーマットから来た開発者がハマるポイントです。
  • 名前空間を無視する。 異なる語彙を混ぜる(例えばSVGとXSLTを混ぜる)大規模なXMLドキュメントでは、<xsl:template>や<svg:path>のようなタグを見かけるでしょう。このxsl:の部分は名前空間で、両方の語彙に<template>という名前のタグがあった場合の衝突を防ぎます。頭痛のタネになることもありますが、複雑なドキュメントには不可欠です。

なぜ知っておくべきか

新しいプロジェクトで、シンプルなAPIのためにXMLを第一候補に選ぶことはないかもしれません(簡潔さの面ではたいていJSONに軍配が上がります)。しかし、XMLには絶対にどこかで出くわします。これは保証します。次のようなときにXMLのことを思い出すべきです。

  • 古いエンタープライズシステム、特にSOAPやWSDLを使用しているものと統合するとき。
  • 二者間で堅牢で破られないデータ契約を定義する必要があるとき(XSDを使用)。
  • RSS/Atomフィード、Officeドキュメント(OOXML)、ベクターグラフィックス(SVG)など、ドキュメント中心のデータを扱うとき。
  • Javaエコシステム(MavenやAntなど)や.NETでツールを設定するとき。
  • .xml、.svg、.rss、.atom、.plistで終わるファイルを受け取り、その内容だけでなく構造を理解する必要があるとき。

XMLの基本を知っていることは、キャブレターの仕組みを知っているようなものです。あなたは現代の燃料噴射式の車を運転しているかもしれませんが、その知識はエンジンについてより深い理解を与え、古いクラシックカーを前にしたとき、はるかに腕のいい整備士にしてくれます。

もっと深く

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

ツールを試す: XML ビューア