XPath gibt nur Elemente zurück, die den Text enthalten, und nicht die übergeordneten Elemente

77

In dieser XML möchte ich übereinstimmen, das Element, das 'match' enthält (random2-Element)

<root>
 <random1>
  <random2>match</random2>
  <random3>nomatch</random3>
 </random1>
</root>

ok, soweit habe ich:

//[re:test(.,'match','i')] (with re in the proper namespace)

Dies gibt random2, random1 und root zurück ... Ich möchte nur "random2" erhalten

irgendwelche Ideen?

julianisch
quelle
Möchten Sie übereinstimmen, wenn es das Wort an einer beliebigen Stelle im Text enthält (z. B. "Überprüfen Sie, ob dies mit dem Wort übereinstimmt ") oder nur Elemente, deren Wert gleich "Übereinstimmung" ist (ignorieren Sie das umgebende Leerzeichen)?
Mads Hansen
es ist nicht so relevant, würde auch funktionieren. Das Problem war hauptsächlich, dass es auch seine Eltern
zurückbrachte

Antworten:

165

Möchten Sie Elemente finden, die "Übereinstimmung" oder gleich "Übereinstimmung" enthalten?

Dadurch werden Elemente mit Textknoten gefunden, die gleich "Übereinstimmung" sind (entspricht keinem der Elemente, da Leerzeichen nach vorne und nach hinten führen random2):

//*[text()='match']

Dadurch werden alle Elemente mit Textknoten gefunden, die gleich "Übereinstimmung" sind, nachdem führende und nachfolgende Leerzeichen (Übereinstimmungen random2) entfernt wurden:

//*[normalize-space(text())='match']

Dadurch werden alle Elemente gefunden, die 'Übereinstimmung' im Textknotenwert (Übereinstimmungen random2und random3) enthalten:

//*[contains(text(),'match')]

Diese XPATH 2.0- Lösung verwendet die matches()Funktion und ein Regex-Muster, das nach Textknoten sucht, die 'match' enthalten und am Anfang der Zeichenfolge (dh ^) oder einer Wortgrenze (dh \W) beginnen und am Ende der Zeichenfolge (dh $) enden. oder eine Wortgrenze. Der dritte Parameter ibewertet das Regex-Muster ohne Berücksichtigung der Groß- und Kleinschreibung. (Streichhölzer random2)

//*[matches(text(),'(^|\W)match($|\W)','i')]
Mads Hansen
quelle
Ihre zweite Aussage ist nicht wahr. Hinweis: Nehmen Sie ein Element mit mehr als einem Textknoten, dessen erster Textknoten keine "Übereinstimmung" enthält.
Dimitre Novatchev
Danke @Dimitre. Aktualisiert mit etwas, das robuster sein sollte.
Mads Hansen
Eigentlich möchte ich eine bestimmte Abfrage mit regulärem Ausdruck wie '^ ma (t | T) ausführen. *' Kann ich die erste verwenden? //*[text()='^ma(t|T).* '] richtig?
Julian
Wenn Sie Regex verwenden möchten, verwenden Sie so etwas wie das letzte Beispiel. Regex wird in XSLT 1.0 nicht unterstützt, daher benötigen Sie ein XSLT 2.0-Stylesheet und einen XSLT 2.0-Prozessor (wie Saxon), um es zu verwenden.
Mads Hansen
Ich glaube, //*/text()[normalize-space(.)='match']/parent::*sollte //*[normalize-space(text())='match']oder//*[normalize-space(./text())='match']
neaumusic
0

Versuchen

//re:*[. ='match']
Gregoire
quelle