子ノードに属性が含まれているノードを取得する


116

次の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>

ヒントはありますか?


これはどのXPath実装ですか?
Pavel Minaev 09/09/25

回答:


175

試す

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

これは次のようになります。

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

これは役立つかもしれません—これは、Ronald Bourretによる「XPath in Five Paragraphs」というタイトルの記事です。

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


4
title直接の子ではないbookが、どこか深く、どこにいるかが正確にわからない場合に、同じようにするにはどうすればよいですか?//book[/title/@lang = 'it']動作していないようですか?
Martin Konicek 2013年

5
マーティン、//book[.//title/@lang = 'it']を使用できます。トリックは「」だと思います。状態の初めに。
Bruno Caponi

1
リンクありがとうございます。私はxPathを何年も使用していますが、これは根本的なロジックを理解するのに本当に役立ちました!
swensor '14 / 06/18

57

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

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

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

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

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


12
//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 ");*/

      }
  }
}

+1そのコンプライアンスの問題と構文が同じノードセットを生成すること。C#の同様のコードも機能します。
Zach Bonham

-1:張さん、質問に関係のないコードを削除することで、あなたに好意を示しようとしていました。それは私があなたに反対票を投じないことを可能にしました。クエリを呼び出すためのコードが他の回答に含まれていないことに注意してください。
ジョンサンダース

6
+1:Saunders氏が何を話しているのか理解できないため-他の回答ではコードを追加していません。この回答は、1でメソッドを検証し、2で自分のテストを実行できるように使用されるコードを示しています。コードは短く、読みやすいです。私は問題を見ません。
DuckPuppy

4

あなたの提案は正しいと思いますが、xmlはあまり有効ではありません。あなたが実行している場合//book[title[@lang='it']]には<root>[Your"XML"Here]</root>そのようなものとして、無料のオンラインれたxPathテスターここでは、期待した結果があります。


2

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

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

これで、すべての本のノードが「it」言語で表示されます。


2
その式の結果は本のノードではなくタイトルのノードです
Caleth

2
それは真実ではありません。本のノードを返します(最後の2つのドットは、タイトルノードの上位ノードを目的としています)。
user1113000
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.