web-dev-qa-db-de.com

XPath: Unterschied zwischen Punkt und Text ()

Meine Frage bezieht sich auf Besonderheiten der Verwendung von dot und text() in XPath. Wenn Sie beispielsweise die Zeilen find_element Befolgen, wird dasselbe Element zurückgegeben:

driver.get('http://stackoverflow.com/')

driver.find_element_by_xpath('//a[text()="Ask Question"]')
driver.find_element_by_xpath('//a[.="Ask Question"]')

Was ist der Unterschied? Was sind die Vor- und Nachteile der Verwendung von . Und text()?

47
Andersson

Es gibt einen Unterschied zwischen . Und text(), aber dieser Unterschied tritt möglicherweise aufgrund Ihres Eingabedokuments nicht auf.

Wenn Ihr Eingabedokument so aussah (das einfachste Dokument, das man sich angesichts Ihrer XPath-Ausdrücke vorstellen kann)

Beispiel 1

<html>
  <a>Ask Question</a>
</html>

Dann geben //a[text()="Ask Question"] und //a[.="Ask Question"] Tatsächlich genau dasselbe Ergebnis zurück. Betrachten Sie jedoch ein anderes Eingabedokument, das aussieht

Beispiel 2

<html>
  <a>Ask Question<other/>
  </a>
</html>

dabei hat das a -Element auch ein untergeordnetes other -Element, das unmittelbar nach "Ask Question" folgt. In diesem zweiten Eingabedokument gibt //a[text()="Ask Question"] immer noch das a -Element zurück, während //a[.="Ask Question"] Nichts zurückgibt!


Dies liegt daran, dass die Bedeutung der beiden Prädikate (alles zwischen [ Und ]) Unterschiedlich ist. [text()="Ask Question"] bedeutet eigentlich: return true, wenn einer der Textknoten eines Elements genau den Text "Ask Question" enthält. Andererseits bedeutet [.="Ask Question"]: True zurückgeben, wenn String-Wert eines Elements mit "Ask Question" identisch ist.

Im XPath-Modell kann Text in XML-Elementen in eine Reihe von Textknoten unterteilt werden, wenn andere Elemente den Text stören (siehe Beispiel 2 oben). Dort steht das other -Element zwischen "Ask Question" und einem Newline-Zeichen, das auch als Textinhalt zählt.

Um ein Beispiel noch deutlicher zu machen, betrachten Sie es als Eingabedokument:

Beispiel

<a>Ask Question<other/>more text</a>

Hier enthält das a -Element tatsächlich zwei Textknoten, "Ask Question" und "more text", da beide direkte Kinder von a sind. Sie können dies testen, indem Sie //a/text() für dieses Dokument ausführen, das zurückgibt (einzelne Ergebnisse durch ---- Getrennt):

Ask Question
-----------------------
more text

In einem solchen Szenario gibt text() eine Menge einzelner Knoten zurück, während . In einem Prädikat die String-Verkettung aller Textknoten ergibt. Sie können diese Behauptung erneut mit dem Pfadausdruck //a[.='Ask Questionmore text'] Testen, der das a -Element erfolgreich zurückgibt.


Bedenken Sie schließlich, dass einige XPath-Funktionen nur eine einzige Zeichenfolge als Eingabe verwenden können. Wie LarsH in den Kommentaren darauf hingewiesen hat, verarbeitet eine solche XPath-Funktion (z. B. contains()) nur den Knoten first und ignoriert ihn unbemerkt der Rest.

64
Mathias Müller

Es gibt einen großen Unterschied zwischen dot (".") und text(): -

  • Die dot (".") in XPath wird als "Kontextelementausdruck" bezeichnet, da sie sich auf das Kontextelement bezieht. Dies könnte mit einem Knoten (wie einem element, attribute oder text node) Oder einem atomaren Wert (wie einem string, number oder boolean). Während text() nur element text Bezieht, das in string Form vorliegt.

  • Die dot (".") -Notation ist der aktuelle Knoten im DOM. Dies wird ein Objekt vom Typ Node während der Verwendung der Funktion XPath text (), um den Text für ein Element zu erhalten, wird nur der Text bis zum erstes inneres Element. Wenn der gesuchte Text nach dem inneres Element steht, müssen Sie den aktuellen Knoten verwenden, um nach der Zeichenfolge zu suchen, und nicht die Funktion XPath text () .

Zum Beispiel :-

<a href="something.html">
  <img src="filename.gif">
  link
</a>

Hier müssen Sie dot (".") verwenden, um das a -Element mithilfe von text link zu finden. Denn wenn Sie //a[contains(.,'link')] verwenden, findet es das Ankerelement a, aber wenn Sie //a[contains(text(),'link')] verwenden, scheint es die Funktion text() nicht zu finden.

Hoffe es wird dir helfen .. :)

12
Saurabh Gaur