包含包含的 xpath 标准化空间

Nod*_*rat 2 xpath

我有一个XPath字符串//*[normalize-space() = "some sub text"]/text()/..,如果我发现文本是在没有多个文本子节点的节点,工作正常,但如果这样做,那么它不会工作,所以我想将其联合contains()如下://*[contains(normalize-space(), "some sub text")]/text()/..其中确实有效,但它总是返回bodyhtml标签以及p包含文本的标签。如何更改它以便它只返回p标签?

Mic*_*Kay 6

这完全取决于您想要匹配的内容。

最可能的情况是,some text如果它出现在元素的规范化字符串值中的任何位置,则您希望匹配它,可能会在不同级别的多个文本节点之间拆分:例如以下任何一个:

<p>some text</p>
<p>There was some text</p>
<p>There was <b>some text</b></p>
<p>There <b>was</b> some text</p>
<p>There was <b>some</b> <!--italic--> <i>text</i></p>
<p>There was <b>some</b> text</p>
Run Code Online (Sandbox Code Playgroud)

如果是这种情况,请使用//p[contains(normalize-space(.), "some text")].

正如您所指出的,//*与此谓词一起使用还将匹配相关元素的祖先元素。解决此问题的最简单方法是使用//p来说明您要查找的元素。如果您不知道要查找什么元素,那么在 XPath 3.0 中您可以使用

innermost(//*[contains(normalize-space(.), "some text")])

但是如果您不幸没有使用 XPath 3.0,那么您可以这样做(//*[contains(normalize-space(.), "some text")])[last()],尽管如果有多个具有所需内容的段落,这不会做完全相同的事情。

如果您不想匹配以上所有内容,但希望更具选择性,那么您需要更清楚地说明您的要求。

无论哪种方式,text()在路径表达式中使用 of通常都是一种代码异味,除非在极少数情况下,您只想在元素中选择未包含在其他标签中的文本。