Eu tenho um pequeno problema com o Xpath contém com dom4j ...
Vamos dizer que meu XML é
<Home>
<Addr>
<Street>ABC</Street>
<Number>5</Number>
<Comment>BLAH BLAH BLAH <br/><br/>ABC</Comment>
</Addr>
</Home>
Vamos dizer que eu quero encontrar todos os nós que têm ABC no texto, dado o elemento raiz ...
Então o xpath que eu precisaria escrever seria
//*[contains(text(),'ABC')]
No entanto, não é isso que o Dom4j retorna .... esse é um problema do dom4j ou eu entendo como o xpath funciona. pois essa consulta retorna apenas o elemento Street e não o elemento Comment.
O DOM torna o elemento Comment um elemento composto com quatro tags dois
[Text = 'XYZ'][BR][BR][Text = 'ABC']
Eu assumiria que a consulta ainda deve retornar o elemento, uma vez que deve encontrar o elemento e executar contém nele, mas não ... ...
a consulta a seguir retorna o elemento, mas retorna muito mais do que apenas o elemento, retorna os elementos pai também ... o que é indesejável para o problema ...
//*[contains(text(),'ABC')]
Alguém conhece a consulta xpath que retornaria apenas os elementos <Street/>
e <Comment/>
?
//*[contains(text(),'ABC')]
retorna apenas o<Street>
elemento. Não retorna nenhum ancestral de<Street>
ou<Comment>
.Respostas:
A
<Comment>
tag contém dois nós de texto e dois<br>
nós como filhos.Sua expressão xpath foi
Para quebrar isso,
*
é um seletor que corresponde a qualquer elemento (ou seja, tag) - ele retorna um conjunto de nós.[]
são uma condicional que opera em cada nó individual nesse conjunto nó. Corresponde se algum dos nós individuais em que opera corresponder às condições dentro dos colchetes.text()
é um seletor que corresponde a todos os nós de texto filhos do nó de contexto - ele retorna um conjunto de nós.contains
é uma função que opera em uma string. Se for passado um conjunto de nós, o conjunto de nós será convertido em uma sequência retornando o valor da sequência do nó no conjunto de nós que é o primeiro na ordem do documento . Portanto, ele pode corresponder apenas ao primeiro nó de texto no seu<Comment>
elemento - ou sejaBLAH BLAH BLAH
. Como isso não corresponde, você não obtém<Comment>
resultados nos resultados.Você precisa alterar isso para
*
é um seletor que corresponde a qualquer elemento (ou seja, tag) - ele retorna um conjunto de nós.[]
é um condicional que opera em cada nó individual nesse conjunto de nós - aqui, ele opera em cada elemento do documento.text()
é um seletor que corresponde a todos os nós de texto filhos do nó de contexto - ele retorna um conjunto de nós.[]
é um condicional que opera em cada nó nesse conjunto de nós - aqui cada nó de texto individual. Cada nó de texto individual é o ponto de partida para qualquer caminho entre parênteses e também pode ser referido explicitamente como.
entre parênteses. Corresponde se algum dos nós individuais em que opera corresponder às condições dentro dos colchetes.contains
é uma função que opera em uma string. Aqui é passado um nó de texto individual (.
). Como é passado o segundo nó de texto na<Comment>
tag individualmente, ele verá a'ABC'
sequência e poderá correspondê-la.fonte
//*[contains(., 'ABC')]
. Eu sempre usei o padrão dado por Mike Milkin, pensando que era mais apropriado, mas apenas fazercontains
no contexto atual parece realmente ser o que eu quero com mais frequência.[contains(text(),'')]
retorna apenas verdadeiro ou falso. Não retornará nenhum resultado de elemento.fonte
contains(text(),'JB-')
não é trabalho!conatains
usa duas strings como argumentos -contains(**string**, **string**)
! text () não é string , é uma função!O documento XML:
A expressão XPath:
//*
corresponde a qualquer elemento descendente do nó raiz . Ou seja, qualquer elemento, exceto o nó raiz.[...]
é um predicado , filtra o conjunto de nós. Retorna nós para os quais...
étrue
:contains('haystack', 'needle')
retornatrue
sehaystack
contémneedle
:Mas
contains()
usa uma string como seu primeiro parâmetro. E são nós passados. Para lidar com isso, todos os nós ou conjuntos de nós transmitidos como o primeiro parâmetro são convertidos em uma cadeia de caracteres pelastring()
função:string()
retornosstring-value
da função do primeiro nó :string-value
de um nó do elemento :string-value
de um nó de texto :Portanto, basicamente,
string-value
todo o texto está contido em um nó (concatenação de todos os nós de texto descendentes).text()
é um teste de nó que corresponde a qualquer nó de texto:Dito isto,
//*[contains(text(), 'ABC')]
corresponde a qualquer elemento (exceto o nó raiz), cujo primeiro nó de texto contémABC
. Desdetext()
retorna um conjunto de nós que contém todos os nós de texto filho do nó de contexto (em relação aos quais uma expressão é avaliada). Mascontains()
leva apenas o primeiro. Portanto, para o documento acima, o caminho corresponde aoStreet
elemento.A expressão a seguir
//*[text()[contains(., 'ABC')]]
corresponde a qualquer elemento (exceto o nó raiz), que possui pelo menos um nó de texto filho, que contémABC
..
representa o nó de contexto. Nesse caso, é um nó de texto filho de qualquer elemento, exceto o nó raiz. Portanto, para o documento acima, o caminho correspondeStreet
aosComment
elementos e.Agora,
//*[contains(., 'ABC')]
corresponde a qualquer elemento (exceto o nó raiz) que contémABC
(na concatenação dos nós de texto descendentes). Para o documento acima, ele corresponde aos elementos theHome
, theAddr
, theStreet
eComment
. Como tal,//*[contains(., 'BLAH ABC')]
coincide com osHome
, osAddr
, e osComment
elementos.fonte
Demorei um pouco, mas finalmente descobri. O xpath personalizado que contém algum texto abaixo funcionou perfeitamente para mim.
fonte
contains(text(),'JB-')
não é trabalho!conatains
usa duas strings como argumentos -contains(**string**, **string**)
! text () não é string , é uma função!A resposta aceita retornará todos os nós pais também. Para obter apenas os nós reais com ABC, mesmo que a sequência seja posterior
:
fonte
retorna
fonte