¿Cómo seleccionar un nodo usando XPath si el nodo hermano tiene un valor específico?


88

Tengo el siguiente documento:

<a>
  <bb>abc</bb>
  <cc>ccc</cc>
  <dd>ddd</dd>
</a>
<a>
  <bb>zz</bb>
  <cc>1</cc>
  <dd>2</dd>
</a>

¿Cómo puedo obtener el valor de <cc>usar XPath si <bb>es así zz?


1
el problema es que sé cómo acceder a un nodo específico, pero no tengo idea de cómo acceder a un nodo si un hermano tiene un valor específico. ¿Puede ser algo como esto / a / cc / contains (/ a / bb = 'zz')?
HOE SENGKIANG

Respuestas:


100

No estoy seguro de por qué todo el mundo está consultando por hermanos, también puede verificar los <bb/>elementos que coincidan con el predicado del <a/>predicado de:

//a[bb/text() = "zz"]/cc/text()

24
"No estoy seguro de por qué todos preguntan por hermanos" : Quizás porque la pregunta era para hermanos ... ;-)
hr_117

4
Parece que en realidad no leí el título. :) La respuesta sigue siendo válida de todos modos.
Jens Erat

2
Sus preguntas de respuesta también para hermanos. Simplemente no usaste un *-siblingeje. +1 aunque.
LarsH

Esto no responde a la pregunta, pero responde a mi pregunta real que formulé mal. ¡Gracias!
User9213


23

P: ¿Cómo seleccionar un nodo usando XPath si el nodo hermano tiene un valor específico?
Debido a que solo hay "ejes XPath" para los hermanos siguientes y los hermanos anteriores, puede usar uno de ellos si la posición es fija.

Pero mejor: busque ccdónde el padre tiene un hijo bbcon valor 'zz':

//cc[../bb='zz']

6
O eso o //a[bb = 'zz']/cc.
Tomalak

No estoy seguro de lo que quiere decir con "solo" ejes XPath "para hermanos siguientes y hermanos anteriores". ¿Se refiere al hecho de que no existe un eje único para todos los hermanos?
LarsH

@LarsH: Sí, lo siento, (disculpe mi mal inglés :-() - eso era lo que estaba tratando de decir (porque la pregunta era para hermanos)
hr_117

6

En primer lugar, su ejemplo no es XML bien formado. Pasando por alto eso y que no describió muy bien sus intenciones (¿Qué es exactamente lo que desea seleccionar en qué condición?), Supongo que desea hacer esto:

//cc[preceding-sibling::bb[text()="zz"]]/text()

Selecciona

TEXT VALUES OF ALL <CC> ELEMENTS
//cc                                    /text()
    THAT HAVE A PRECEDING SIBLING <BB>
    [preceding-sibling::bb             ]
                          THAT HAS TEXT VALUE EQUAL TO "zz"
                          [text()="zz"]

Podrías escribir también es como

//bb[text()="zz"]/following-sibling::cc/text()

Mire la especificación , tiene algunos ejemplos muy legibles de los que aprenderá mucho.


1
@LarsH Gracias por la corrección de "no válido" a "no bien formado". Hoy aprendí algo nuevo.
Petr Janeček

4
//a/cc[../bb='zz']/text()

// a: Selecciona todos los elementos 'a' sin importar dónde se encuentren.

// a / cc: Selecciona los elementos 'cc' que son hijos del elemento 'a' (sin importar dónde esté a).

..: Selecciona el padre del nodo actual.

[../bb='zz ']: donde el valor del elemento hermano' bb 'es zz.

Referencia: http://www.w3schools.com/xsl/xpath_syntax.asp


4

Otra solución para este problema es

//bb[contains(.,'zz')]/../cc/text()

Explicación : Cualquiera bbque contenga una 'zz'cadena en todos los nodos secundarios de bbluego ir al nodo principal de ese bbuso .., ahora que podemos acceder al cctexto de retorno.

Espero que esa explicación no sea compleja.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.