Cómo seleccionar el primer elemento con un atributo específico usando XPath

El XPath bookstore/book[1] selecciona el primer nodo de libro debajo bookstore.

¿Cómo puedo seleccionar el primer nodo que coincide con una condición más complicada, por ejemplo, el primer nodo que coincide /bookstore/book[@location='US']

preguntado el 17 de junio de 09 a las 07:06

9 Respuestas

Uso:

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

Esto primero obtendrá los elementos del libro con el atributo de ubicación igual a 'US'. Luego seleccionará el primer nodo de ese conjunto. Tenga en cuenta el uso de paréntesis, que son necesarios para algunas implementaciones.

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

Respondido el 26 de enero de 20 a las 05:01

¿Cómo podría hacer lo mismo para // librería / libro [@ location = 'US']? - Alejandro V. Ilyin

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

@Kevinsecadora /bookstore/book[@location='US'][1] no devuelve todos los libros de "EE. UU.". Lo he probado varias veces y bajo implementaciones xpath de diferentes lenguajes. /bookstore/book[@location='US'][1] devuelve el primer libro de "EE. UU." 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 debajo de la librería). Su versión devuelve solo un libro de todas las librerías (la primera coincidencia). - jonathan finlandia

@JonathanFingland, no entendiste: lee la respuesta de KevinDriedger nuevamente, junto con el contexto de la pregunta de AlexanderV.Ilyin. Ambos quieren decir lo mismo. - kiedysktos

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

Agrega un poco más de estructura y las 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] los rendimientos

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

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

Con paréntesis puede obtener el resultado para el que fue la pregunta original:

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

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

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

Respondido 11 Oct 20, 02:10

Autor de la respuesta aceptada aquí. La pregunta del OP considerada /bookstore/book[1] y no (/bookstore/book)[1]. El caso que ha proporcionado no es el mismo que solicitó OP. Presumiblemente, OP aceptó mi respuesta ya que hizo lo que esperaba (y solicitó). - jonathan finlandia

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

También encuentro que esta respuesta es más correcta que la respuesta seleccionada, como en mi caso, también tenía una estructura más compleja donde simplemente agregar [1] devolvía múltiples nodos. ¡Gracias! - midoghasgusanos

¡Los paréntesis funcionan! También puede agregar más ruta después de (..) [1], como: '(//div[text() = "'+ name +'"])[1]/following-sibling::*/div/text()'. En caso de que haya muchas coincidencias de nodos name. - colgado

Estoy cambiando de opinión. Después de cierta distancia, entiendo lo que decía esta respuesta, y si no hubiera visto el ejemplo del OP, habría votado por esto. Supongo que estaba reaccionando al tono de esta respuesta; si @tkurki hubiera explicado un poco más acerca de separar la condición de la selección del primer nodo, lo habría visto instantáneamente. Quizás lo mismo para JonFingland. - Gerard ONeill

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 todo
  • múltiples condiciones en predicados consecutivos ([position()=1][@location='US']) debe ser verdad Uno después del 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 crear expresiones complejas en predicados con los operadores booleanos "and"Y"or", y con las funciones booleanas XPath not(), true() y false(). Además, puede envolver subexpresiones entre paréntesis.

Respondido 27 ago 13, 22:08

La forma más fácil de encontrar el primer nodo de libro en inglés (en todo el documento), teniendo en cuenta un archivo xml estructurado 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]

contestado el 13 de mayo de 13 a las 16:05

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

Entonces, 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 Estados Unidos. [A1]

//book[@location='US']

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

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

Devolvería la primera ubicación del libro en EE. UU. 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 US que existe en cualquier lugar debajo de la librería del elemento raíz; haciendo que la parte de / bookstore sea realmente redundante. [A1]

En respuesta directa:

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

Le devolverá el primer nodo del elemento del libro con la ubicación en EE. UU. Que se encuentra debajo de la librería [A1]

Por cierto, si quisiera, en este ejemplo, encontrar el primer libro de EE. UU. Que no fue un hijo directo de la librería:

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

Respondido el 30 de diciembre de 16 a las 13:12

Utilice el índice para obtener el nodo deseado si xpath es complicado o hay más de un nodo presente con el mismo xpath.

Ejemplo:

(//bookstore[@location = 'US'])[index]

Puede dar el número de qué nodo desea.

Respondido 09 Oct 19, 14:10

si se proporciona un espacio de nombres en el xml dado, es mejor usarlo.

(/*[local-name() ='bookstore']/*[local-name()='book'][@location='US'])[1]

Respondido el 27 de junio de 19 a las 04:06

por ej.

<input b="demo">

Y también debes

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

respondido 17 mar '17, 13:03

Con la ayuda de un probador xpath Estoy escribiendo esta respuesta ...
Para esto:

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

el siguiente xpath:

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

salidas:

123
foo
bar
xyz

Como 1 significa seleccionar todo td elementos que son el primer hijo de su propio padre directo.
Pero el siguiente xpath:

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

salidas:

123

Respondido 15 Jul 17, 12:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.