Page History
...
- XPath に関する簡単な入門レベルのチュートリアル:W3schools Xpath Tutorial (英語)
- ZVON XPath Tutorial (英語)
- XML in a Nutshell – A Desktop Quick Reference の本 (英語) は購入することができます。
- XML Path Language (XPath) (英語)
このドキュメントは、XPath 式の構文に関する参照文献や詳しい説明を提供することが目的ではありません。 ですが、これまでに XPath 式を使ったことがない場合、このセクションでは簡単な概要と例が示されており、XMLQueryService を使い始めるにあたっての参考となるでしょう。 以下のトピックを参照してください。
...
このセクションの後半で提供されている例では、以下の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) の紹介
...
以下は、サンプルの 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, 式には次のいずれかが含まれています。
...
- 次の例では、<SalesOrder> エレメントの選択に XML と XPath の大文字小文字が誤って使われているため、何も選択されません。
QUERY NODES(//SALESORDER) NODESVALUE1(@SONumber)
- 次の 2 つの例はいずれも、<SalesOrder> エレメントすべてを選択して、それぞれに対して販売注文番号を返します。 機能的には、この 2 つは同じです(サンプル XML ドキュメントを使用した場合)。
QUERYQUERY NODES(//SalesOrder/@SONumber)
QUERY
QUERYNODES(//SalesOrder) NODESVALUE1(@SONumber)
- すべての <SalesOrder> エレメントを選択し、それぞれに顧客番号を返します。
QUERYQUERY NODES(//SalesOrder) NODESVALUE1(Customer/@CustNumber)
- 顧客番号に値 '543' を持つ <Customer> エレメントを選択して、親エレメント <SalesOrder> の販売注文番号を返します。
QUERYQUERY NODES(//Customer
\[@CustNumber="543"\]) NODESVALUE1(../@SONumber)
- 指定の注文番号の <SalesOrder> に対するすべての <Part> エレメントを選択して、それぞれに対するパーツ番号を返します。
QUERYQUERY NODES(//SalesOrder
\[@SONumber="12345"\]/Line/Part)
NODESVALUE1(@PartNumber)
NODESVALUE2(../Quantity) - 価格が 2.99 よりも大きい <Part> エレメントをすべて選択し、注文番号、パーツ番号、価格、数量を返して、合計金額 (価格*数量) も返します。
QUERY NODES(//Part[Price>2.99])
NODESVALUE1NODESVALUE1(../../@SONumber)
NODESVALUE2NODESVALUE2(@PartNumber)
NODESVALUE3NODESVALUE3(Price)
NODESVALUE4NODESVALUE4(../Quantity)
NODESVALUE5NODESVALUE5(Price*../Quantity)
XML 名前空間と XMLQueryService の XPath 式への影響
...
サンプルの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 ドキュメント・サンプルを使って、前の例と比較してみましょう。
<?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 に多くの情報が提供されていますので、そちらを参照してください。 参考までに、次のサイト (英語) を紹介します。
...
このような例のドキュメントに対して使用する 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
LOAD FILE(salesorder.xml) NAMESPACEAWARE(*YES)
...
ただし、いったんドキュメントが名前空間認識モードでロードされると、ここまで上記で示したサンプル・クエリーは機能しなくなります。これは、名前空間が XML ドキュメント内のノード識別の一部を形成するからです。
名前空間認識モードで機能するように Xpath 式を作成する方法は様々ありますが、すべてのオプションを紹介することはこのドキュメントの目的ではありません。 ただし、以下の例は、まず始めに取り掛かる際に参考になると思います。
- この例では、XPath 組み込み関数 local-name を使って、lローカル名 (名前空間接頭辞が無いノード名) をベースにノードを選択します。
QUERYQUERY NODES(//*
\[local-name() = 'SalesOrder'
\]) NODESVALUE1(@SONumber)
複数の名前空間が使用されており、このコンテキストで 'SalesOrder' が不明瞭な場合は、この前の例を拡張して、XPath 組み込み関数 namespace-uri を利用します。
QUERY NODES(//*[local-name() = 'SalesOrder' and namespace-uri() = 'urn:schemas-acme-com:tutorder.dtd'])
NODESVALUE1NODESVALUE1(@SONumber)
もしくは、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)