2009-06-17 682 views

Respuesta

318

uso (/bookstore/book[@location='US'])[1]

Esta será la primera obtener los elementos del libro con la ubicación atribuyen igual a 'Estados Unidos'. Luego seleccionará el primer nodo de ese conjunto. Tenga en cuenta el uso de paréntesis, que algunas implementaciones requieren.

(tenga en cuenta que esto no es lo mismo que /bookstore/book[1][@location='US'] a menos que el primer elemento también pasa a tener ese atributo de ubicación )

+0

¿Cómo podría hacer lo mismo para // bookstore/book [@ location = 'US']? –

+7

Esto obtendrá todos los libros de 'EE. UU.' (/ bookstore/book [@ location = 'US']) [1] obtendrá el primero. –

+2

@KevinDriedger '/ bookstore/book [@ location = 'US'] [1]' no devuelve todos los libros de 'US'. Lo he probado varias veces y bajo diferentes idiomas 'implementaciones xpath. '/ bookstore/book [@ location = 'US'] [1]' devuelve el primer libro 'US' en una librería. Si hay varias librerías, devolverá la primera de cada una. Esto es lo que pidió el OP (el primer nodo en la librería). Su versión devuelve solo un libro de todas las librerías (la primera coincidencia). –

36

Como explicación a la respuesta de Jonathan Fingland:

  • múltiples condiciones en el mismo predicado ([position()=1 and @location='US']) debe ser verdad como un conjunto
  • múltiples condiciones en predicados consecutivos ([position()=1][@location='US']) debe ser verdad , uno tras otro
  • esto implica que [position()=1][@location='US'] = [@location='US'][position()=1]
    mientras [position()=1 and @location='US'] == [@location='US' and position()=1]
  • pista: un solitario [position()=1] puede abreviarse como [1]

Puede construir expresiones complejas en los predicados con el Operadores booleanos "and" y "or", y con las funciones booleanas XPath not(), true() y false(). Además, puede ajustar las expresiones parciales entre paréntesis.

+4

Esto sería una alternativa al segundo fragmento de código de xpath, que Jonathan Fingland observó que no daría los mismos resultados. La publicación original solicitó el primer nodo que coincidía con attrib, pero este xpath devuelve un nodo si es el primer nodo y tiene esa coincidencia attrib. – mirezus

+0

@alram: Esto es cierto. Gracias por la pista, modifiqué mi respuesta para ser más claro sobre este punto. – Tomalak

+0

Tomalak, sus notas son más claras, pero su respuesta sigue siendo incorrecta. La respuesta correcta está enterrada como el segundo selector en el punto 3 ([@ location = 'US'] [position() = 1]). Lo cual como señalaste refactores hasta la respuesta de Johnathan Fingland. No puede usar el 'y' con esta respuesta. –

149

/bookstore/book[@location='US'][1] funciona solo con estructura simple.

Agregue un poco más de estructura y cosas se rompen.

Con

<bookstore> 
<category> 
    <book location="US">A1</book> 
    <book location="FIN">A2</book> 
</category> 
<category> 
    <book location="FIN">B1</book> 
    <book location="US">B2</book> 
</category> 
</bookstore> 

/bookstore/category/book[@location='US'][1] produce

<book location="US">A1</book> 
<book location="US">B2</book> 
no

"el primer nodo que coincide con una condición más complicada". /bookstore/category/book[@location='US'][2] no devuelve nada.

Con paréntesis, se puede obtener el resultado de la pregunta original fue por:

(/bookstore/category/book[@location='US'])[1] da

<book location="US">A1</book> 

y (/bookstore/category/book[@location='US'])[2] funciona como se espera.

+21

¡Esto debería ser aceptado! No puedo entender cómo la respuesta aceptada obtuvo tanto votos ascendentes ... No funciona en absoluto cuando se trata de casos más complicados ... – korda

+9

Autor de la respuesta aceptada aquí. La pregunta de OP considera '/ bookstore/book [1]' y NOT '(/ bookstore/book) [1]'. El caso que proporcionó no es el mismo que el que solicitó OP. Es de suponer que OP aceptó mi respuesta porque hizo lo que esperaba (y solicitó). –

