レベル: 中級 Martin Brown, Freelance Writer, Consultant
2008年 5月 13日 XML の作業を容易にするために、この記事で紹介する 10 項目のヒントを活用しましょう。これらのヒントを学ぶことによって、最終的に誤りが減り、生産性を高めることができます。
はじめに
XML、そして XML によって実現される柔軟性と相互運用性を好ましいと思う人は多いと思いますが、XML や XML 用のツールを扱う際には、いくつかのことを実行することで作業を非常に容易にすることができます。また XML を扱う際の適切な基本的習慣を身につけると、XML によるドキュメントやアプリケーションを非常に効率よく使用できるようになります。
10 項目の適切な習慣を身につける
 |
頻繁に使用する頭字語
- DOM: Document Object Model
- DTD: Document Type Definition
- HTML: Hypertext Markup Language
- IDE: Integrated Development Environment
- SAX: Simple API for XML
- XSD: XML Schema Definition
- XML: Extensible Markup Language
- XSLT: Extensible Stylesheet Language Transformations
|
|
XML を使用する際の適切な習慣の上位 10 項目は次のとおりです。
-
XML とエンコーディングを定義する
-
DTD または XSD を使う
-
妥当性検査を忘れずに行う
-
妥当性検査をすればよいというわけではない
-
XML の構造と属性
-
XPath を使って情報を発見する
-
情報の抽出にパーサーが必要とは限らない
-
どういう場合に DOM ではなく SAX を使って構文解析するのか
-
どういう場合に SAX ではなく DOM を使って構文解析するのか
-
適切な XML エディターを使用する
XML とエンコーディングを定義する
急いで XML 文書を作成する場合には、基本的な構造のみを作成してしまい、XML 文書に関する通常の要求 (つまり XML 宣言の指定や、その文書に含まれるデータのエンコーディング・タイプの指定が必要という要求) を避けたくなるものです。
リスト 1 に示す XML 文書を考えてみてください。
リスト 1. XML 宣言とデータのエンコーディング・タイプが指定されていない XML 文書
<phrases>
<phrase lang="en">Hello</phrase>
<phrase lang="it">Buongiorno</phrase>
<phrase lang="fr">Salut!</phrase>
</phrases>
|
この文書を人間が見て、XML であると判断することはできますが、同じ判断をコンピューターが行うことは非常に困難です。この XML であると判断するプロセスをもっと明確で、判断しやすくするためには、このファイルの先頭に XML 宣言を追加します。この宣言は 1 行であり、この 1 行の中で、この文書が XML であることを指定し、またこの XML データの中で使われるバージョン番号と文字エンコーディングを記述します。例えば次のようにします。
<?xml version="1.0" encoding="us-ascii"?> |
また、エンコーディング仕様の内容は正確でなければなりません。XML パーサーはこのエンコーディングを使用して、個々の文字を XML 文書から適切にロードします。例えばリスト 1 の phrase ベースの例を再度使用して説明すると、この文書の中にロシア語のエントリーを追加すると問題が起こります。なぜなら、現在指定されているエンコーディングは hello に相当するロシア語の表現に必要な拡張文字セットをサポートしていないからです。
誤ったエンコーディングを指定するということは、パーサーはその文書を不適切に処理する可能性があるということです。例えばマルチバイトの拡張文字を単なる個々のバイトのシーケンスとして読み取ると、データが破損し、出力が不適切になる可能性があります。
DTD または XSD を使う
XML 宣言を行ったら、次は DTD または XSD を使って XML ファイルに妥当な構造が確実に定義されるようにします。どちらのソリューションを使用した場合にも、XML パーサーを使うことによって、その XML ファイルの内容がモデリング対象のデータにとって妥当な構造となっているかどうかを確認することができます。
例えば連絡先のデータベースのための簡単な XML 構造があったとすると、連絡先の名前と住所、電話番号を指定できるような構造を定義する必要があります。DTD を使用するということは、そうした構造を緻密に計画するということであり、その構造内に各連絡先がきちんと配置されていることを確認するということです。
例えば、リスト 2 は連絡先のデータベースのための DTD を示しています。
リスト 2. 連絡先のデータベースのための DTD
<!ELEMENT phone (#PCDATA)>
<!ATTLIST phone type (home | work | mobile) #REQUIRED>
<!ELEMENT contact (#PCDATA | name | phone | address)*>
<!ELEMENT contacts (#PCDATA | contact)*>
<!ELEMENT country (#PCDATA)>
<!ELEMENT road (#PCDATA)>
<!ELEMENT address (#PCDATA | road | city | state | postcode | country)*>
<!ATTLIST address type (home | work) #REQUIRED>
<!ELEMENT state (#PCDATA)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT postcode (#PCDATA)>
<!ELEMENT city (#PCDATA)>
|
この DTD は、ある連絡先を記述するために必要な要素と属性 (そしてこれらの属性がサポートしている値) を定義しています。例えばリスト 2 を見ると、phone 要素には type 属性があること、また address 要素には属性があり、address 要素内に下位要素があることがわかります。
DTD を使うことによって、構造が妥当であることが保証され、また妥当性検査プロセスと組み合わせることで問題を特定することができます。また DTD を XML 対応のエディターと合わせて使用すると、内容の編集と自動補完にも DTD を活用することもできます。
XSD またはスキーマの機能の多くは DTD と同じですが、XSD は DTD とは別の面で役立ちます。例えば、一部の XML エディターは内容を自動補完するために DTD を必要としますが、文書の実際の階層構造を設計する際にはスキーマの方が高い柔軟性を発揮します。どちらのツールを選択するかは、そのツールが使用される状況に依存します。
妥当性検査を忘れずに行う
リスト 3 を見て、どこに問題があるか、おわかりでしょうか。
リスト 3. 妥当性検査の例
<contacts>
<contact>
<name>Martin</name>
<phone type="home">123 456 7890</phone>
<phone type="mobile">123 456 7890</phone>
<phone type="work">123 456 7890</phone>
<address type="home">
<road>Home road</road>
<city>Home city</city>
<state>Home state</state>
<zipcode>12434</zipcode>
<country>USA</country>
</address>
</contact>
<contact>
<name>Sharon</name>
<phone type="work">234 567 8901</phone>
<phone>234 567 8901</phone>
<address type="home">
<road>Other home road</road>
<city>Other city</city>
<state>Other state</state>
<zipcode>39487</zipcode>
<country>USA</country>
</address>
<address type="work>
<road>Work building, work road</road>
<city>Work city</city>
<state>Work state</state>
<zipcode>12347</zipcode>
<country>USA</country>
</address>
</contact>
</contacts>
|
問題を目で探して見つけようとすると面倒です。しかし、XML ファイルの内容と構造の妥当性を検査する無料のツールである xmllint を使ってこのファイルを実行すると、リスト 4 のような出力が表示されます。
リスト 4. xmllint を使ってリスト 3 を実行した後の出力
$ xmllint contacts.xml
contacts.xml:27: parser error : Unescaped '<' not allowed in attributes values
<road>Work building, work road</road>
^
contacts.xml:27: parser error : attributes construct error
<road>Work building, work road</road>
^
contacts.xml:27: parser error : Couldn't find end of Start Tag address line 26
<road>Work building, work road</road>
^
contacts.xml:32: parser error : Opening and ending tag mismatch: contact line 15
and address
</address>
^
contacts.xml:33: parser error : Opening and ending tag mismatch: contacts line 1
and contact
</contact>
^
contacts.xml:34: parser error : Extra content at the end of the document
</contacts>
|
上記出力を見ると、元々の問題 (属性の 1 つが閉じられていません) に比べて非常に複雑に見えますが、それでもどこから手をつければよいかがわかります。
この xmllint は、診断の方法と結果を選択するための何種類かのコマンドライン・オプションをサポートしています。そのうち最も便利なオプションの 1 つは --noout オプションです。このオプションを指定すると、ファイルを構文解析する際に xmllint がその解析対象ファイルの内容を出力しないようにすることができます。短いファイルの場合には、解析対象ファイルの内容が出力されても問題になりませんが、長いファイルの場合には問題になることがあります。
DTD を使用している場合には、--postvalid オプションを使うと、内容の妥当性検査をその DTD に対して行うように xmllint に指示することができ、それによってその内容が妥当な XML であることを保証できるだけでなく、DTD の構造にも一致していることも保証することができます。「DTD または XSD を使う」の中で contacts ファイルに対して生成した DTD を contacts ファイルに追加し、さらに属性定義のエラーを修正すると、今度は別のエラーが生成されます (リスト 5)。
リスト 5. xmllint が別のエラーを発見する
$ xmllint --noout --postvalid contacts.xml
contacts.xml:9: element address: validity error : Element zipcode is not declared
in address list of possible children
contacts.xml:21: element address: validity error : Element zipcode is not declared
in address list of possible children
contacts.xml:28: element address: validity error : Element zipcode is not declared
in address list of possible children
Document contacts.xml does not validate
|
このように xmllint を使用することで、文書の構造が妥当であることを素早く手軽に確認することができます。xmllint は libxml2 ツールキットに含まれており、libxml2 は Linux、UNIX®、Mac OS X にはバンドルされています。Windows® の場合は別途ダウンロードする必要があります。xmllint と libxml2 の詳細については「参考文献」を参照してください。
妥当性検査をすればよいというわけではない
XML ファイルの妥当性を検査するために xmllint や類似のツールを使う方法は、特に DTD を使用している場合には、素晴らしい方法です。しかしこのソリューションには限界があります。例えば、XML ファイルの内容に関して検査をするにはどうすればよいのでしょう。
DTD または XSD を利用すると、属性の内容を明示的に指定することができます。属性のストリングまたは ID が一定の選択肢の範囲内であるようにすることはできますが、同じ方法で要素の内容を制御したり制限したりすることはできません。
例えば連絡先の例では、電話番号要素は番号と空白を含んでいます。しかしその要素にユーザーがアルファベットの文字を追加することを禁止することはできません。ユーザーがそうした追加を行っても xmllint を使った妥当性検査では、エラーは検出できません。エディターや他の XML 対応ソリューションでも、そうした問題への対応や、問題の識別はできません。標準ではないデータ型をアプリケーションが認識することによってアプリケーションがエラーを起こし、それによってようやく問題がわかる、という事態になるかもしれません。
要するに、XML の妥当性検査では、構造が適切であることのみを確認するのであり、データが適切であるかどうかを確認するわけではないのです。
この問題に対処する最も簡単な方法は、XML ファイルを読み取ってデータの内容を実際に検証するパーサーを作成することです。ただし内容の検証を過剰に行う必要はなく、そのデータがアプリケーションの要求を満たしていることを確認できれば十分です。
XML の構造と属性
XML ファイルの中で表現したい情報を記述するために、属性と要素のどちらを使った方がよいかについて、意見は分かれています。
一般的なルールとして、ファイルの中に含まれる情報を定義するためには要素 (つまりタグで囲まれたデータ) を使う必要があります。属性を使う必要があるのは、記述したいデータをさらに細かく分類する場合です。
要素にも属性にも制約があります。例えば属性をタグの中で繰り返すことはできませんが、これは属性よりも要素の方が適切な場合の典型的な例です。要素は、このように繰り返される情報をサポートできるため、非常に実用的です。対照的に、データを分類するために要素を使うと処理が複雑になりすぎることがあります。
連絡先の例での電話番号は属性の利点を説明するための好例です。連絡先の例 (リスト 6 に示してあります) では、電話番号の種類 (work (職場) や home (自宅)、mobile (携帯) など) で分類するために属性が使われています。
リスト 6. 電話番号の種類で分類する
<phone type="home">123 456 7890</phone>
<phone type="mobile">123 456 7890</phone>
<phone type="work">123 456 7890</phone>
|
この構造であれば、(属性を無視することで) すべての電話番号を抽出することや、(属性を参照することで) 特定の種類の電話番号のみを抽出することが容易にできます。
この構造を、要素のみを使って設計された構造 (リスト 7) と比較してみてください。
リスト 7. 要素を使用して電話番号を分類する
<phone>
<type>home</type>
<number>123 456 7890</number>
</phone>
<phone>
<type>mobile</type>
<number>123 456 7890</number>
</phone>
<phone>
<type>work</type>
<number>123 456 7890</number>
</phone>
|
これでは森の中で目的の木を探すのは困難です。理論的には、XML パーサーを使ったり、あるいは適切な XPath 定義を使ったりすれば、必要な情報を抽出できるはずですが、実際にはほとんど情報を得ることはできず、しかも XML 文書は読みにくくなってしまいます。
XPath を使って情報を発見する
XML データを扱う際に、必要な情報を発見する作業は複雑です。もちろん、必要な素材を抽出するパーサーを作成することはできますが、場合によると、ファイルの中にある小さな情報のフラグメントをとにかく大至急発見したい、ということがあります。
例えば、連絡先 XML ファイルの中にあるすべての国のリストを抽出し、連絡先の範囲がどれほど広がっているかを調べたい場合であれば、XPath を使って情報を抽出することができます。
XPath を利用すると、XML ファイルの構造をクエリーの一部として使うことによって、その XML ファイルからデータを抽出することができます。例えば特定の要素のデータを抽出する場合には、以下のように XML ファイル内でのその要素へのパスを指定します。
$ xpath contacts.xml '//contact/address/country' |
この内容は次のように分解することができます。
- 最初のダブル・スラッシュ (//) は、指定された要素 (contact) を発見するために文書内のすべての場所を検索するように指定しています。
- その次のスラッシュと要素名は、次の抽出対象要素 (address) を指定しています。つまり contact 要素の中にある address 要素を探します。
- 最後のスラッシュは、その同じプロセスを繰り返し、今度は country を抽出します。
この例では、情報の選択元として address という種類を指定しているので、すべての address が抽出されることに注意してください。この XPath クエリーの結果はリスト 8 のようになります。
リスト 8. XPath クエリーの結果
$ xpath contacts.xml '//contact/address/country'
Found 3 nodes:
-- NODE --
<country>USA</country>-- NODE --
<country>USA</country>-- NODE --
<country>USA</country>
|
さらに絞り込んだデータを抽出したい場合には、要素の内容や属性の内容を突き合わせの対象として指定します。例えば携帯電話の番号のみを選択したい場合には、その属性の種類と値を指定する必要があります。そのためには @ 記号を使います。@ は属性を検索することを表しており、@ を使って突き合わせを行うための値を指定します (リスト 9)。
リスト 9. 携帯電話の番号のみを選択する
$ xpath contacts.xml '//contact/phone[@type="mobile"]'
Found 1 nodes:
-- NODE --
<phone type="mobile">123 456 7890</phone>
|
リスト 8 と 9 はコマンドライン・ツールを使っています。多くの XML ツールキットには XPath 要素を扱うための固有の方法が用意されており、情報を得るためにパーサーを使わなくても、アプリケーションの中で直接 XPath 仕様を使うことでデータを抽出することができます。
情報の抽出にパーサーが必要とは限らない
直感には反するかもしれませんが、必要な情報を XML ファイルから抽出ためには、必ずしも SAX や DOM、あるいは XPath や XQuery など他の手法を使用する完全な XML パーサーは必要ありません。
XML ファイルには構造化されたフォーマットのデータが含まれており、その構造化フォーマットで情報を利用したいこともありますが、ちょっとした情報を素早く検索したい時には、もっと簡単なソリューションの方が適切な場合がよくあります。
文書の構造あるいは内容を XML ファイルとして実際に構文解析しなくても、単純に grep や Perl、あるいはそれらに似た何かを使って必要なデータを抽出できることが多いものです。
例えば、grep を使って電話番号を抽出することができます (リスト 10)。
リスト 10. grep を使って電話番号を抽出する
$ grep '<phone' contacts.xml
<phone type="home">123 456 7890</phone>
<phone type="mobile">123 456 7890</phone>
<phone type="work">123 456 7890</phone>
<phone type="work">234 567 8901</phone>
<phone>234 567 8901</phone>
|
これで必要な情報を抽出することができ、これが XML であるという事実や XML の構造を気にせずにすんだのです。
とにかくすぐに情報を必要とする場合には、単純な処理方法でも十分であり、それによって通常の構文解析ソリューションに関わるオーバーヘッドを回避することができます。
どういう場合に DOM ではなく SAX を使って構文解析するのか
必要な情報を抽出するために文書を構文解析するパーサーを作成する場合には、どういう時に SAX を使ったプロセッサーを使い、どういう時に DOM を使ったプロセッサーを使うのかの判断が難しいことがよくあるものです。
これを最も容易に判断するための方法は、その文書の複雑さと、その文書の情報を使って何をしたいのかの両方を考慮することです。文書を変換する場合、あるいは文書が特に大規模な場合には、SAX が最善の選択肢です。
SAX は要素ごとに文書を構文解析し、要素が識別されると、呼び出しが必要なメソッドまたは関数を起動します。XML 文書を別のフォーマットに変換する場合には、例えば XML を HTML に変換する場合には、SAX が最も効率的な方法です。メモリーの中に文書全体をロードする必要がなく、識別された要素や構造に単純に対応すればよいからです。
SAX の欠点が問題になるのは、構造の保存や記録が必要な場合、あるいは文書全体を理解してから個々の要素をその文書から抽出する必要がある場合 (例えば文書全体の中から 1 つの連絡先を選択するような場合) です。そうしたことをするためには、その XML をロードし、構造を持つように XML のデータを記録し、そして要素を識別して出力ターゲットに出力できるようにするという、複雑なプロセスを作成する必要があります。
どういう場合に SAX ではなく DOM を使って構文解析するのか
DOM の処理では、文書全体とその文書の構造をメモリーにロードするので、アプリケーションの中で XML 文書の構造を参照したり使用したりすることができます。例えば連絡先の例では、連絡先のデータベース全体をメモリーに読み込み、連絡先全体に対して繰り返し処理を行い、さらにその各連絡先の中の各電話番号に対して繰り返し処理を行うことで、すべての電話番号を選択することができます。
DOM は構造を保持するのに加え、もっと重要な点として、構造を理解して扱うことができるため、構造全体を扱うのも、個々の構造を扱うのも容易な作業です。同じく連絡先の例を使うと、SAX を使って新しい連絡先を挿入しようとすると複雑になりますが、DOM を使えば、新しい連絡先を表す新しい XML 要素を既存の XML 文書の中に挿入するだけで済むのです。
DOM の限界は、ファイルをストリームで処理する場合 (例えば HTML に変換する場合) には複雑になってしまうことです。これは構造の中にある各要素に対して個別に繰り返し処理を行うことで文書を処理する必要があるためです。
さらに、DOM は構文解析中に XML 文書全体をメモリーにロードするため、DOM パーサーは動作が遅く、そして当然ながら多くのメモリーを必要とします。ただし DOM プロセスには、この点に関して少し利点があります。例えば、1 回構文解析をすれば、DOM を何度でも使って、構文解析をした XML 文書を処理することができます。SAX を使って同じ結果を得るためには、構文解析を何度も繰り返さなければなりません。
DOM と SAX の使い方の詳細と例については「参考文献」を参照してください。
適切な XML エディターを使用する
定常的に XML を作成し、使用するのであれば、適切な XML エディターが必須です。XML エディターは XML の構造を理解できるため、標準的なテキスト・エディターとは異なります。XML エディターは XML を扱う作業を支援するために非常にさまざまな機能を提供しています。そうした機能には次のようなものがあります。
- 補完機能—終了要素用の文字の入力を始めると、XML エディターが残りを入力して完成させてくれます。
- 内容の補完機能—DTD を持つ XML ファイルを使用している場合には、XML エディターがその XML ファイルの内容のさまざまな部分に入力し、またフォーマットしてくれます。例えば連絡先の DTD の場合には、phone 要素の type 属性は必須要素でした。インテリジェントな XML エディターを使うと、phone タグを作成する際に、(空の値を持つ) 属性がテキストの中に自動的に追加されます。
- インライン・フォーマット機能—エディターによって XML が読みやすく、理解しやすくなります。この動作は編集の最中にライブで行われることもあれば、あるいは別のフォーマット・コマンドを使って行うこともできます。最終的な結果として、理解しやすく、要素を特定しやすい XML が得られます。
- 組み込みの妥当性検査機能—エディターはユーザーが入力を行う間に XML 文書の妥当性を検査してエラーを検出し、さまざまな問題をエディターの中で強調してくれるため、ユーザーは何を修正すればよいのかを容易に知ることができます。
- 組み込みの変換機能—一部の XML エディターには、XPath や XQuery、また場合によると XSLT やその他の変換機能へのインターフェースが含まれているため、編集環境の中で変換の結果を調べることができます。
- 学習機能と操作機能—場合によると、DTD よりも前に XML の構造を作成することがあります。こうした場合、エディターがその XML ファイルを読み取り、その文書の構造を学習し、そして DTD を作成し、妥当性検査してくれるため、時間とエネルギーを大幅に節約することができます。
優れた XML エディターの例には Eclipse や oXygenXML がありますが、他にも選択肢は豊富にあります。
まとめ
XML に関する適切な習慣を学ぶことによって、XML によって提供される機能を利用する際にも、また妥当性検査と構文解析の基本を適切に行うために XML の標準を相手に苦労する上でも、大きな違いが生まれます。XML の文書とデータを扱う際の効果と効率を高めるための適切な 10 項目の習慣を身につける上で、この記事は大いに役立つはずです。
参考文献 学ぶために
- 「The Java XPath API」(Elliote Rusty Harold 著、developerWorks、2007年6月) を読み、XML 文書の情報をナビゲートし、また選択するための XML 技術である XPath について学んでください。
- 「Understanding DOM」(Nicholas Chase 著、developerWorks、2007年3月) では DOM (Document Object Model) と DOM 文書の構造を適確に紹介し、また Java 技術を使って XML ファイルから文書を作成する方法やその文書の変更方法、そして出力を取得する方法も説明しています。
- 「Understanding SAX」(Nicholas Chase 著、developerWorks、2003年7月) では、DOM に代わる、SAX (Simple API for XML) として知られる方法について学ぶことができます。SAX では文書を読み込みながらその文書を処理することができるため、文書のすべてが保存されるのを待ってから作業を行う必要がありません。
- 「Introduction to XML」(Doug Tidwell 著、developerWorks、2002年8月) は XML の基本を理解するのに適した典型的なチュートリアルです。
- XML および関連技術において IBM 認定技術者になる方法については、IBM XML certification を参照してください。
- developerWorks の XML ゾーンは XML の技術ライブラリーとして、広範な話題を網羅した技術記事やヒント、チュートリアル、技術標準、IBM Redbooks などを用意しています。
-
developerWorks technical events and webcasts で最新情報を入手してください。
-
テクノロジー・ブックストアには、この記事や他の技術的な話題に関する本が豊富に取り揃えられています。
-
developerWorks
podcasts では、ソフトウェア開発者のための興味深いインタビューや議論を聞くことができます。
製品や技術を入手するために
- Gnome プロジェクト用に開発された xmllint ツールであり、XML C パーサーであり、そしてツールキットでもある libxml2 を入手してください。libxml2 は Linux と UNIX、そして Mac OS X に同梱されています。Windows 用には別にダウンロードする必要があります。
- XML 文書の作成、妥当性検査、そして処理のためのリッチな環境を持つ XML エディターである、oXygenXML を入手してください。
- よく使われる開発プラットフォームである Eclipse IDE を入手してください。Eclipse IDE には、XML 処理用に開発されるアプリケーションを扱うために設計された XML 編集機能が含まれています。
- developerWorks から直接ダウンロードできる IBM trial software を利用して皆さんの次期プロジェクトを構築してください。これらの試用版には DB2® や Lotus®、Rational®、Tivoli®、WebSphere® などが提供するアプリケーション開発ツールやミドルウェア製品が含まれています。
議論するために
著者について  | 
|  | Martin Brown は過去 8 年以上プロのライターとして活躍してきました。彼はさまざまな話題に関して数多くの本や記事を執筆しています。専門領域は広く、無数の開発言語やプラットフォーム (Perl、Python、Java、JavaScript、Basic、Pascal、Modula-2、C、C++、Rebol、Gawk、Shellscript、Windows、Solaris、Linux、BeOS、Mac OS/X その他) から、Web プログラミング、システム管理やシステム統合にまでわたります。彼は ServerWatch.com と LinuxToday.com、そして IBM developerWorks に頻繁に寄稿しており、また Computerworld や The Apple Blog などのサイトの他、Microsoftの SME (Subject Matter Expert) にもブロガーとして頻繁に寄稿しています。彼の連絡先は、彼の Web サイトhttp://www.mcslp.com です。 |
記事の評価
|