Tengo un pequeño problema con Xpath contiene dom4j ...
Digamos que mi XML es
<Home>
<Addr>
<Street>ABC</Street>
<Number>5</Number>
<Comment>BLAH BLAH BLAH <br/><br/>ABC</Comment>
</Addr>
</Home>
Digamos que quiero encontrar todos los nodos que tienen ABC en el texto dado el Elemento raíz ...
Entonces, el xpath que necesitaría escribir sería
//*[contains(text(),'ABC')]
Sin embargo, esto no es lo que devuelve Dom4j ... es un problema de dom4j o mi comprensión de cómo funciona xpath. dado que esa consulta solo devuelve el elemento Street y no el elemento Comment.
El DOM hace que el elemento Comentario sea un elemento compuesto con cuatro etiquetas dos
[Text = 'XYZ'][BR][BR][Text = 'ABC']
Supongo que la consulta aún debería devolver el elemento, ya que debería encontrar el elemento y ejecutarlo, pero no ...
la siguiente consulta devuelve el elemento pero devuelve mucho más que solo el elemento, también devuelve los elementos principales ... lo que no es deseable para el problema ...
//*[contains(text(),'ABC')]
¿Alguien sabe la consulta xpath que devolvería solo los elementos <Street/>
y <Comment/>
?
//*[contains(text(),'ABC')]
solo devuelve el<Street>
elemento. No devuelve ningún antepasado de<Street>
o<Comment>
.Respuestas:
La
<Comment>
etiqueta contiene dos nodos de texto y dos<br>
nodos como elementos secundarios.Tu expresión xpath fue
Para romper esto,
*
es un selector que coincide con cualquier elemento (es decir, etiqueta); devuelve un conjunto de nodos.[]
son un condicional que opera en cada nodo individual en ese conjunto de nodos. Coincide si alguno de los nodos individuales en los que opera coincide con las condiciones dentro de los corchetes.text()
es un selector que coincide con todos los nodos de texto que son hijos del nodo de contexto; devuelve un conjunto de nodos.contains
es una función que opera en una cadena. Si se pasa un conjunto de nodos, el conjunto de nodos se convierte en una cadena al devolver el valor de cadena del nodo en el conjunto de nodos que está primero en el orden del documento . Por lo tanto, solo puede coincidir con el primer nodo de texto en su<Comment>
elemento, es decirBLAH BLAH BLAH
. Como eso no coincide, no obtienes un<Comment>
resultado en tus resultados.Necesitas cambiar esto a
*
es un selector que coincide con cualquier elemento (es decir, etiqueta); devuelve un conjunto de nodos.[]
son un condicional que opera en cada nodo individual en ese conjunto de nodos; aquí opera en cada elemento del documento.text()
es un selector que coincide con todos los nodos de texto que son hijos del nodo de contexto; devuelve un conjunto de nodos.[]
son un condicional que opera en cada nodo en ese conjunto de nodos, aquí cada nodo de texto individual. Cada nodo de texto individual es el punto de partida para cualquier ruta entre paréntesis, y también se puede mencionar explícitamente como.
dentro de los paréntesis. Coincide si alguno de los nodos individuales en los que opera coincide con las condiciones dentro de los corchetes.contains
es una función que opera en una cadena. Aquí se pasa un nodo de texto individual (.
). Como se pasa el segundo nodo de texto en la<Comment>
etiqueta individualmente, verá la'ABC'
cadena y podrá hacerla coincidir.fuente
//*[contains(., 'ABC')]
. Siempre había usado el patrón dado por Mike Milkin, pensando que era más apropiado, pero hacercontains
lo que quiero en el contexto actual parece ser lo que quiero con más frecuencia.[contains(text(),'')]
solo devuelve verdadero o falso. No devolverá ningún resultado de elemento.fuente
contains(text(),'JB-')
no es trabajo!conatains
toma dos cadenas como argumentos -contains(**string**, **string**)
! ¡text () no es una cadena , es una función!El documento XML:
La expresión XPath:
//*
coincide con cualquier elemento descendiente del nodo raíz . Es decir, cualquier elemento menos el nodo raíz.[...]
es un predicado , filtra el conjunto de nodos. Devuelve nodos para los cuales...
estrue
:contains('haystack', 'needle')
devuelvetrue
sihaystack
contieneneedle
:Pero
contains()
toma una cadena como primer parámetro. Y ha pasado nodos. Para lidiar con eso, cada nodo o conjunto de nodos pasado como primer parámetro se convierte en una cadena por lastring()
función:string()
función devuelvestring-value
del primer nodo :string-value
de un nodo de elemento :string-value
de un nodo de texto :Entonces, básicamente
string-value
todo el texto está contenido en un nodo (concatenación de todos los nodos de texto descendientes).text()
es una prueba de nodo que coincide con cualquier nodo de texto:Dicho esto,
//*[contains(text(), 'ABC')]
coincide con cualquier elemento (excepto el nodo raíz), cuyo primer nodo de texto contieneABC
. Dado quetext()
devuelve un conjunto de nodos que contiene todos los nodos de texto secundarios del nodo de contexto (en relación con el cual se evalúa una expresión). Perocontains()
solo toma el primero. Entonces, para el documento de arriba, la ruta coincide con elStreet
elemento.La siguiente expresión
//*[text()[contains(., 'ABC')]]
coincide con cualquier elemento (pero el nodo raíz), que tiene al menos un nodo de texto secundario, que contieneABC
..
representa el nodo de contexto. En este caso, es un nodo de texto hijo de cualquier elemento que no sea el nodo raíz. Entonces, para el documento de arriba, la ruta coincide conStreet
losComment
elementos.Ahora bien,
//*[contains(., 'ABC')]
coincide con cualquier elemento (pero el nodo raíz) que contieneABC
(en la concatenación de los nodos de texto descendientes). Para el documento anterior, coincide con los elementosHome
, theAddr
, theStreet
y theComment
. Como tal,//*[contains(., 'BLAH ABC')]
coincide con los elementosHome
, theAddr
y theComment
.fuente
Me tomó un tiempo, pero finalmente lo descubrí. Xpath personalizado que contiene algo de texto a continuación funcionó perfectamente para mí.
fuente
contains(text(),'JB-')
no es trabajo!conatains
toma dos cadenas como argumentos -contains(**string**, **string**)
! ¡text () no es una cadena , es una función!La respuesta aceptada también devolverá todos los nodos principales. Para obtener solo los nodos reales con ABC incluso si la cadena es posterior
:
fuente
devoluciones
fuente