2009-12-30 13 views
55

Teniendo en cuenta este XML:Usando XPath, ¿cómo selecciono un nodo en función de su contenido de texto y el valor de un atributo?

<DocText> 
<WithQuads> 
    <Page pageNumber="3"> 
     <Word> 
      July 
      <Quad> 
       <P1 X="84" Y="711.25" /> 
       <P2 X="102.062" Y="711.25" /> 
       <P3 X="102.062" Y="723.658" /> 
       <P4 X="84.0" Y="723.658" /> 
      </Quad> 
     </Word> 
     <Word> 
     </Word> 
     <Word> 
      30, 
      <Quad> 
       <P1 X="104.812" Y="711.25" /> 
       <P2 X="118.562" Y="711.25" /> 
       <P3 X="118.562" Y="723.658" /> 
       <P4 X="104.812" Y="723.658" /> 
      </Quad> 
     </Word> 
    </Page> 
</WithQuads> 

Me gustaría encontrar los nodos que tienen texto de 'Julio' y un Quad/P1/X atributo mayor que 90. Por lo tanto, en este caso, no debería devolver ninguna coincidencia. Sin embargo, si uso GT (>) o LT (<), obtengo una coincidencia en el primer elemento de Word. Si uso eq (=), no obtengo ninguna coincidencia.

Así:

//Word[text()='July' and //P1[@X < 90]] 

volverá cierto, como se

//Word[text()='July' and //P1[@X > 90]] 

¿Cómo limitar esto correctamente en el atributo P1 @ X?

Además, imagine que tengo varios elementos de página, para diferentes números de página. ¿Cómo puedo restringir adicionalmente la búsqueda anterior para buscar Nodos con text()='July', [email protected] < 90 y Página @pageNumber=3?

+0

Una cosa importante a tener en cuenta con este XML particular que puede no ser obvio para cada lector, es que debido a que este XML usa un modelo de contenido mixto es complicado combinar elementos con XPath. Me encontré con este tema recientemente y, estando oxidado con mi XPath, estaba a punto de concluir que no se podían combinar elementos de contenido mixto hasta que encontré la respuesta de Michael Kay a continuación. No he podido encontrar ninguna otra referencia que trate sobre trampas con contenido mixto y XPath. –

+0

Su pregunta respondió mi pregunta. Es muy importante utilizar 'apóstrofes únicos' para cadenas en XPath, no "comillas dobles". Es realmente muy importante Gracias por la pista. –

Respuesta

66

En general, consideraría el uso de un // no prefijado como un mal olor en un XPath.

Prueba esto: -

/DocText/WithQuads/Page/Word[text()='July' and Quad/P1/@X > 90] 

Su problema es que se utiliza el //P1[@X < 90] que comienza volver al principio del documento e inicia la caza de cualquier P1 por lo que siempre será cierto. Del mismo modo, //P1[@X > 90] es siempre cierto.

+1

Me sorprende que esto, de hecho, funcionó debido a los problemas de espacio en blanco que se abordaron en la respuesta de Michael Kay. Intenté esta respuesta en un par de diferentes evaluadores de XPath y no coincidió con ninguno de los dos. Una vez que cambié al predicado con 'normalize-space', hice una coincidencia exitosa. –

23

Aparte del problema "//", este XML es un uso muy extraño de contenido mixto. El predicado text()='July' coincidirá con el elemento si cualquier nodo de texto hijo es exactamente igual a julio, lo cual no es cierto en su ejemplo debido al espacio en blanco circundante. Dependiendo de la definición exacta de la fuente XML, me gustaría ir a [text()[normalize-space(.)='July'] and Quad/P1/@X > 90]

+0

gracias, Michael. Me preguntaba sobre el espacio en blanco ... He formateado la muestra antes de pegarla en el desbordamiento de la pila, pero mi XML fuente es todo "ajustado". Cuando ejecuté xpath contra la versión formateada, no funcionó correctamente. Trataré de usar normalize-space (.) –

Cuestiones relacionadas