Ich habe ein kleines Problem mit Xpath enthält mit dom4j ...
Nehmen wir an, mein XML ist
<Home>
<Addr>
<Street>ABC</Street>
<Number>5</Number>
<Comment>BLAH BLAH BLAH <br/><br/>ABC</Comment>
</Addr>
</Home>
Nehmen wir an, ich möchte alle Knoten mit ABC im Text finden, wenn das Stammelement angegeben ist ...
Der xpath, den ich schreiben müsste, wäre also
//*[contains(text(),'ABC')]
Dies ist jedoch nicht das, was Dom4j zurückgibt. Ist dies ein dom4j-Problem oder mein Verständnis, wie xpath funktioniert? da diese Abfrage nur das Straßenelement und nicht das Kommentarelement zurückgibt.
Das DOM macht das Kommentarelement zu einem zusammengesetzten Element mit vier Tags und zwei
[Text = 'XYZ'][BR][BR][Text = 'ABC']
Ich würde annehmen, dass die Abfrage das Element immer noch zurückgeben sollte, da es das Element finden und ausführen sollte, aber es nicht ... ...
Die folgende Abfrage gibt das Element zurück, aber es gibt weit mehr als nur das Element zurück, es gibt auch die übergeordneten Elemente zurück ... was für das Problem unerwünscht ist ...
//*[contains(text(),'ABC')]
Kennt jemand die xpath-Abfrage, die nur die Elemente <Street/>
und zurückgeben würde <Comment/>
?
//*[contains(text(),'ABC')]
nur das<Street>
Element zurückgegeben. Es werden keine Vorfahren von<Street>
oder zurückgegeben<Comment>
.Antworten:
Das
<Comment>
Tag enthält zwei Textknoten und zwei<br>
Knoten als untergeordnete Knoten.Ihr xpath-Ausdruck war
Um dies zu brechen,
*
ist ein Selektor, der mit einem beliebigen Element (dh einem Tag) übereinstimmt - er gibt eine Knotenmenge zurück.[]
sind Bedingungen, die für jeden einzelnen Knoten in diesem Knotensatz gelten. Es stimmt überein, ob einer der einzelnen Knoten, an denen es arbeitet, mit den Bedingungen in den Klammern übereinstimmt.text()
ist ein Selektor , der mit allen Textknoten übereinstimmt, die untergeordnete Elemente des Kontextknotens sind. Er gibt einen Knotensatz zurück.contains
ist eine Funktion, die mit einer Zeichenfolge arbeitet. Wenn ein Knotensatz übergeben wird, wird der Knotensatz in eine Zeichenfolge konvertiert, indem der Zeichenfolgenwert des Knotens in dem Knotensatz zurückgegeben wird, der zuerst in der Dokumentreihenfolge steht . Daher kann es nur mit dem ersten Textknoten in Ihrem<Comment>
Element übereinstimmen - nämlichBLAH BLAH BLAH
. Da dies nicht übereinstimmt, erhalten Sie keine<Comment>
Ergebnisse.Sie müssen dies ändern in
*
ist ein Selektor, der mit einem beliebigen Element (dh einem Tag) übereinstimmt - er gibt eine Knotenmenge zurück.[]
ist eine Bedingung, die für jeden einzelnen Knoten in diesem Knotensatz gilt - hier für jedes Element im Dokument.text()
ist ein Selektor , der mit allen Textknoten übereinstimmt, die untergeordnete Elemente des Kontextknotens sind. Er gibt einen Knotensatz zurück.[]
sind eine Bedingung, die für jeden Knoten in diesem Knotensatz gilt - hier für jeden einzelnen Textknoten. Jeder einzelne Textknoten ist der Ausgangspunkt für einen beliebigen Pfad in den Klammern und kann auch explizit als.
innerhalb der Klammern bezeichnet werden. Es stimmt überein, ob einer der einzelnen Knoten, an denen es arbeitet, mit den Bedingungen in den Klammern übereinstimmt.contains
ist eine Funktion, die mit einer Zeichenfolge arbeitet. Hier wird ein einzelner Textknoten (.
) übergeben. Da der zweite Textknoten im<Comment>
Tag einzeln übergeben wird, wird die'ABC'
Zeichenfolge angezeigt und kann mit ihr übereinstimmen.quelle
//*[contains(., 'ABC')]
. Ich hatte immer das von Mike Milkin gegebene Muster verwendet und dachte, es sei angemessener, aber nurcontains
im aktuellen Kontext zu arbeiten, scheint tatsächlich das zu sein, was ich öfter möchte.[contains(text(),'')]
gibt nur true oder false zurück. Es werden keine Elementergebnisse zurückgegeben.quelle
contains(text(),'JB-')
ist keine Arbeit!conatains
nimmt zwei Zeichenfolgen als Argumente -contains(**string**, **string**)
! text () ist kein String , ist eine Funktion!Das XML-Dokument:
Der XPath-Ausdruck:
//*
Entspricht einem beliebigen untergeordneten Element des Stammknotens . Das heißt, jedes Element außer dem Wurzelknoten.[...]
ist ein Prädikat , es filtert die Knotenmenge. Es gibt Knoten , für die...
isttrue
:contains('haystack', 'needle')
gibt zurück,true
wennhaystack
enthältneedle
:Nimmt
contains()
aber einen String als ersten Parameter. Und es ist Knoten übergeben. Um damit umzugehen, wird jeder Knoten oder Knotensatz, der als erster Parameter übergeben wird , von der Funktion in einen String konvertiertstring()
:string()
Funktionsrückgabestring-value
des ersten Knotens :string-value
eines Elementknotens :string-value
eines Textknotens :Grundsätzlich
string-value
handelt es sich also um den gesamten Text, der in einem Knoten enthalten ist (Verkettung aller untergeordneten Textknoten).text()
ist ein Knotentest, der mit jedem Textknoten übereinstimmt:Dies
//*[contains(text(), 'ABC')]
entspricht jedoch jedem Element (außer dem Wurzelknoten), dessen erster Textknoten enthältABC
. Sincetext()
gibt einen Knotensatz zurück, der alle untergeordneten Textknoten des Kontextknotens enthält (relativ zu dem ein Ausdruck ausgewertet wird). Nimmtcontains()
aber nur den ersten. Für das Dokument oben entspricht der Pfad demStreet
Element.Der folgende Ausdruck
//*[text()[contains(., 'ABC')]]
entspricht jedem Element (außer dem Stammknoten), das mindestens einen untergeordneten Textknoten enthältABC
..
repräsentiert den Kontextknoten. In diesem Fall handelt es sich um einen untergeordneten Textknoten eines Elements außer dem Stammknoten. Für das Dokument oben entspricht der Pfad alsoStreet
denComment
Elementen und.Entspricht nun
//*[contains(., 'ABC')]
jedem Element (außer dem Stammknoten), das enthältABC
(in der Verkettung der untergeordneten Textknoten). Für das obige Dokument entspricht es denHome
, denAddr
, denStreet
und denComment
Elementen. Entspricht als solches//*[contains(., 'BLAH ABC')]
denHome
, denAddr
und denComment
Elementen.quelle
Es hat eine Weile gedauert, aber ich habe es endlich herausgefunden. Benutzerdefinierter xpath, der unten Text enthält, hat für mich perfekt funktioniert.
quelle
contains(text(),'JB-')
ist keine Arbeit!conatains
nimmt zwei Zeichenfolgen als Argumente -contains(**string**, **string**)
! text () ist kein String , ist eine Funktion!Die akzeptierte Antwort gibt auch alle übergeordneten Knoten zurück. So erhalten Sie nur die tatsächlichen Knoten mit ABC, auch wenn die Zeichenfolge nach
:
quelle
kehrt zurück
quelle