+0

Esta respuesta proporcionada me ayudó para este caso peculiar. ¿Alguien puede explicar por qué no manejará "situaciones más complicadas"? Como básicamente encuentra una lista con dos elementos, el [2] simplemente debería recogerlo (en mi mundo) – Skurpi

10

La forma más fácil de encontrar primer nodo libro de Inglés (en todo el documento), tomando en consideración archivo XML Structered más complicado, como:

<bookstore> 
<category> 
    <book location="US">A1</book> 
    <book location="FIN">A2</book> 
</category> 
<category> 
    <book location="FIN">B1</book> 
    <book location="US">B2</book> 
</category> 
</bookstore> 

es la expresión XPath:

/descendant::book[@location='US'][1] 

3
<bookstore> 
    <book location="US">A1</book> 
    <category> 
     <book location="US">B1</book> 
     <book location="FIN">B2</book> 
    </category> 
    <section> 
     <book location="FIN">C1</book> 
     <book location="US">C2</book> 
    </section> 
    </bookstore> 

Por lo tanto, dado lo anterior; Puede seleccionar el primer libro con

(//book[@location='US'])[1] 

Y este encontrará el primero en cualquier lugar que tenga una ubicación en EE. UU. [A1]

//book[@location='US'] 

Devolvería el conjunto de nodos con todos los libros con ubicación EE. UU. [A1, B1, C2]

(//category/book[@location='US'])[1] 

devolvería la primera ubicación de libros de Estados Unidos que existe en una categoría en cualquier parte del documento. [B1]

(/bookstore//book[@location='US'])[1] 

devolverá el primer libro con la ubicación de Estados Unidos que existe en cualquier lugar bajo el elemento raíz librería; haciendo que la/librería sea redundante en realidad. [A1]

En respuesta directa:

/bookstore/book[@location='US'][1] 

le devolverá el primer nodo de elemento de libro con la ubicación de Estados Unidos que se encuentra en la librería [A1]

Por cierto si usted quiere, en este ejemplo para encuentre el primer libro de EE. UU. que no fue un hijo directo de la librería:

(/bookstore/*//book[@location='US'])[1] 
+2

La mayoría de sus ejemplos con '//' y el uso del índice '[1]' son incorrectos. '// book [@ location = 'US'] [1]' selecciona los tres libros con 'location = 'US''. '// category/book [@ location = 'US'] [1]' devuelve un nodo pero solo porque tiene un nodo 'category'. '/ bookstore // book [@ location = 'US'] [1]' devuelve los tres libros "US" también, '/ bookstore/* // book [@ location = 'US'] [1]' en el otra mano devuelve dos nodos. – matt

+1

Estás en lo correcto; Me falta paréntesis; Editaré para agregarlos ... ¡No estoy seguro de cómo los extrañé a todos! – iZian

0

por ej.

<input b="demo"> 

Y

(input[@b='demo'])[1] 
+1

Por favor, especifique por qué su respuesta debería funcionar. –

0

Con la ayuda de una línea xpath tester Estoy escribiendo esta respuesta ...
Por esta:

<table id="t2"><tbody> 
<tr><td>123</td><td>other</td></tr> 
<tr><td>foo</td><td>columns</td></tr> 
<tr><td>bar</td><td>are</td></tr> 
<tr><td>xyz</td><td>ignored</td></tr> 
</tbody></table> 

la siguiente XPath:

id("t2")/tbody/tr/td[1] 

salidas:

123 
foo 
bar 
xyz 

Desde 1 medios seleccionar todos td elementos que son el primer hijo de su propia matriz directa.
Pero la siguiente XPath:

(id("t2")/tbody/tr/td)[1] 

salidas:

123 
2

utilizar el índice para obtener nodo deseado si XPath es complicado o más de un nodo presentes con igual XPath.

ex: (// librería [@location = 'EE.UU.']) [índice]

se puede dar el número que nodo que desee.

Cuestiones relacionadas