2010-01-29 31 views
8

tengo el siguiente código XML:Seleccionar un nodo específico en XPath

<parent> 
    <pet> 
     <data> 
     <birthday/> 
     </data> 
    </pet> 
    <pet> 
     <data> 
     <birthday/> 
     </data> 
    </pet> 
</parent> 

Y ahora quiero seleccionar el primer elemento de cumpleaños a través de parent//birthday[1] pero esto devuelve los dos elementos de cumpleaños porque bothof ellos son el primer hijo de sus padres . ¿Cómo solo puedo seleccionar el primer elemento de cumpleaños de todo el documento sin importar dónde esté ubicado? He intentado parent//birthday[position()=1], pero eso tampoco funciona.

Saludos

+0

Lo XPath herramienta/biblioteca está usando? –

Respuesta

12

¿Quiere decir (tenga en cuenta los paréntesis!)

(/parent/pet/data/birthday)[1]

o, más corto, pero menos descriptiva

(/*/*/*/birthday)[1]

o, mejor, porque semánticamente correcta:

/parent/pet[1]/data/birthday

o , si no todas las mascotas tienen entradas de cumpleaños:

/parent/pet[data/birthday][1]/data/birthday

En cualquier caso, evitar el uso de // porque es computacionalmente caro (recursivamente prueba cada nodo en el documento). Cuando la estructura del documento es fija y conocida, es fácil de evitar.

Si trabaja desde un nodo de contexto, puede abreviar la expresión haciéndola relativa a ese nodo de contexto.

Breve explicación:

  • /parent/pet/data/birthday[1] selecciona todos <birthday> nodos que son los primeros en sus respectivos padres (los <data> nodos), en todo el documento
  • (/parent/pet/data/birthday)[1] selecciona todos <birthday> linfáticos, y de los (eso es lo que hacen los paréntesis, crean un conjunto de nodos intermedios), toma el primero
+0

Gracias. Sabía que tenía que haber una manera más fácil. –

+0

> evitar el uso // Estoy asumiendo que tiene que usarlo teniendo en cuenta la redacción aquí: > ¿Cómo puedo seleccionar sólo el primer elemento de cumpleaños de todo el documento, sin importar dónde se encuentra – igor

+0

@igor: Estaba haciendo una conjetura educada basada en la estructura de entrada de muestra XML. Los elementos de cumpleaños que no son descendientes de elementos de mascota me parecieron improbables en este caso. – Tomalak

-1

tratan

//birthday[position()=1] 

// encuentra nodos no importa donde hay en la jerarquía

también se puede hacer

pet[position()=1]/data/birthday 
+0

Eso me da el mismo resultado, todavía obtengo los dos elementos de cumpleaños – Benjamin

+0

Eso no me funciona. Devuelve 2 elementos. –

+0

Es cierto, pero el problema es que cuando ejecuto mi expresión xpath solo sé que debe haber un par de elementos de cumpleaños en el documento, no hago nada acerca de la mascota – Benjamin

1

Ok, admito que esto es horrible y debe haber una mejor manera, pero parece funcionar.

/*/*[descendant::birthday and not(preceding-sibling::*[descendant::birthday])] 

miro para todos los elementos del segundo nivel en el árbol que tiene un elemento llamado descendiente de cumpleaños que no tienen un elemento hermano precedente que tiene un elemento de cumpleaños como un descendiente.

+0

si hubiera elementos alternantes de 'mascota' con y sin descendientes de 'cumpleaños', esto coincidiría con todos aquellos con un 'cumpleaños', no solo con el primero. – carillonator

+0

No, no lo haría porque el eje hermano anterior mira a todos los hermanos anteriores, no solo al anterior. –

0
<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

    <xsl:template match="/"> 
     <xsl:variable name="birthdays" select="//birthday"/> 
     <xsl:value-of select="$birthdays[1]"/> 
    </xsl:template> 

</xsl:stylesheet> 
4

FYI: puede visualizar los resultados de varias consultas Xpath con el (libre) XPathVisualizer tool. Funciona solo en Windows.

alt text http://i50.tinypic.com/f8apd.jpg

+0

** Excelente ** herramienta. Ideal para la práctica, así como también cuando tienes problemas con XML. –

+0

Desafortunadamente, esto no parece ser compatible con Windows 10 64bit – AndyHerb

Cuestiones relacionadas