web-dev-qa-db-ja.com

XPath:子ノードに属性が含まれるノードを取得します

次のXMLがあるとします。

<book category="CLASSICS">
  <title lang="it">Purgatorio</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

<book category="CLASSICS">
  <title lang="it">Inferno</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

<book category="CHILDREN">
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>

<book category="WEB">
  <title lang="en">XQuery Kick Start</title>
  <author>James McGovern</author>
  <author>Per Bothner</author>
  <author>Kurt Cagle</author>
  <author>James Linn</author>
  <author>Vaidyanathan Nagarajan</author>
  <year>2003</year>
  <price>49.99</price>
</book>

<book category="WEB">
  <title lang="en">Learning XML</title>
  <author>Erik T. Ray</author>
  <year>2003</year>
  <price>39.95</price>
</book>

「it」の言語属性を持つタイトルノードを持つすべてのブックノードを取得するxpathを実行したいと思います。

私の試みは次のように見えました:

//book[title[@lang='it']]

しかし、それはうまくいきませんでした。私はノードを取り戻すことを期待しています:

<book category="CLASSICS">
  <title lang="it">Purgatorio</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

<book category="CLASSICS">
  <title lang="it">Inferno</title>
  <author>Dante Alighieri</author>
  <year>1308</year>
  <price>30.00</price>
</book>

ヒントはありますか?前もって感謝します。

99
user176872

試して

//book[title/@lang = 'it']

これは次のとおりです。

  • すべてのbook要素を取得します
    • 少なくとも1つのtitle がある
      • 属性はlang です
        • "it"の値

this 役立つ—それは、Ronald Bourretによる "XPath in Five Paragraphs" というタイトルの記事です。

しかし、正直なところ、XPathエンジンに「問題」がない限り、//book[title[@lang='it']]と上記のものは同等でなければなりません。そのため、コードまたはサンプルXMLに表示されていないものがあります。たとえば、サンプルはXMLフラグメントです。ルート要素に名前空間があり、クエリでそれをカウントしていない可能性がありますか?そして、あなたはそれがうまくいかなかったと言っただけでしたが、どんな結果が得られたのか教えてくれませんでした。

155
lavinio

数年後ですが、便利なオプションはXPath軸を利用することです( https://www.w3schools.com/xml/xpath_axes.asp )。具体的には、descendants軸の使用を検討しています。

この例でうまくいくと思います:

//book[descendant::title[@lang='it']]

これにより、「it」に等しい言語属性値を含む子book要素(ネストの深さに関係なく)を含むすべてのtitle要素を選択できます。

XPath軸がその時点で存在していたことを100%確信していないので、この回答が2009年に関連するかどうかを確実に言うことはできません。私が確認できるのは、それらが今日存在していることであり、XPathナビゲーションで非常に有用であることがわかりました。あなたもそうするでしょう。

46
wes.hysell
//book[title[@lang='it']]

実際に同等です

 //book[title/@lang = 'it']

Vtd-xmlを使用して試してみましたが、両方の式が同じ結果を吐き出しました...どのxpath処理エンジンを使用しましたか?適合性の問題があると思います

import com.ximpleware.*;
public class test1 {
  public static void main(String[] s) throws Exception{
      VTDGen vg = new VTDGen();
      if (vg.parseFile("c:/books.xml", true)){
          VTDNav vn = vg.getNav();
          AutoPilot ap = new AutoPilot(vn);
          ap.selectXPath("//book[title[@lang='it']]");
                  //ap.selectXPath("//book[title/@lang='it']");

          int i;
          while((i=ap.evalXPath())!=-1){
              System.out.println("index ==>"+i);
          }
          /*if (vn.endsWith(i, "< test")){
             System.out.println(" good ");  
          }else
              System.out.println(" bad ");*/

      }
  }
}
9
vtd-xml-author

あなた自身の提案は正しいと思いますが、xmlはまったく有効ではありません。 //book[title[@lang='it']]<root>[Your"XML"Here]</root>を実行している場合、 here などの無料のオンラインxPathテスターが期待される結果を見つけます。

3
Joakim Byg

このxPath式を使用してみてください。

//book/title[@lang='it']/..

これにより、すべてのブックノードが「it」言語になります。

0
user1113000