前回は,はてなダイアリーからエクスポートしたXML文書を題材にしてXMLの基本構文を学習しました。今回は,この基本構文がどのように解析されるのかを見ていきましょう。

◇XMLパーサー(XMLプロセッサ)

 XML1.0で定められた文法に従ってXML文書を解析するソフトウエアを,XMLパーサー(またはXMLプロセッサ)と言います。XMLパーサーは,市販されているものからフリーのものまで様々なものが入手可能です。また,IE(Internet Explorer)などのWebブラウザもXMLパーサーの機能を持っていますので,XMLの文法はWebブラウザで確認することも可能です。

 XMLパーサーは,XML文書を読み込み先頭から順番に解析(パース)していきます。XML1.0の文法どおりでない文書の場合には,通常エラーメッセージを出力します。うまく解析できた場合には,解析したXML文書を表示するものや,ただ単に解析の終了を知らせたりするものなど,様々な仕様のものがあります。

 XMLパーサーによって正しい文法であることが判明したとしても,必ずしも「意図したXML文書」として解析されたとは限りませんので,注意が必要です。例えば,日記に「a要素は開始タグ<a>と終了タグ</a>の間に要素の内容が記述されます」という内容を記載したケースを考えてみましょう。日記に単純にbodyタグを付けると下記のようになります。

<body> a要素は開始タグ<a>と終了タグ</a>の間に要素の内容が記述されます</body>

 このbody要素は,文法的には全く問題ありません。しかし,正しく日記の内容をマークアップできていません。XMLパーサーは「<」という記号をタグの始まりの文字と解釈するため,「<a>と終了タグ</a>」を日記の内容ではなく,body要素の子要素(a要素)とみなしてしまうからです。

◇定義済み実体参照

 この日記を実際に,はてなダイアリーでエクスポートしてみると,次のようなデータが出力されます。

<?xml version="1.0" encoding="UTF-8"?>
<diary>
<day date="2006-08-30" title="a要素">
<body>
a要素は開始タグ&lt;a&gt;と終了タグ&lt;/a&gt;の間に要素の内容が記述されます
</body>
</day>
</diary>

 日記内の「<」がタグの始まりとみなされないよう,body要素の内容の中にある「<」は「&lt;」,「>」は「&gt;」に置き換えて記述されています。この「&lt;」「&gt;」などを定義済み実体参照と呼びます。このように「<」をタグの開始としてではなく,文字データとしてXMLパーサーに認識させたいときには,定義済み実体参照を利用することができます。ただし,定義済み実体参照は要素名や属性名の中では使用できません。

 定義済み実体参照には次のようなものがあります(表1)。

表1●定義済み実体参照の例
文字 定義済み実体参照
< &lt;
> &gt;
& &amp;
" &quot;
' &apos;

 では確認問題です。

確認問題1
次の中から正しい文法のXML文書を選択してください。

(a)
<数式>xy<4/(X+Y)</数式>

(b)
<&lt;>data</&lt;>

(c)
<product parts="abc&amp;6">HTF058</product>

(d)
<product parts&lt;="abc6">HTF058</product>

 正解は(c)です。(a)は数式内の不等号「<」がタグの開始とみなされてしまいます。定義済み実体参照は要素名の中では使用できませんので,(b)も正しくありません。(c)は,定義済み実体参照「&amp;」により,partsの値が「abc&6」となります。(d)は,定義済み実体参照を属性名の中で使用しているので,正しくありません。

◇CDATAセクション

 CDATAセクション(<![CDATA[文字データ]]>)を使うことによって,文字データとして解釈させることもできます。次のように文字データとして取り扱いたい部分をCDATAセクションで囲みます。

<body>
<![CDATA[a要素は開始タグ<a>と終了タグ</a>の間に要素の内容が記述されます]]>
</body>

 これにより<a>と</a>はタグとしてではなく,文字データとして解釈されます。また,タグの開始が記載されておらず,「>」が単独で記載されている場合も,「>」は文字データとみなされます。

確認問題2
次のXML文書のうち,XMLパーサーに読み込まれたら他の3つと異なる文書構造とみなされるXML文書を選択してください。

(a)
<data> <![CDATA[<a></a>]]></data>

(b)
<data>&lt;a&gt;&lt;/a&gt;</data>

(c)
<data>&lt;a>&lt;/a></data>

(d)
<data> <a></a></data>

 正解は(d)です。(a)は,CDATAセクション内が文字データとみなされますので,ルート要素data(要素の内容は<a></a>という文字データ)のみが要素となります。(b)も,定義済み実体参照の定義により「<」「>」は文字データとして扱われますので,(a)と同じくルート要素data(要素の内容は<a></a>という文字データ)のみが要素になります。(c)は,タグの開始が記載されていない中で「>」が単独で記載されていますので,「>」は単なる文字データとみなされます。従って(a)や(b)と同じく,ルート要素dataのみが要素となります。(d)は,<a></a>が,data要素の子要素とみなされます。このため,(d)のみが他の3つと異なる文書構造とみなされます。

◇XMLパーサーの解析手順

 W3Cが勧告したXML1.0の文法に合致しているXML文書を整形式XML文書,さらにあらかじめ定義されているXMLの文書構造と合致しているXML文書を妥当なXML文書と呼びます。これまで解説してきたXMLの基本構文は,すべてW3Cが勧告したXML1.0の文法に則っています。

 XMLパーサーには,単なる文法だけでなく,構造チェックまで行うものもあります。構造チェックまで行うXMLパーサーはまず,そのXML文書が整形式XML文書かどうかを確認し,次に妥当なXML文書かどうかを確認します。

確認問題3
次の中から整形式XML文書を選択してください。

(a)
<納期 顧客="c01" 顧客="c02">2007/12/12</納期>

(b)
<顧客 No="c001 ">
<納期>2007/12/12</納期>
</顧客>
<顧客 No="c002 ">
<納期>2007/12/12</納期>
</顧客>

(c)
<受注伝票>
<顧客 納期="2007/12/12">c001</顧客>
<顧客 納期="2007/12/12">c002</顧客>
</受注伝票>


(d)
<受注伝票><![CDATA[
<顧客 納期="2007/12/12">c001</顧客>
<顧客 納期="2007/12/12">c002</顧客>
</受注伝票>]]>

 正解は(c)です。(a)は,1つの要素に同じ名前の属性を複数指定しているので,整形式XML文書ではありません。(b)は,ルート要素(顧客要素)が2個あります。ルート要素は必ず1個である必要がありますので,(b)も整形式XML文書ではありません。(c)は,整形式XML文書です。(d)は,受注伝票の終了タグがCDATAセクションにより単なる文字データとみなされてしまいます。このため,整形式XML文書ではありません。



野中 康弘
インフォテリア 教育部 エンジニア。十数年間システム開発に携わり,そのうちの半分をデータベース管理者として奮闘する。現在は,インフォテリア認定教育センターのサポートや,XML技術者認定制度の「XMLマスター」に対応したコーステキストの開発などを担当している。