2. ロケーションパス
2.1 ロケーションパス (簡略な記述法)
XPath では、XML 文書上のノードの位置を指定する際、ロケーションパスと呼ばれる式によって表します。ロケーションパスの書き方には、厳密かつ詳細に記述する書き方と、簡略に記述する書き方の 2 つがありますが、ここではまず、ファイルのディレクトリ構造の記法に似ていて直感的に分かりやすい後者の方から説明することにします。
主な構文を以下の表に示します。
構文 | 意味 |
---|---|
para | コンテキストノードの子要素 para を選択する |
* | コンテキストノードのすべての子要素を選択する |
text() | コンテキストノードのすべての子テキストノードを選択する |
@name | コンテキストノードの name 属性を選択する |
@* | コンテキストノードのすべての属性を選択する |
para[1] | コンテキストノードの 1番目の子要素 para を選択する |
para[last()] | コンテキストノードの最後の子要素 para を選択する |
//para | ルートノードの子孫ノードから要素ノード para をすべて選択する。つまり、コンテキストノードと同じ文書内のすべての para 要素を選択する |
.(ピリオド) | コンテキストノードを選択する |
..(ダブルピリオド) | コンテキストノードの親を選択する |
chapter[title="Introduction"] | コンテキストノードの子要素 chapter のうち、文字列値が Introduction である子要素 title を 1個以上持つものを選択する |
chapter[title] | コンテキストノードの子要素 chapter のうち、子要素 title を 1個以上持つものを選択する |
employee[@secretary and @assistant] | secretary 属性と assistant 属性の両方をもつコンテキストノードの子要素 employee をすべて選択する |
上の表中の構文で示されたものを 1個以上 "/" (スラッシュ)で繋いだものがロケーションパスとなります。前ページで示したノードツリーから例を挙げ構文とともに確認しましょう。まず最初の例文ですが、コンテキストノードの最初の位置は music とします。
artist/text()
"/" (スラッシュ) の前の artist 部分の意味は「コンテキストノード music の子要素である artist を選択する」となります。次に後半部分 text() ですが、この時点でコンテキストノードは artist にかわっていて、意味は「コンテキストノード artist のすべての子テキストノードを選択する」となります。
ひとつのロケーションパス式の評価が終わるとコンテキストノードは最初にあったノードに戻ります。次の例文ですが、コンテキストノードの最初の位置は trackListings とします。
../title/@releaseYear
まず、".."(ダブルピリオド) の部分ですが、「コンテキストノード (trackListings) の親ノードを選択する」ですから「cdを選択する」となります。次の "title" 部分は「コンテキストノード (cd) の子要素 title を選択する」となり、最後の "@releaseYear" は「コンテキストノード(title)の releaseYear 属性を選択する」となります。
次の例文のコンテキストノードの最初の位置は artist とします。
cd//track[3]
cd 部分の意味は「コンテキストノード artist の子要素である cd を選択する」となります。"//track[3]" の部分を解釈する際のコンテキストノードは cd ですからこの部分の意味は「コンテキストノード cd の子孫ノードのうち 3 番目の track 要素を選択する」となります。兄弟要素の順番ですが、XML 文書内での出現順に 1, 2, 3, ... となります。
<trackListings> <track no="1">Soon</track> ・・・・・・・1番目 <track no="2">Glider</track> ・・・・・・2番目 <track no="3">Don't Ask Why</track>・・・3番目 <track no="4">Off Your Face</track>・・・4番目 </trackListings>
また、このロケーションパス式を XSLT を用いて出力した結果は、"Don't Ask Why" となりますが、これはテキストノードの値ですので本来は、"cd//track[3]/text()" と記述しなければいけないはずです。なぜこのような結果となるのでしょうか。ここで、問題となるのは「文字列値」と呼ばれる値です。要素ノードの文字列値とは、その要素の子孫として存在するすべてのテキストノードの文字データを連結した値となります。
具体例を挙げると、要素ノード trackListings の文字列値は "Soon Glider Don't Ask Why Off Your Face" となり、属性ノード no の値が 1 である要素ノード track の文字列値は "Soon" となります。
上記の理由から、"cd//track[3]" と指定した場合と "cd//track[3]/text()" と指定した場合のロケーションパス式の評価値が同じになります。
//track[last()]/@no
ロケーションパスの意味は「ルートノードの子孫ノードのうち、最後、つまり 4番目の track 要素に従属する no 属性を選択する」となります。ここで重要なのは、ロケーションパスの最初に現れる "/" がルートノードを表すということです。
cd/trackListings[track="Glider"]
コンテキストノードの最初の位置は artist とします。まず cd 部分の意味は「コンテキストノード artist の子要素である cd を選択する」となります。次に trackListings[track="Glider"] の部分の意味は、「コンテキストノードの子要素 trackListings のうち、文字列値が Glider である子要素 track を 1個以上持つものを選択する」となりますから、選択されるノードは trackListings です。
//track[@no and @time]
ロケーションパスの意味は「ルートノードの子孫ノードのうち、属性ノード no と属性ノード time の両方を含む要素ノード track を選択する」となりますので、選択されるノードは上図の一番右の要素ノード track です。
次ページでは詳細な記述法について説明します。