XPath:点和文本之间的区别()

And*_*son 51 selenium xpath

我的问题是关于使用dot和text()in的具体细节XPath.例如,以下find_element行返回相同的元素:

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

driver.find_element_by_xpath('//a[text()="Ask Question"]')
driver.find_element_by_xpath('//a[.="Ask Question"]')
Run Code Online (Sandbox Code Playgroud)

那么区别是什么呢?使用.和有text()什么好处和缺点?

Mat*_*ler 70

.和之间存在差异text(),但由于您的输入文档,这种差异可能不会出现.

如果您的输入文档看起来像(根据您的XPath表达式可以想象的最简单的文档)

例1

<html>
  <a>Ask Question</a>
</html>
Run Code Online (Sandbox Code Playgroud)

然后//a[text()="Ask Question"]//a[.="Ask Question"]确实返回完全相同的结果.但考虑一下看起来像的不同输入文档

例2

<html>
  <a>Ask Question<other/>
  </a>
</html>
Run Code Online (Sandbox Code Playgroud)

其中a元素还有一个子元素other,紧跟在"提问"之后.给定第二个输入文档,//a[text()="Ask Question"]仍返回a元素,//a[.="Ask Question"]而不返回任何内容!


这是因为两个谓词的含义([和之间的所有内容])是不同的.[text()="Ask Question"]实际上意味着:如果元素的任何文本节点包含文本"Ask Question",则返回true.另一方面,[.="Ask Question"]表示:如果元素的字符串值与"Ask Question"相同,则返回true .

在XPath模型中,如果其他元素干扰文本,则XML元素内的文本可以划分为多个文本节点,如上面的示例2所示.在那里,other元素在"Ask Question"和换行符之间,也称为文本内容.

为了做一个更清晰的例子,请考虑作为输入文档:

例3

<a>Ask Question<other/>more text</a>
Run Code Online (Sandbox Code Playgroud)

这里,a元素实际上包含两个文本节点,"提问"和"更多文本",因为它们都是直接的子节点a.您可以通过运行//a/text()此文档进行测试,该文档将返回(单个结果分隔----):

Ask Question
-----------------------
more text
Run Code Online (Sandbox Code Playgroud)

因此,在这种情况下,text()返回一组单独的节点,而.在谓词中评估所有文本节点的字符串连接.同样,您可以使用//a[.='Ask Questionmore text']将成功返回a元素的路径表达式来测试此声明.


最后,请记住,某些XPath函数只能将一个字符串作为输入.正如LarsH在评论中指出的那样,如果contains()给定一个节点序列这样的XPath函数(例如),它将只处理第一个节点并静默忽略其余节点.


Sau*_*aur 14

dot (".")和之间有很大的区别text(): -

  • dot (".")XPath被称为"上下文项表达式",因为它是指上下文项.这可能是匹配的节点(诸如element,attributetext node),或者一个原子值(如string,numberboolean).虽然text()是指只匹配element text这是在string形式.

  • dot (".")符号是在DOM当前节点.这将是Node类型的对象,而使用XPath函数text()来获取元素的文本只会将文本获取到第一个内部元素.如果您要查找的文本位于内部元素之后,则必须使用当前节点来搜索字符串而不是XPathtext()函数.

举个例子: -

<a href="something.html">
  <img src="filename.gif">
  link
</a>
Run Code Online (Sandbox Code Playgroud)

这里如果你想a通过文本链接找到锚元素,你需要使用dot (".").因为如果你使用//a[contains(.,'link')]它找到锚a元素,但如果你使用//a[contains(text(),'link')]text()函数似乎没有找到它.

希望它会帮助你.. :)

  • @Andersson:你有一个很好的观点,但只有当`link`位于`a`的第一个文本节点子节点时才有效.在Saurabh的例子中,在`<img>`元素之前可能只有一个空白文本节点,在这种情况下,注释中的XPath表达式与锚点不匹配.原因是`contains()`和`normalize-space()`函数接受作为第一个参数的节点集中*first*节点的字符串值. (4认同)
  • @SaurabhGaur:你有一些好点,但是`text()`只选择文本到第一个内部元素是不正确的.`text()`选择所有文本节点(它们是上下文节点的子节点,除非您指定不同的轴).但是,如果将`text()`选择的节点集传递给`contains()`,就像你所做的那样,通过获取节点集中****节点的字符串值将其转换为字符串.(https://www.w3.org/TR/xpath/#function-string) (4认同)
  • ***( - 1)这个答案具有误导性.***阅读LarsH和Mathias的评论以了解如何,或者更好地看到[**Mathias的回答**](/sf/answers/2930366141/)和/或[**Lars回答另一个问题**](/sf/answers/2674588801/)和/或[**我对另一个问题的回答**](https: //stackoverflow.com/a/46488908/290085)以更好地理解这里的细微之处. (4认同)
  • 正如@LarsH正确指出的那样,这个答案的某些部分仍然是错误的,应该修改.答案中最重要的误解是`text()`只选择_first_文本节点,这完全是不真实的. (2认同)