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

HOE SENGKIANG
fuente
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()
Jens Erat
fuente
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']
hr_117
fuente
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.

Petr Janeček
fuente
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

Bae Cheol Shin
fuente
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.

Saleh Mahmood
fuente