2009-09-22 25 views
74

Supongamos que tengo el siguiente código XML:XPath: Obtener nodos donde nodo secundario contiene un atributo

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

me gustaría hacer un XPath que vuelve todos los nodos de libros que tienen un nodo título con un lenguaje atributo de "eso".

Mi intento parecía algo como esto:

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

Pero eso no funcionó. Espero que volver los nodos:

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

¿Alguna pista? Gracias por adelantado.

+0

¿Qué implementación de XPath es esto? –

Respuesta

131

Trate

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

Esto lee:

  • obtener todos los elementos book
    • que tienen al menos un title
      • que tiene un atributo lang
        • con un valor de "it"

Usted puede encontrar útil this - es un artículo titulado "XPath in Five Paragraphs" por Ronald Bourret.

Pero honestamente, //book[title[@lang='it']] y lo anterior deben ser equivalentes, a menos que su motor XPath tenga "problemas". Por lo tanto, podría ser algo en el código o XML de muestra que no nos muestre, por ejemplo, su muestra es un fragmento XML. ¿Podría ser que el elemento raíz tenga un espacio de nombres y no cuente para eso en su consulta? Y solo nos dijiste que no funcionó, pero no nos dijiste qué resultados obtuviste.

+0

mm, lectura interesante. –

+1

¿Cómo hacer lo mismo si 'title' no es un hijo directo de' book', pero en algún lugar más profundo y no sabemos dónde exactamente? '// book [/ title/@ lang = 'it']' no parece funcionar? –

+0

+1 para el artículo de Ronald Bourret – w5m

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

es en realidad equivalente a

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

lo probé usando ETV-xml, ambas expresiones escupir el mismo resultado ... lo motor de procesamiento de XPath ha utilizado?Supongo que tiene problema de la conformidad A continuación se muestra el código

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 que es un problema de cumplimiento y que la sintaxis genera el mismo conjunto de nodos. Código similar en C# también funciona. –

+0

-1: Sr. Zhang, estaba tratando de hacerle un favor eliminando el código que no es relevante para la pregunta. Me permitió no rechazarte, lo que ahora siento que debo hacer. Tenga en cuenta que ninguna otra respuesta incluye código para llamar a la consulta. –

+4

+1: Como no puedo entender de qué habla el Sr. Saunders, ninguna otra respuesta agregó NINGÚN código, y esta respuesta muestra el código utilizado para que podamos 1: validar sus métodos y 2: realizar su prueba nosotros mismos. El código es corto y fácil de leer. No veo el problema. – DuckPuppy

2

intenta utilizar esta expresión XPath:

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

que se debe dar a todos los nodos de libros en "eso" lang

+0

el resultado de esa expresión son los nodos del título, no los nodos del libro – Caleth

2

lo haría piense que su sugerencia es correcta, sin embargo, el xml no es completamente válido. Si está ejecutando el //book[title[@lang='it']] en <root>[Your"XML"Here]</root>, entonces los probadores de xPath en línea gratuitos como uno here encontrarán el resultado esperado.

30

Años después, pero una opción útil sería utilizar XPath Axes (https://www.w3schools.com/xml/xpath_axes.asp). Más específicamente, está buscando utilizar los descendientes ejes.

Creo que este ejemplo sería hacer el truco:

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

Esto le permite seleccionar todos los book elementos que contienen un elemento hijo title (independientemente de qué tan profundo es anidada) que contiene el valor del atributo lengua igual a ' eso'.

No puedo decir con certeza si esta respuesta es relevante para el año 2009 ya que no estoy 100% seguro de que los ejes XPath existían en ese momento. Lo que puedo confirmar es que sí existen hoy y he encontrado que son extremadamente útiles en la navegación XPath y estoy seguro de que también lo harán.

Cuestiones relacionadas