web-dev-qa-db-ja.com

XPath:特定の属性を持つ最初の要素を選択

XPathのbookstore/book[1]は、bookstoreの下の最初のブックノードを選択します。

より複雑な条件に一致する最初のノードを選択するにはどうすればよいですか。 /bookstore/book[@location='US']に一致する最初のノード

272
ripper234

(/bookstore/book[@location='US'])[1]を使う

これは最初にlocation属性が 'US'のbook要素を取得します。その後、そのセットから最初のノードを選択します。いくつかの実装で必要とされる括弧の使用に注意してください。

(最初の要素がそのlocation属性を持っていない限り、これは/bookstore/book[1][@location='US']と同じではありません)

394

/bookstore/book[@location='US'][1]は単純な構造でのみ機能します。

もう少し構造を追加すると物事は壊れます。

あり

<bookstore>
 <category>
  <book location="US">A1</book>
  <book location="FIN">A2</book>
 </category>
 <category>
  <book location="FIN">B1</book>
  <book location="US">B2</book>
 </category>
</bookstore> 

/bookstore/category/book[@location='US'][1]の結果

<book location="US">A1</book>
<book location="US">B2</book>

「より複雑な条件に一致する最初のノード」ではありません。 /bookstore/category/book[@location='US'][2]は何も返しません。

括弧を使用すると、元の質問の結果が得られます。

(/bookstore/category/book[@location='US'])[1]

<book location="US">A1</book>

そして(/bookstore/category/book[@location='US'])[2]は期待通りに動作します。

163
tkurki

Jonathan Finglandの答えに対する説明として:

  • 同じ述語([position()=1 and @location='US'])内の複数の条件は、全体として真でなければなりません
  • 連続した述語([position()=1][@location='US'])の複数の条件は次々に真でなければなりません
  • これは[position()=1][@location='US']!= [@location='US'][position()=1]を意味します。
    while [position()=1 and @location='US'] == [@location='US' and position()=1]
  • ヒント:単独の[position()=1][1]と省略することができます

ブール演算子 "and"と "or"、およびブールXPath関数not()true()false()を使用して、述部に複雑な式を作成できます。さらに、サブ式を括弧で囲むこともできます。

42
Tomalak

以下のように、より複雑な構造化されたxmlファイルを考慮して、最初の英語のブックノード(ドキュメント全体)を見つける最も簡単な方法:

<bookstore>
 <category>
  <book location="US">A1</book>
  <book location="FIN">A2</book>
 </category>
 <category>
  <book location="FIN">B1</book>
  <book location="US">B2</book>
 </category>
</bookstore> 

xpath式です:

/descendant::book[@location='US'][1]
12
Gee-Bee
    <bookstore>
     <book location="US">A1</book>
     <category>
      <book location="US">B1</book>
      <book location="FIN">B2</book>
     </category>
     <section>
      <book location="FIN">C1</book>
      <book location="US">C2</book>
     </section>
    </bookstore> 

それで、上記を考えてください。あなたはで最初の本を選択することができます

(//book[@location='US'])[1]

そして、これは米国という場所を持つどこでも最初のものを見つけるでしょう。 [A1]

//book[@location='US']

場所がUSのすべての書籍に設定されているノードを返します。 [A1、B1、C2]

(//category/book[@location='US'])[1]

文書内の任意の場所のカテゴリに存在する最初の書籍の所在地USを返します。 [B1]

(/bookstore//book[@location='US'])[1]

ルート要素bookstoreの下のどこかに存在する、場所がUSの最初の本を返します。/bookstoreの部分を本当に冗長にします。 [A1]

直接答えて:

/bookstore/book[@location='US'][1]

書店の下にあるUSという場所を持つbook要素の最初のノードを返します[A1]

ちなみにあなたが望むなら、この例ではbookstoreの直接の子供ではなかった最初の米国の本を見つけるために:

(/bookstore/*//book[@location='US'])[1]
8
iZian

Xpathが複雑な場合、または同じxpathを持つ複数のノードが存在する場合は、インデックスを使用して目的のノードを取得します。

例:(// bookstore [@location = 'US'])[index]

どのノードが欲しいか番号を与えることができます。

2

指定されたxmlで名前空間が提供されている場合、これを使用することをお勧めします。

(/*[local-name() ='bookstore']/*[local-name()='book'][@location='US'])[1]
1
metal

例えば。

<input b="demo">

そして

(input[@b='demo'])[1]
0
SenthilKumarP