Web には多数の XPath 式に関するリソースが存在します。 以下を参考にしてみてください。
- XPath に関する簡単な入門レベルのチュートリアル:&<a href="https://www.w3schools.com/xml/xpath_intro.asp" target="_blank"&>W3schools Xpath Tutorial&</a&> (英語)
- &<a href="http://www.zvon.org/xxl/XPathTutorial/General/examples.html" target="_blank"&>ZVON XPath Tutorial&</a&> (英語)
- &<a href="http://shop.oreilly.com/product/9780596007645.do" target="_blank"&>XML in a Nutshell – A Desktop Quick Reference&</a&>, の本 (英語) は購入することができます。
- &<a href="http://www.w3.org/TR/xpath/" target="_blank"&>XML Path Language (XPath)&</a&> (英語)
このドキュメントは、XPath 式の構文に関する参照文献や詳しい説明を提供することが目的ではありません。 ですが、これまでに XPath 式を使ったことがない場合、このセクションでは簡単な概要と例が示されており、XMLQueryService を使い始めるにあたっての参考となるでしょう。 以下のトピックを参照してください。
- XML の例
- XML Path Language (XPath) の紹介
- XMLQueryService で使用する XPath 使用例
- XML 名前空間と XMLQueryService の XPath 式への影響
XML の例
このセクションの後半で提供されている例では、以下のXML ドキュメントの簡素なサンプルを参照します。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Orders SYSTEM "http://www.acme.com/schemas/tutorder.dtd" >
<Orders>
<SalesOrder SONumber="12345">
<Customer CustNumber="543">
<CustName>ABC Industries</CustName>
<Street>123 North St.</Street>
<City>Bankstown</City>
<State>NSW</State>
<PostCode>2087</PostCode>
</Customer>
<OrderDate>2012-11-19</OrderDate>
<Line LineNumber="1">
<Part PartNumber="123">
<Description>Gasket Paper</Description>
<Price>9.95</Price>
</Part>
<Quantity>10</Quantity>
</Line>
<Line LineNumber="2">
<Part PartNumber="456">
<Description>Glue</Description>
<Price>13.27</Price>
</Part>
<Quantity>5</Quantity>
</Line>
</SalesOrder>
</Orders>
XML Path Language (XPath) の紹介
XPath はパス式を構成するための構文で、XML ドキュメントのノードを選択することができます。 ある意味、このパス式は、自身のコンピュータでファイル・システムの作業をする際のパス式と大変良く似ています。
一般的に XPath は 7 つのタイプのノード (viz. エレメント、属性、テキスト、名前空間、処理命令、コメント、ドキュメントのノード.) を認識します。 XMLQueryService のコンテキストでは、エレメントと属性ノード、そして当然ながらドキュメント・ノードに関係することが主です。
上に示された XML ドキュメントの例では、エレメントはは、<Orders>、<SalesOrder>、<Customer>、<OrderDate>、<Line>、<Part> などであり、属性としては、SONumber=、CustNumber=、 LineNumber=、PartNumber=.などがあります。
以下は、サンプルの XML ドキュメント内の最初の <SalesOrder> エレメントにある 2 番目の <Line> エレメントの最初の <Part> エレメントの PartNumber= 属性を選択する XPath 式の例です。
/Orders/SalesOrder\[1\]/Line\[2\]/Part\[1\]/@PartNumber
上記例の <SalesOrder>、<Line>、<Part> エレメントの選択は序数インデックスにより行われることに注意してください。 特に、<Line> エレメントの選択に、LineNumber= 属性の値が参照される訳ではありません (この後説明しますが、この方法による参照も可能ではあります)。
XPath からはかなりの数の組み込み関数が提供されており、これを使って様々な方法で値を比較したり、より上級向けの使い方もできるようになっています。 例えば、次の式では組み込み関数 contains を使って、<Part> エレメントの <Description> エレメント内に文字列 "Paper" が含まれている、(場所に関係なく) すべての <Part> エレメントを選択することができます。
//Part\[contains(Description, "Paper")\]
XPath では、パスかステップに従って、1 つのノード、もしくは複数のノードのセットを選択します。 多くの場合、XPath, 式には次のいずれかが含まれています。
nodename | 指定された名前ですべてのノードを選択します。 |
/ | ルート・ノードから選択します。 |
// | 位置に関係なく、選択条件に一致する現在ノードからのドキュメントのノードを選択します。 |
. | 現在のノードを選択します。 |
.. | 現在のノードの親を選択します。 |
@nodename | 指定された名前で属性を選択します。 |
XPath では、述語は角カッコに含まれるサブ式で、これを利用して、特定のノードまたは特定の値を含むノードを選択することができます。 以下は述語を使用する XPath 式の例です。
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="999f91b6-81fb-4db6-8656-b56bc66c5c5e"><ac:plain-text-body><![CDATA[ | /Orders/SalesOrder[1] | <Orders> エレメントの子である、最初の <SalesOrder> エレメントを選択します。 | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="02ab01fa-c2d6-4bb3-bc45-463698ba20d0"><ac:plain-text-body><![CDATA[ | /Orders/SalesOrder[last()] | <Orders> エレメントの子である、最後の <SalesOrder> エレメントを選択します。 (示されている XML ドキュメントのサンプルには <SalesOrder> エレメントが 1 つしか存在しませんので、同じ結果になります。) | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="8cf42c85-6abb-47ad-b344-e77bf9cfb8ad"><ac:plain-text-body><![CDATA[ | //Part[Price<=10.00] | 場所に関係なく、エレメントの <Price> エレメントの値が 10.00 以下である <Part> エレメントを選択します。 | ]]></ac:plain-text-body></ac:structured-macro> |
XPath 式にはこの他にも多くの機能があります。 さらに詳しい情報を得るには、上記で紹介されているリンクをまず参照してみてください。
重要な注意点: XML ノード名では大文字と小文字が区別されます。 XPath 式ではエレメントや属性の名前を指定する際に大文字と小文字を正しく指定する必要があります。 例えば、式 '//salesorder' は '//SalesOrder' と同じではありません。 上記に示されているサンプル XML ドキュメントと共に利用する場合、'//salesorder' の式はエラーになり、どのノードも選択しませんが、'//SalesOrder' では、ドキュメントのどの場所であっても発生する、すべての <SalesOrder> エレメントが選択されます。
XMLQueryService で使用する XPath 使用例
次は、XMLQueryService の QUERY コマンドのパラメータで使用する XPath 式の例で、上で示されているサンプル XML ドキュメントの値を選択します。
1. 次の例では、<SalesOrder> エレメントの選択に XML と XPath の大文字小文字が誤って使われているため、何も選択されません。
QUERY NODES(//SALESORDER) NODESVALUE1(@SONumber)
2. 次の 2 つの例はいずれも、<SalesOrder> エレメントすべてを選択して、それぞれに対して販売注文番号を返します。 機能的には、この 2 つは同じです(サンプル XML ドキュメントを使用した場合)。
QUERY NODES(//SalesOrder/@SONumber)
QUERY NODES(//SalesOrder) NODESVALUE1(@SONumber)
3. すべての <SalesOrder> エレメントを選択し、それぞれに顧客番号を返します。
QUERY NODES(//SalesOrder) NODESVALUE1(Customer/@CustNumber)
4. 顧客番号に値 '543' を持つ <Customer> エレメントを選択して、親エレメント <SalesOrder> の販売注文番号を返します。
QUERY NODES(//Customer\[@CustNumber="543"\]) NODESVALUE1(../@SONumber)
5. 指定の注文番号の <SalesOrder> に対するすべての <Part> エレメントを選択して、それぞれに対するパーツ番号を返します。
QUERY NODES(//SalesOrder\[@SONumber="12345"\]/Line/Part)
NODESVALUE1(@PartNumber)
NODESVALUE2(../Quantity)
6. 価格が 2.99 よりも大きい <Part> エレメントをすべて選択し、注文番号、パーツ番号、価格、数量を返して、合計金額 (価格*数量) も返します。
QUERY NODES(//Part\[Price>2.99\])
NODESVALUE1(../../@SONumber)
NODESVALUE2(@PartNumber)
NODESVALUE3(Price)
NODESVALUE4(../Quantity)
NODESVALUE5(Price*../Quantity)
XML 名前空間と XMLQueryService の XPath 式への影響
これまで利用したサンプルは、名前空間の明示的な宣言が無く、名前空間の接頭辞も使用していない XML ドキュメントに対する演算でした。 これは最もシンプルな形ですが、多くの場合、これが現実を反映している訳ではありません。
サンプルのXML ドキュメントに少し修正を加えて、以下のようにXML ドキュメントに対してデフォルトの名前空間が指定されているとして考えてみましょう。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Orders SYSTEM "http://www.acme.com/schemas/tutorder.dtd" >
<Orders xmlns="urn:schemas-acme-com:tutorder.dtd">
… etc …
</Orders>
このようにデフォルトの単一の名前空間を使用する場合、これに対する Xpath 式を作成する最も簡単な方法で一般的なのは、名前空間を無視することです。 使用される名前空間は 1 つだけなので、ノード名には名前空間の接頭辞は表示されず、したがって、通常はこれまで示された例と同じ式を使うことができます。 以下の各クエリは、ドキュメントが名前空間認識モードでロードされていない限り、デフォルトで名前空間を宣言したサンプル・ドキュメントで正常に作動します。
QUERY NODES(//SalesOrder/@SONumber)
QUERY NODES(//SalesOrder) NODESVALUE1(Customer/@CustNumber)
QUERY NODES(//Customer\[@CustNumber="543"\])
NODESVALUE1(../@SONumber)
QUERY NODES(//SalesOrder\[@SONumber="12345"\]/Line/Part)
NODESVALUE1(@PartNumber)
NODESVALUE2(../Quantity)
QUERY NODES(//Part\[Price>2.99\])
NODESVALUE1(../../@SONumber)
NODESVALUE2(@PartNumber)
NODESVALUE3(Price)
NODESVALUE4(../Quantity)
NODESVALUE5(Price*../Quantity)
ただし、XML ドキュメントが複数の名前空間を使用している、名前空間の接頭辞を使用しているかのいずれか、もしくは両方の場合は、少々複雑になります。 以下の代替 XML ドキュメント・サンプルを使って、前の例と比較してみましょう。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Orders SYSTEM "http://www.acme.com/schemas/tutorder.dtd" >
<tut:Orders xmlns:tut="urn:schemas-acme-com:tutorder.dtd">
<tut:SalesOrder SONumber="12345">
<tut:Customer CustNumber="543">
<tut:CustName>ABC Industries</tut:CustName>
<tut:Street>123 North St.</tut:Street>
<tut:City>Bankstown</tut:City>
<tut:State>NSW</tut:State>
<tut:PostCode>2087</tut:PostCode>
</tut:Customer>
<tut:OrderDate>2012-11-19</tut:OrderDate>
<tut:Line LineNumber="1">
<tut:Part PartNumber="123">
<tut:Description>Gasket Paper</tut:Description>
<tut:Price>9.95</tut:Price>
</tut:Part>
<tut:Quantity>10</tut:Quantity>
</tut:Line>
<tut:Line LineNumber="2">
<tut:Part PartNumber="456">
<tut:Description>Glue</tut:Description>
<tut:Price>13.27</tut:Price>
</tut:Part>
<tut:Quantity>5</tut:Quantity>
</tut:Line>
</tut:SalesOrder>
</tut:Orders>
このドキュメントには名前空間宣言が含まれており、エレメント名に関連する名前空間の接頭辞が使われています。 名前空間機能、特に名前空間の接頭辞を利用している場合は、所定のクエリに必要となる Xpath 式の構文が複雑になります。
XML 名前空間やこれが XPath に与える影響については、Web に多くの情報が提供されていますので、そちらを参照してください。 参考までに、次のサイト (英語) を紹介します。
- &<a href="http://developers.slashdot.org/story/02/05/30/002252/xml-namespaces-and-how-they-affect-xpath-and-xslt" target="_blank"&>XML Namespaces and how they affect Xpath and XSLT&</a&>
このような例のドキュメントに対して使用する Xpath 式を作成する際の、最も簡単なアプローチは、名前空間を無視することです。 ドキュメントが名前空間認識オプションを使用せずに(デフォルト・モードで) ロードされた場合は、先に紹介した例と同じ式を利用することがほぼ可能です。 次の各クエリは、上に示されたドキュメントの名前空間の接頭辞バージョンでも正しく作動します (名前空間の接頭辞が Xpath 式から完全に省略されていることに注意してください) 。
QUERY NODES(/Orders/SalesOrder/@SONumber)
QUERY NODES(/Orders/SalesOrder) NODESVALUE1(Customer/@CustNumber)
QUERY NODES(/Orders/SalesOrder/Customer\[@CustNumber="543"\])
NODESVALUE1(../@SONumber)
QUERY NODES(/Orders/SalesOrder\[@SONumber="12345"\]/Line/Part)
NODESVALUE1(@PartNumber)
NODESVALUE2(../Quantity)
QUERY NODES(/Orders/SalesOrder/Line/Part\[Price>2.99\])
NODESVALUE1(../../@SONumber)
NODESVALUE2(@PartNumber)
NODESVALUE3(Price)
NODESVALUE4(../Quantity)
NODESVALUE5(Price*../Quantity)
ただし、ドキュメントで複数の名前空間の宣言が行われており、特に名前空間無しでは名前空間の競合が起こり得る場合は、名前空間認識モードでドキュメントをロードする必要があるかもしれません。 この名前空間認識モードのロードは、XMLQueryService の LOAD コマンドで NAMESPACEAWARE キーワードに *YES を設定すれば実行できます。 例:
LOAD FILE(salesorder.xml) NAMESPACEAWARE(*YES)
ただし、いったんドキュメントが名前空間認識モードでロードされると、ここまで上記で示したサンプル・クエリーは機能しなくなります。これは、名前空間が XML ドキュメント内のノード識別の一部を形成するからです。
名前空間認識モードで機能するように Xpath 式を作成する方法は様々ありますが、すべてのオプションを紹介することはこのドキュメントの目的ではありません。 ただし、以下の例は、まず始めに取り掛かる際に参考になると思います。
1. この例では、XPath 組み込み関数 local-name を使って、lローカル名 (名前空間接頭辞が無いノード名) をベースにノードを選択します。
QUERY NODES(//*\[local-name() = 'SalesOrder'\]) NODESVALUE1(@SONumber)
2. 複数の名前空間が使用されており、このコンテキストで 'SalesOrder' が不明瞭な場合は、この前の例を拡張して、XPath 組み込み関数 namespace-uri を利用します。
QUERY NODES(//*\[local-name() = 'SalesOrder' and namespace-uri() = 'urn:schemas-acme-com:tutorder.dtd'\])
NODESVALUE1(@SONumber)
3. もしくは、XML ドキュメントのすべてのインスタンスで同じ名前空間の接頭辞が使用されていることが分かっている場合 (実際はこのようなケースが一般的ではありますが、そうでなければ有効にならない訳ではないことを頭に入れておいてください)、Xpath 式にこの名前空間の接頭辞を含めることができます (ドキュメントが名前空間認識モードでロードされていることが前提です)。
QUERY NODES(//tut:SalesOrder) NODESVALUE1(@SONumber)
つまり、以下の各クエリは上に示されたドキュメントの名前空間の接頭辞バージョンで正しく作動します。これは、ドキュメントが名前空間認識モードでロードされており、かつ、実際の XML ドキュメントの名前空間接頭辞がクエリ内で指定されたものと一致していることが前提です。
QUERY NODES(//tut:SalesOrder/@SONumber)
QUERY NODES(//tut:SalesOrder) NODESVALUE1(tut:Customer/@CustNumber)
QUERY NODES(//tut:Customer\[@CustNumber="543"\])
NODESVALUE1(../@SONumber)
QUERY NODES(//tut:SalesOrder\[@SONumber="12345"\]/tut:Line/tut:Part)
NODESVALUE1(@PartNumber)
NODESVALUE2(../tut:Quantity)
QUERY NODES(//tut:Part\[tut:Price>2.99\])
NODESVALUE1(../../@SONumber)
NODESVALUE2(@PartNumber)
NODESVALUE3(tut:Price)
NODESVALUE4(../tut:Quantity)
NODESVALUE5(tut:Price*../tut:Quantity)