为什么 XPath contains(text(),'substring') 无法按预期工作?

Noc*_*ceo 3 html xml xpath

假设我有一段这样的 HTML:

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

我可以匹配这段XPath:

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

或者...

//a[text() = 'more text']
Run Code Online (Sandbox Code Playgroud)

或者我可以使用点来匹配整个内容:

//a[. = 'Ask Questionmore text']
Run Code Online (Sandbox Code Playgroud)

这篇文章.描述了(dot) 和 之间的区别text(),但简而言之,第一个返回单个元素,而后者返回一个元素列表。但这对我来说有点奇怪。因为 whiletext()可以用来匹配列表中的任意一个元素,但对于 XPath 函数来说,情况并非如此contains()。如果我这样做:

//a[contains(text(), 'Ask Question')]
Run Code Online (Sandbox Code Playgroud)

...我收到以下错误:

错误: contains() 的第一个参数所需的基数为一或零

为什么它text()在使用完整匹配(等于)时有效,但在部分匹配(包含)时不起作用?

kjh*_*hes 7

对于这个标记,

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

请注意,该a元素有一个文本节点子节点 ( "Ask Question")、一个空元素子节点 ( other) 和第二个文本节点子节点 ( "more text")。

以下是如何推理根据//a[contains(text(),'Ask Question')]该标记进行评估时发生的情况:

  1. contains(x,y)期望x是一个字符串,但text()匹配两个文本节点。
  2. XPath 1.0中,将多个节点转换为字符串的规则是这样的

通过返回节点集中文档顺序第一个节点的字符串值,将节点集转换为字符串。如果节点集为空,则返回空字符串。[强调已添加]

  1. XPath 2.0+中,向需要字符串的函数提供一系列文本节点是错误的,因此contains(text(),'substr')会导致多个匹配文本节点出现错误。

就你而言...

  • XPath 1.0 将contains(text(),'Ask Question')视为

    contains('Ask Question','Ask Question')
    
    Run Code Online (Sandbox Code Playgroud)

    这是true. 另一方面,请务必注意XPath 1.0 中的contains(text(),'more text')计算结果为false。如果不知道上面的 (1)-(3),这可能是违反直觉的。

  • XPath 2.0 会将其视为错误。

更好的选择

也可以看看


Kei*_*all 5

原因是该contains函数不接受节点集作为输入 - 它只接受字符串。(嗯,它可能与引擎相关,因为它适用于Python'slxml模块。根据规范,它应该将集合中第一个节点的值转换为字符串并对其进行操作。另请参阅XPath contains(text() ,'some string') 与具有多个文本子节点的节点一起使用时不起作用

//a[text() = 'Ask Question']匹配包含a等于 的文本节点的任何元素Ask Question

//a[text() = 'more text']匹配包含a等于 的文本节点的任何元素more text

所以这两个表达式都匹配相同的a元素。

您可以重新处理查询,//a[text()[contains(., 'Ask Question')]]以便该contains方法一次仅作用于一个文本节点。