web-dev-qa-db-fra.com

XPath: différence entre dot et text ()

Ma question concerne les spécificités de l'utilisation de dot et de text() dans XPath. Par exemple, si vous suivez find_element lignes, vous obtenez le même élément:

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

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

Alors, quelle est la difference? Quels sont les avantages et les inconvénients de l’utilisation de . et de text()?

47
Andersson

Il existe une différence entre . et text(), mais cette différence peut ne pas apparaître à cause de votre document d'entrée.

Si votre document d'entrée ressemblait (le document le plus simple que l'on puisse imaginer étant donné vos expressions XPath)

Exemple 1

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

Alors //a[text()="Ask Question"] et //a[.="Ask Question"] retournent en effet exactement le même résultat. Mais considérons un autre document d’entrée qui ressemble à

Exemple 2

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

où l'élément a a également un élément enfant other qui suit immédiatement "Poser une question". Étant donné ce deuxième document d'entrée, //a[text()="Ask Question"] renvoie toujours l'élément a, tandis que //a[.="Ask Question"] ne renvoie rien!


En effet, la signification des deux prédicats (tout ce qui se situe entre [ et ]) est différente. [text()="Ask Question"] signifie en réalité: renvoie vrai si l'un des nœuds de texte d'un élément contient exactement le texte "Poser une question". Par contre, [.="Ask Question"] signifie: retourne vrai si le valeur de chaîne d'un élément est identique à "Poser une question".

Dans le modèle XPath, le texte contenu dans des éléments XML peut être partitionné en un certain nombre de nœuds de texte si d'autres éléments interfèrent avec le texte, comme dans Exemple 2 ci-dessus. Ici, l'élément other se trouve entre "Poser une question" et un caractère de nouvelle ligne qui compte également comme contenu textuel.

Pour rendre un exemple encore plus clair, considérons comme document d’entrée:

Exemple

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

Ici, l'élément a contient deux nœuds de texte, "Poser une question" et "plus de texte", car ils sont tous deux des enfants directs de a. Vous pouvez le tester en exécutant //a/text() sur ce document, qui renverra (résultats individuels séparés par ----):

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

Ainsi, dans un tel scénario, text() renvoie un ensemble de nœuds individuels, tandis que . dans un prédicat correspond à la concaténation de chaîne de tous les nœuds de texte. De nouveau, vous pouvez tester cette revendication avec l'expression de chemin //a[.='Ask Questionmore text'] qui retournera avec succès l'élément a.


Enfin, gardez à l'esprit que certaines fonctions XPath ne peuvent prendre qu'une seule chaîne en entrée. Comme LarsH l’a souligné dans les commentaires, si une telle fonction XPath (par exemple, contains()) se voit attribuer une séquence de nœuds, elle ne traitera que la première nœud et ignorer le reste en silence.

64
Mathias Müller

Il y a une grande différence entre dot (".") et text(): -

  • La dot (".") dans XPath est appelée "expression d'élément de contexte" car elle fait référence à l'élément de contexte. Cela peut correspondre à un nœud (tel que element, attribute ou text node) ou à une valeur atomique (telle que string, number, ou boolean). Alors que text() fait référence à ne faire correspondre que element text qui est sous la forme string.

  • La notation dot (".") est le nœud actuel du DOM. Cela va être un objet de type Node pendant l'utilisation de la fonction XPath function text () pour obtenir le texte d'un élément ne récupère que le texte jusqu'au premier élément interne. Si le texte que vous recherchez se trouve après élément intérieur, vous devez utiliser le nœud actuel pour rechercher la chaîne et non la fonction XPath text ().

À titre d'exemple :-

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

Ici si vous voulez trouver l'élément anchor a à l'aide de text link, vous devez utiliser dot ("."). Parce que si vous utilisez //a[contains(.,'link')], il trouve l'élément ancre a mais si vous utilisez //a[contains(text(),'link')], la fonction text() ne semble pas le trouver.

J'espère que cela vous aidera .. :)

12
Saurabh Gaur