2009-09-22 12 views
74

Załóżmy, że mam następujące XML:XPath: Get węzły gdzie węzeł dziecko zawiera atrybut

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

chciałbym zrobić XPath że wróci wszystkie węzły książek, które mają węzeł tytułowy z języka atrybut "to".

Moja próba wyglądała mniej więcej tak:

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

Ale to nie działa. Spodziewam się wrócić węzły:

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

Wszelkie wskazówki? Z góry dziękuję.

+0

Jaka jest implementacja XPath? –

Odpowiedz

131

Spróbuj

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

To brzmi:

  • uzyskać wszystkie book elementy
    • , które mają co najmniej jeden title
      • który ma atrybut lang
        • o wartości "it"

Możesz wybrać this pomocny - to artykuł zatytułowany "XPath in Five Paragraphs" Ronald Bourret.

Ale szczerze mówiąc, //book[title[@lang='it']] i powyższe powinny być równoważne, chyba że twój silnik XPath ma "problemy". Może to być coś w kodzie lub przykładowym kodzie XML, którego nam nie pokazujesz - na przykład Twoja próbka jest fragmentem XML. Czy to możliwe, że element główny ma przestrzeń nazw i nie liczysz na to w zapytaniu? Powiedziałeś nam tylko, że to nie działa, ale nie powiedziałeś nam, jakie masz rezultaty.

+0

mm, ciekawa lektura. –

+1

Jak zrobić to samo, jeśli "tytuł" nie jest bezpośrednim dzieckiem "książki", ale gdzieś głębiej i nie wiemy gdzie dokładnie? '// book [/ title/@ lang = 'it']' wydaje się nie działać? –

+0

+1 dla artykułu Ronalda Bourreta: – w5m

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

jest rzeczywiście równoważne

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

Próbowałem go za pomocą VTD-xml, oba wyrażenia wypluć ten sam wynik ... co XPath przetwarzanie silnik nie używasz?Chyba że ma potwierdzeń, problem Poniżej znajduje się kod

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

     } 
    } 
} 
+0

+1, że jest to problem zgodności i że składnia generuje ten sam zestaw węzłów. Działa również podobny kod w języku C#. –

+0

-1: Panie Zhang, próbowałem wyświadczyć przysługę, usuwając kod niezwiązany z pytaniem. Pozwoliło mi to nie poprowadzić cię, co teraz uważam za konieczne. Zauważ, że żadna inna odpowiedź nie zawierała kodu wywołującego zapytanie. –

+4

+1: Ponieważ nie mogę rozgryźć, o czym mówi pan Saunders - żadna inna odpowiedź nie dodała KAŻDEGO kodu, a ta odpowiedź pokazuje użyty kod, abyśmy mogli 1: potwierdzić swoje metody i 2: wykonać test samemu. Kod jest krótki i łatwy do odczytania. Nie widzę problemu. – DuckPuppy

2

Spróbuj skorzystać z tej XPath wyrażenie:

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

To powinno dać ci wszystkie węzły książkę w „to” lang

+0

wynikiem tego wyrażenia są węzły tytułowe, a nie węzły książki – Caleth

2

bym uważam, że twoja własna sugestia jest poprawna, jednak xml nie jest całkiem poprawny. Jeśli używasz //book[title[@lang='it']] na <root>[Your"XML"Here]</root>, wtedy bezpłatne testery online xPath, takie jak jeden here, znajdą oczekiwany wynik.

30

Wiele lat później, ale użyteczną opcją byłoby wykorzystanie osi XPath (https://www.w3schools.com/xml/xpath_axes.asp). Dokładniej, chcesz użyć osi potomnych.

Uważam ten przykład by rade:

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

Pozwala to na wybranie wszystkich book elementy, które zawierają element dziecko title (niezależnie od tego, jak głęboko jest zagnieżdżona) zawierające wartość atrybutu języka równą " to'.

Nie mogę powiedzieć na pewno, czy ta odpowiedź ma znaczenie dla roku 2009, ponieważ nie jestem w 100% pewna, czy w tym czasie istniały Osie XPath. Mogę potwierdzić, że istnieją one dzisiaj i okazało się, że są bardzo przydatne w nawigacji XPath i jestem pewien, że również.

Powiązane problemy