Mam mały problem z Xpath zawiera dom4j ...
Powiedzmy, że mój XML to
<Home>
<Addr>
<Street>ABC</Street>
<Number>5</Number>
<Comment>BLAH BLAH BLAH <br/><br/>ABC</Comment>
</Addr>
</Home>
Powiedzmy, że chcę znaleźć wszystkie węzły, które mają ABC w tekście, biorąc pod uwagę element główny ...
Więc xpath, którą musiałbym napisać, to
//*[contains(text(),'ABC')]
Jednak nie to zwraca Dom4j .... to jest problem z dom4j lub moje zrozumienie, jak działa xpath. ponieważ to zapytanie zwraca tylko element Street, a nie element Comment.
DOM sprawia, że element komentarza jest elementem złożonym z czterema znacznikami dwoma
[Text = 'XYZ'][BR][BR][Text = 'ABC']
Zakładam, że zapytanie powinno nadal zwracać element, ponieważ powinno ono znaleźć element i uruchomić na nim, ale nie ...
następujące zapytanie zwraca element, ale zwraca znacznie więcej niż tylko element, zwraca również elementy nadrzędne ... co jest niepożądane dla problemu ...
//*[contains(text(),'ABC')]
Czy ktoś zna zapytanie xpath, które zwróci tylko elementy <Street/>
i <Comment/>
?
//*[contains(text(),'ABC')]
zwraca tylko<Street>
element. Nie zwraca żadnych przodków<Street>
ani<Comment>
.Odpowiedzi:
<Comment>
Tag zawiera dwa węzły tekstowe i dwa<br>
węzły jak dzieci.Twoje wyrażenie xpath było
Aby to rozbić,
*
jest selektorem pasującym do dowolnego elementu (tj. znacznika) - zwraca zestaw węzłów.[]
Są warunkowe, które działa na każdym węźle w tym zbiorze węzłów. Dopasowuje, jeśli którykolwiek z poszczególnych węzłów, na których działa, odpowiada warunkom w nawiasach.text()
to selektor pasujący do wszystkich węzłów tekstowych, które są potomkami węzła kontekstowego - zwraca zestaw węzłów.contains
to funkcja działająca na łańcuchu. Jeśli zostanie przekazany zestaw węzłów, zestaw węzłów jest konwertowany na ciąg znaków, zwracając wartość ciągu węzła w zestawie węzłów, który jest najpierw w kolejności dokumentów . Dlatego może pasować tylko do pierwszego węzła tekstowego w<Comment>
elemencie - mianowicieBLAH BLAH BLAH
. Ponieważ to się nie zgadza, wyniki nie są wyświetlane<Comment>
.Musisz to zmienić na
*
jest selektorem pasującym do dowolnego elementu (tj. znacznika) - zwraca zestaw węzłów.[]
to warunek, który działa na każdym pojedynczym węźle w tym zestawie węzłów - tutaj działa na każdym elemencie w dokumencie.text()
to selektor pasujący do wszystkich węzłów tekstowych, które są potomkami węzła kontekstowego - zwraca zestaw węzłów.[]
to warunek, który działa na każdym węźle w tym zestawie węzłów - tutaj każdy pojedynczy węzeł tekstowy. Każdy pojedynczy węzeł tekstowy jest punktem początkowym dowolnej ścieżki w nawiasach, a także może być jawnie określany.
w nawiasach. Dopasowuje, jeśli którykolwiek z poszczególnych węzłów, na których działa, odpowiada warunkom w nawiasach.contains
to funkcja działająca na łańcuchu. Tutaj przekazywany jest pojedynczy węzeł tekstowy (.
). Ponieważ jest on przekazywany<Comment>
osobno do drugiego węzła tekstowego w znaczniku, zobaczy'ABC'
łańcuch i będzie mógł go dopasować.źródło
//*[contains(., 'ABC')]
. Zawsze korzystałem ze wzoru podanego przez Mike'a Milkina, myśląc, żecontains
byłby bardziej odpowiedni, ale po prostu robienie tego w obecnym kontekście wydaje się faktycznie tym, czego chcę częściej.[contains(text(),'')]
zwraca tylko prawdę lub fałsz. Nie zwróci żadnych wyników elementów.źródło
contains(text(),'JB-')
to nie praca!conatains
przyjmuje dwa ciągi jako argumenty -contains(**string**, **string**)
! text () nie jest łańcuchem , jest funkcją!Dokument XML:
Wyrażenie XPath:
//*
pasuje do każdego potomka elementu z węzła głównego . Oznacza to, że każdy element oprócz węzła głównego.[...]
jest predykatem , filtruje zestaw węzłów. Zwraca węzły, dla których...
jesttrue
:contains('haystack', 'needle')
zwraca,true
jeślihaystack
zawieraneedle
:Ale
contains()
jako pierwszy parametr przyjmuje ciąg. I to przeszedł węzły. Aby sobie z tym poradzić, każdy węzeł lub zestaw węzłów przekazany jako pierwszy parametr jest konwertowany na ciąg przezstring()
funkcję:string()
funkcja zwracastring-value
z pierwszego węzła :string-value
o węzeł elementu :string-value
z węzła tekstowego :Zasadniczo
string-value
jest to cały tekst zawarty w węźle (konkatenacja wszystkich potomnych węzłów tekstowych).text()
to test węzła pasujący do dowolnego węzła tekstowego:Powiedziawszy to,
//*[contains(text(), 'ABC')]
pasuje do dowolnego elementu (oprócz węzła głównego), którego pierwszy węzeł tekstowy zawieraABC
. Ponieważtext()
zwraca zestaw węzłów, który zawiera wszystkie potomne węzły tekstowe węzła kontekstu (w odniesieniu do którego oceniane jest wyrażenie). Alecontains()
bierze tylko pierwszy. Tak więc dla dokumentu powyżej ścieżka pasuje doStreet
elementu.Poniższe wyrażenie
//*[text()[contains(., 'ABC')]]
pasuje do dowolnego elementu (oprócz węzła głównego), który zawiera co najmniej jeden potomny węzeł tekstowy, który zawieraABC
..
reprezentuje węzeł kontekstu. W tym przypadku jest to potomny węzeł tekstowy dowolnego elementu oprócz węzła głównego. Tak więc dla dokumentu powyżej ścieżka pasujeStreet
doComment
elementów i.Teraz
//*[contains(., 'ABC')]
dopasowuje dowolny element (oprócz węzła głównego), który zawieraABC
(w konkatenacji potomnych węzłów tekstowych). Na dokumencie powyżej pasuje doHome
, naAddr
, naStreet
, aComment
elementy. Jako takie,//*[contains(., 'BLAH ABC')]
pasuje doHome
ZAddr
, aComment
elementy.źródło
Zajęło mi to trochę czasu, ale w końcu się zorientowałem. Niestandardowa ścieżka xpath zawierająca tekst poniżej działała dla mnie idealnie.
źródło
contains(text(),'JB-')
to nie praca!conatains
przyjmuje dwa ciągi jako argumenty -contains(**string**, **string**)
! text () nie jest łańcuchem , jest funkcją!Zaakceptowana odpowiedź zwróci również wszystkie węzły nadrzędne. Aby uzyskać tylko rzeczywiste węzły z ABC, nawet jeśli ciąg jest po
:
źródło
zwroty
źródło