2010-11-02 14 views
11

Tengo una consulta XPath que está haciendo lo que quiero, es decir, seleccionando una unión de 'apellido' & 'nombres-dados' con los predicados dados (En realidad es o que necesito, pero la unión funciona bien):XPath seleccionando elementos múltiples con predicados

/header/authors/surname[./text() and @id='1'] 
| 
/header/authors/given-names[./text() and @id='1'] 

sin embargo, esto parece excesivamente largo aliento para mí y siento que debería ser posible de hacer algo más sucinto, tales como:

/header/authors/(surname|given-names)[./text() and @id='1'] 

pero esto ... la versión no es válida XPath.

¿Alguien puede decirme de una manera más ordenada de escribir la expresión XPath original que no requiere que la ruta completa se escriba dos veces?

Gracias

Richard

+0

¿Qué quiere decir con "cualquiera/o"? –

+0

@Alejandro: Dada una identificación, el elemento requerido podría ser 'apellido' o 'nombres de pila'. Eso es lo que estaba tratando de decir. Creo que es la unión que necesito. –

Respuesta

24

En primer lugar, esto es válido XPath 2.0:

/header/authors/(surname|given-names)[./text() and @id='1'] 

En segundo lugar, este XPath 1.0:

/header/authors/*[self::surname|self::given-names][text()][@id='1'] 
+1

Esto es excelente y estaba a punto de +1. Sin embargo, en la versión XPath 1.0 es mejor no usar '|' dentro del predicado. El operador correcto es 'o'. En este caso, la expresión aún selecciona los nodos deseados, pero en otros casos al sustituir 'o' con' | 'no se produce una expresión equivalente. +1, de todos modos. –

+1

@Dimitre: Tiene razón sobre '|' union set operator, pero lo he usado ** en este caso **, porque ambos términos son conjuntos de nodos (y porque la clave era sucinta). Lo mismo aplica para la secuencia de predicados. –

+0

Esta respuesta explica por qué sentí que debería poder usar '(apellido | nombres-dados)' (el proyecto actual no usa XPath 2.0) y también proporcioné una gran alternativa de XPath 1.0. Gracias. –

4

¿Qué tal

/header/authors/*[(name() = "surname" or name()="given-names") and ./text() and @id='1'] 
+0

Eso funcionará, pero si es más bonito ... – annakata

+0

Gracias por su respuesta. Sí salva guardar la ruta de acceso dos veces, pero todavía es un poco difícil de manejar en comparación con lo que tenía en mente. –

2

Además de Alejandro y de buenas respuestas de Seva, otra alternativa es

(/header/authors/surname | /header/authors/given-names)[text() and @id='1'] 

Esto es válido en XPath 1.0. Todavía es un poco redundante, pero es más sucinto que la versión larga en su pregunta.

Otra alternativa sería declarar una variable para elementos de apellido y una variable para elementos de nombre de pila, y luego

($surnames | $given-names)[text() and @id='1'] 

que probablemente sería más largo en total, pero más fácil de leer que los anteriores.

Cuestiones relacionadas