XML Path Language (XPath(エックスパス)) は、マークアップ言語 XML に準拠した文書の特定の部分を指定する言語構文である。XPath自体は簡潔な構文 (式言語) であり、XMLベースのマークアップ言語ではない。標準化団体 W3C (World Wide Web Consortium) で開発され、1999年11月16日に XML Path Language (XPath) 1.0 が XSL Transformations (XSLT) 1.0 と同時に勧告として公表された[1][2]。XPathは、XSLT と XSL-FO とともに XSL の構成要素である。2007年1月23日、W3C で XPath 1.0 の次期バージョンが制定され、XPath 2.0 が XSLT 2.0 と同時に勧告された。2014年4月8日に XPath 3.0、2017年3月21日に XPath 3.1 が勧告された。他に、XPathを拡張したようなものとして XQuery がある。
XPathは、XML文書中から必要な要素群(サブセット)を取り出す、などといった用途に使うものとして、急速に受け入れられていった。なお、もともとはXPathは、XSL (XSLT) と XPointer に共通する構文と振る舞いのモデルを目標としていた。
XMLはデータを格納する。
特定のデータを、ある文書中のあらかじめ知っている場所(パス(path)と呼ばれます)から取り出したいという状況を考えます。URLとパスが与えられているのであるならば、データを自動的に取得できてしかるべきです
すべてのXML文書はツリー構造で図示できると言いましたが、この特徴が重要である理由が今こそ明かされます。どんな文書にも、たった1つだけのツリー構造が対応するので、文書中のどんな場所にもルートからのパスが一意に決定されるのです。XPathは、どのようにツリー構造をたどっていけばよいかを、目的地に到着するための一連のステップで簡潔に表現するものです。
XPathではノードを7種類に分類します。
ノードの種類 | 説明 |
---|---|
ルート | 文書のルートは特別なノードです。これは要素と思われるかもしれませんが、むしろ文言要素の入れ物であるとも考えられます。ルート(root)には文書要素によって囲まれているすべてのコメントや処理命令も格納されています。 |
要素 | 要素(element)とルートノードは、単独で他のノードを格納することができるという特別な性質を持っています。要素ノードは、他の要素だけでなくルートノード以外の種類のノードも格納することができます。要素は、ツリー上では2つの枝の合流点となるか、またはそれが空要素ならば、葉ノードとなります。 |
属性 | 単純化のために、XPathは属性(attribute)を元となっている要素からは分離されたノードとして取り扱います。これによって、パスの構文は同一のまま、要素全体を取り扱うか、その中の属性だけを取り扱うかを選ぶことができるわけです。属性は、テキストしか格納できない要素のようにふるまいます。 |
テキスト | ひと続きのテキスト(text)の領域は葉ノードとして取り扱われます。テキストは常に要素の子となります。テキストノードは要素や他の種類のノードによって分割されることがあり、このような場合に要素は1つ以上のテキストノードを子として持つことになります。要素中のテキストを処理するときは、1つ以上のノードをチェックする必要があるかもしれないことを覚えておきましょう。 |
コメント | コメント(comment)は文書の内容にはまったく寄与しませんし、ほとんどのXML処理系はこれを無視しますが、XMLでのコメントは正当なノードとみなされます。このようにすると、文字単位で忠実に再現するための文書の表現方法となるかもしれないわけです(もっとも、後で説明しますが、これは厳密な意味で可能というわけではありません)。それに、コメントを保持しておきたいかどうかは誰にもわかりません。 |
処理命令 | コメントと同様にルートノードの下であれば処理命令(PI:Processing Instruction)は文書中のどこにでも出現可能です。 |
名前 | 属性と名前空間宣言が別々に扱われていることを奇妙に思うかもしれません。しかし、名前空間(namespace)は文書の領域に対して有効で、1つの要素だけに属しているのではないことを考えてみてください。すべての子要素は名前空間宣言の影響を受けます。XMLの処理系は名前空間に対して特別な処理をしなくてはなりませんから、XPathでも別個の種類のノードとしています、 |
DTDはこのリストに含まれていません。XPathを内部もしくは外部サプセットを操作するために使うことはできないのです。XPathは暗黙的にそういった情報を取り扱うため、これらに直接アクセスするようにはできていないのです。また、XPathでツリーを操作する前に、すべての実体参照は解決済みであることが想定されています。実体は要素によるツリーを含んでいてもよく、そのツリーを操作したいこともありえるので、この想定は望ましいものでしょう。
ロケーションパス
ロケーションパス(location path)はロケーションステップを並べて、XML文書中のあるノードから特手のノードまでの位置を示すものです。各ロケーションステップはスラッシュ(/)を用いて連結され、たとえば次のようなものです。
/book/chapter/section/para
ここで、先頭のスラッシュ(/)はロケーションステップを連結するものではなく、ルートノードを表します。
ルートノード(先頭がスラッシュ)から始まるロケーションパスは絶対パスと呼ばれ、それ以外はある位置から相対的に目的のノード位置までを示すので相対パスと呼ばれます。
ロケーションパスのステップはスラッシュ(/)を用いて連結できます。各々のステップをたどることによって、少しずつ目的のノードに近づいていくわけです。例えば、ルートノードから、para要素に行くとします。それは、section要素の中にあり、それはまたchapter要素の中にあり、それはまたbook要素の中にあるとします。その場合、パスは以下のようになります。
この構文は冗長となる場合があるので、XPathでは表6-3に示すような簡便な記法を定義しています。
ロケーションステップ
ロケーションステップは3つの部分に分かれます。
ロケーションステップの部分 | 説明 |
---|---|
軸(axis) | 移動する方向を指定 |
ノードテスト(node test) | どの種類のノードに適用されるかを指定 |
述語(predicate) | リストは省略可能で、真偽値のテストを使って移動できる候補をさらに絞り込むために指定 |
「軸」は移動する方向を示すためのキーワードです。先祖の方向に向かって上に移動することも、子孫の方向に向かって下に降りることも、兄弟の方向に向かうこともできます。表6-1にすべての種類の軸を示します。
軸
「軸」は移動する方向を示すためのキーワードで、次のいずれかを指定することができます。
軸の種類 | マッチするもの |
---|---|
child | コンテキストノードの子 |
descendant | コンテキストノードの子孫。子、そのまた子(孫)、と辿れるものをすべて含む。このためdescendant軸が属性や名前空間ノードを含むことはない。 |
parent | コンテキストノードの親 |
ancestor | コンテキストノードの祖先。親、そのまた親、と辿れるものをすべて含む。 |
self | コンテキストノード自身 |
descendant-or-self | 子孫ノードとコンテキストノード自身 |
ancestor-or-self | 先祖ノードとコンテキストノード自身 |
following | 文書中に出現する順序で、コンテキストノードより後(そのためコンテキストノードの子孫は含まれない)に出現するすべてのノード。つまり、コンテキストノードより後に出現する兄弟ノードとその子孫。 |
following-sibling | 文書中に出現する順序で、コンテキストノードより後に出現するすべての兄弟ノード。 |
preceding | 文書中に出現する順序で、コンテキストノードより前(そのためコンテキストノードの子孫は含まれない)に出現するすべてのノード。つまり、コンテキストノードより前に出現する兄弟ノードとその子孫。 |
preceding-sibling | 文書中に出現する順序で、コンテキストノードより前に出現するすべての兄弟ノード。 |
attribute | コンテキストノードが要素の場合、その属性ノード |
namespace | コンテキストノードが要素の場合、その名前空間ノード |
訳注:コンテキストノードとは、XPathの処理における現在の対象となっているノードのことを指します。XPathは、現在の状態として他に、現在の候補が何番目か(コンテキストポジション)、現在の候補の数(コンテキストサイズ)、変数の状態、関数定義、現在の名前空間宣言を保持しています。
軸の後に記述されるノードテストのパラメータと軸は二重コロン(::)で区切られます。明示的なノードの種類を指定する代わりに、名前を使うこともできます。この場合、ノードの種類は軸から推測されます。
Attribute軸に対しては、ノードは属性だとみなされますし、Namespace軸に対しては、ノードは名前空間だとみなされます。他の種類の軸では、ノードは要素だとみなされます。軸の指定がない場合には、Child軸とされ、ノードの種類は要素とみなされます。表6-2にノードテストの表を示します。
ノードテスト(node test)
ノードテストの指定 | マッチするもの |
---|---|
/ | ルートノードにマッチする。ルートノードはルート要素ではなくルー卜要素を持っているノードで、その中に入っているコメントや処理命令も含む |
名前 | attribute軸の場合はコンテキストノードの「名前」の属性にマッチし、namespace軸の場合は「名前」の名前空間にマッチする。これら以外の軸の場合には要素名が「名前」であるあらゆる要素にマッチする。「名前空間:名前」という形式で指定してもよい。 |
* | attribute軸の場合は、あらゆる属性にマッチし、namespace軸の場合は、あらゆる名前空問にマッチする。これら以外の軸の場合には、あらゆる要素にマッチする。 |
node() | あらゆるノードにマッチする。例えば、attribute::node()はコンテキストノードのすべての属性にマッチする。 |
text() | あらゆるテキストノードにマッチする |
processing-instruction() | あらゆる処理命令にマッチする。「processing-instruction('目的の処理命令')」という形式で指定しても良い。この場合たとえば、<?xsl-stylesheet href="article.css" ?>という処理命令を指定するには、「processing-instruction('xsl-stylesheet')」と指定する。 |
comment() | あらゆるコメントノードにマッチする |
ロケーションパスの簡便な記法
指示 | マッチするもの |
---|---|
@role | roleという名前の属性にマッチする。attribute::roleと等価 |
. | コンテキストノードにマッチする。self::node()と等価 |
/* | 文書要素にマッチする。スラッシュ(/)で始まるあらゆるロケーションパスは絶対パスであり、最初のステップはルートノードを表す。次のステップは*で、あらゆる要素にマッチする |
parent::*/following-sibling::para | コンテキストノードの親に続くあらゆるpara要素にマッチする |
.. | 親ノードにマッチする。二重ドット(..)はparent::node()の短縮形 |
.//para | コンテキストノードの子孫である、あらゆるpara要素にマッチする。二重スラッシュ(//)は/descendant-or-self::node()/の短縮形 |
//para | ルートノードの下にあるあらゆる要素にマッチする。すなわち、これは文書中のすべてのpara要素にマッチする。二重スラッシュ(//)で始まるロケーションパスは、ルートノードから始まるとみなされる |
../* | すべての兄弟要素にマッチする(コンテキストノードが要素である場合には、コンテキストノードにもマッチする) |