XPath:dot和text()之间的区别


69

我的问题是关于使用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"]')

那么区别是什么呢?使用.和的优点和缺点是text()什么?


2
我在stackoverflow.com/a/38208411/423105上的回答描述了使用text(),它选择一个文本节点,和使用一个比较通用的节点选择器(例如.)之间的区别。
LarsH '16

Answers:


100

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

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

例子1

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

然后//a[text()="Ask Question"]//a[.="Ask Question"]实际上返回完全相同的结果。但是考虑一个看起来像这样的输入文件

例子2

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

其中该a元素还有一个子元素other,紧接在“问问题”之后。给定第二个输入文档,//a[text()="Ask Question"]仍然返回a元素,而//a[.="Ask Question"]什么都不返回!


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

在XPath模型中,如果其他元素干扰文本,则可以将XML元素内的文本划分为多个文本节点,如上面的示例2所示。在那里,other元素位于“问问题”和换行符之间,换行符也视为文本内容。

为了使示例更清晰,请考虑将其作为输入文档:

例子3

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

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

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

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


最后,请记住,某些XPath函数只能将一个字符串作为输入。正如LarsH在评论中指出的那样,如果为这样的XPath函数(例如contains())提供了一系列节点,则它将仅处理第一个节点,而忽略其余节点。


1
在示例3中,[text()=“询问问题”]的结果将是<a>还是什么都不返回。
Maninder Singh's

21

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

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

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

例如:

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

如果要a使用文本链接查找锚点元素,则需要使用dot (".")。因为如果你使用//a[contains(.,'link')]它找到锚a元素,但如果你使用//a[contains(text(),'link')]text()功能似乎没有找到它。

希望能对您有所帮助.. :)


我非常确定我可以与锚匹配//a[contains(text(),'link')]以及//a[normalize-space(text())='link')]:)无论如何,谢谢您的回答
Andersson

4
@Andersson:您的观点很不错,但是只有link在的第一个文本节点子节点中有效a。在Saurabh的示例中,<img>元素前面可能只有纯空白文本节点,在这种情况下,注释中的XPath表达式与锚点不匹配。原因是contains()andnormalize-space()函数采用节点集中第一个节点的第一个参数的字符串值。
LarsH '16

4
@SaurabhGaur:您有一些好处,但是text()仅选择第一个内部元素之前的文本并不是正确的。text()选择所有文本节点(它们是上下文节点的子节点,除非您指定其他轴)。但是,如果像您一样将所选择的节点集传递text()contains(),则会通过获取节点集中第一个节点的字符串值将其转换为字符串。(w3.org/TR/xpath/#function-string
LarsH

2
正如@LarsH正确指出的那样,此答案的某些部分仍然是错误的,应进行修改。答案中最重要的误解是text()仅选择第一个文本节点,这是完全不正确的。
MathiasMüller17年

4
(-1)这个答案有误导性。 阅读LarsH和Mathias的评论,以了解如何更好地了解Mathias的回答和/或Lars对另一个问题的回答和/或我对另一个问题的回答,以更好地理解此处的细微差别。
kjhughes

-3

在这里输入的图像描述 文本节点内中的XPath text()函数所处元件,同时点(。)定位内部或文本节点以外的元件。在图像描述屏幕快照中,XPath text()函数将仅在DOM Example 2中找到Success 。由于它位于标记之间,因此在DOM示例1中不会成功。

另外,在DOM示例3中,text()函数不会成功,因为成功与element没有直接关系。这是一个视频演示,解释了text()和点(。)之间的区别。https://youtu.be/oi2Q7-0ZIBg

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.