Ruft Knoten ab, bei denen der untergeordnete Knoten ein Attribut enthält


115

Angenommen, ich habe das folgende 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>

Ich möchte einen xpath erstellen, der alle Buchknoten zurückgibt, die einen Titelknoten mit dem Sprachattribut "it" haben.

Mein Versuch sah ungefähr so ​​aus:

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

Aber das hat nicht funktioniert. Ich erwarte, die Knoten zurückzubekommen:

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

Irgendwelche Hinweise?


Welche XPath-Implementierung ist das?
Pavel Minaev

Antworten:


174

Versuchen

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

Dies lautet:

  • Holen Sie sich alle bookElemente
    • das haben mindestens eine title
      • das hat ein Attribut lang
        • mit einem Wert von "it"

Vielleicht finden Sie dies hilfreich - es ist ein Artikel mit dem Titel "XPath in Five Paragraphs" von Ronald Bourret.

Aber ganz ehrlich, //book[title[@lang='it']]und das oben Genannte sollte gleichwertig sein, es sei denn, Ihre XPath-Engine hat "Probleme". Es könnte sich also um etwas im Code oder im Beispiel-XML handeln, das Sie uns nicht anzeigen. Beispielsweise ist Ihr Beispiel ein XML-Fragment. Könnte es sein, dass das Stammelement einen Namespace hat und Sie dies in Ihrer Abfrage nicht berücksichtigen? Und Sie haben uns nur gesagt, dass es nicht funktioniert hat, aber Sie haben uns nicht gesagt, welche Ergebnisse Sie erzielt haben.


4
Wie kann man dasselbe tun, wenn titleman kein direktes Kind ist book, sondern irgendwo tiefer und wir nicht genau wissen, wo? //book[/title/@lang = 'it']scheint nicht zu funktionieren?
Martin Konicek

5
Martin, du könntest //book[.//title/@lang = 'it'] verwenden. Ich glaube, der Trick ist das "." am Anfang der Bedingung.
Bruno Caponi

1
Danke für den Link, ausgezeichneter Artikel. Ich benutze xPath seit Jahren, aber das hat mir wirklich geholfen, die zugrunde liegende Logik zu verstehen!
Swensor

57

Jahre später wäre es jedoch eine nützliche Option, XPath-Achsen zu verwenden ( https://www.w3schools.com/xml/xpath_axes.asp) ). Insbesondere möchten Sie die Nachkommen verwenden Achsen .

Ich glaube, dieses Beispiel würde den Trick machen:

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

Auf diese Weise können Sie alle auswählen book Elemente , die ein Element enthaltentitle Element enthalten (unabhängig davon, wie tief es verschachtelt ist), dessen Sprachattributwert gleich 'it' ist.

Ich kann nicht sicher sagen, ob diese Antwort für das Jahr 2009 relevant ist oder nicht, da ich nicht 100% sicher bin, dass die XPath-Achsen zu diesem Zeitpunkt existierten. Was ich bestätigen kann, ist, dass sie heute existieren und ich habe festgestellt, dass sie in der XPath-Navigation äußerst nützlich sind, und ich bin sicher, dass Sie dies auch tun werden.


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

ist eigentlich gleichbedeutend mit

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

Ich habe es mit vtd-xml versucht. Beide Ausdrücke haben das gleiche Ergebnis erzielt. Welche xpath-Verarbeitungs-Engine haben Sie verwendet? Ich denke, es hat ein Konformitätsproblem. Unten ist der Code

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 dass es sich um ein Compliance-Problem handelt und dass die Syntax denselben Knotensatz generiert. Ähnlicher Code in C # funktioniert auch.
Zach Bonham

-1: Herr Zhang, ich habe versucht, Ihnen einen Gefallen zu tun, indem ich Code entfernt habe, der für die Frage nicht relevant ist. Es hat mir erlaubt, dich nicht herabzustimmen, was ich jetzt für nötig halte. Beachten Sie, dass keine andere Antwort Code zum Aufrufen der Abfrage enthielt.
John Saunders

6
+1: Weil ich nicht herausfinden kann, wovon Mr. Saunders spricht - keine andere Antwort hat JEDEN Code hinzugefügt, und diese Antwort zeigt den verwendeten Code, damit wir 1: seine Methoden validieren und 2: seinen Test selbst durchführen können. Der Code ist kurz und leicht zu lesen. Ich sehe das Problem nicht.
DuckPuppy

4

Ich würde denken, Ihr eigener Vorschlag ist richtig, aber die XML ist nicht ganz gültig. Wenn Sie das //book[title[@lang='it']]on <root>[Your"XML"Here]</root>ausführen, finden die kostenlosen Online-xPath-Tester wie hier das erwartete Ergebnis.


2

Versuchen Sie, diesen xPath-Ausdruck zu verwenden:

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

Das sollte Ihnen alle Buchknoten in "it" lang geben


2
Das Ergebnis dieses Ausdrucks sind die
Titelknoten

2
Das ist nicht wahr. Es werden Buchknoten zurückgegeben (diese beiden Punkte am Ende sollen auf den oberen Knoten des Titelknotens zielen).
user1113000
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.