首页 > 解决方案 > XPath 语法,带或不带“/text()”后缀

问题描述

不同网站提供的XPath语法不同,主要是需要“/text()”后缀。

无需后缀的引用语法:

需要后缀的引用语法:

据我所知,不同的库也只能使用或不使用后缀(在此之前我没有遇到过无论有无后缀都可以使用的库)。

不需要后缀:

需要后缀:

看起来,很可能,用于 XML 和用于 DOM 的 XPath 库实现之间存在差异?如果是这样,有什么区别,我在哪里可以找到区别?

标签: xmlxpathxpath-2.0domxpathxpath-1.0

解决方案


我认为您误诊了这种情况,误诊的原因(将类比延伸得太远)是您查看了大约 7 名患者的症状,而不是去医学院学习解剖学。

这里的“剖析”是支持 XPath 语义的 XDM 数据模型。特别注意

(a) 当你有这样的结构时

<title>Water</title>

有一个元素节点,其字符串值为“Water”,它是单个文本节点的父节点,其字符串值为“Water”。

(b) 当你有这样的结构时

<title>H<sub>2</sub>O</title>

有一个元素节点,其字符串值为“H2O”,它是三个孩子的父节点:一个字符串值为“H”的文本节点,一个字符串值为“2”的元素节点(它本身是另一个文本的父节点)节点...),以及第二个文本节点,字符串值为“O”。

在情况 (a) 中,无论是应用于元素节点还是文本节点,几乎所有操作都会产生相同的结果。例如contains($x, "ate"),无论$x是元素节点还是文本节点都为真。所以添加/text()到路径通常是多余的:它没有害处,但它是不必要的。我们经常建议不要这样做,因为如果以后数据结构发生变化,它会使您的代码更加脆弱,而不仅仅是增加不必要的冗长。

如果 (b) 添加/text()到路径导致您选择两个文本节点“H”和“O”,而不是选择元素节点。在 XPath 1.0 中,许多操作(例如contains())在应用于两个文本节点的序列时会忽略除第一个之外的所有操作,因此contains(x/y/title/text(), "O")将返回 false;在 XPath 2.0 中,它会抛出一个错误,指出 contains() 的参数必须是单例。如果你只是想知道标题是否包含字母“O”,那么最好省略掉/text()并应用操作到元素的字符串值,即所有文本节点的串联。

唯一需要使用“/text()”的情况是,如果您想更深入地探究title元素的内部结构。

当然,XPath 实现之间可能存在差异——并非所有实现都 100% 符合标准。但是主流的实现还是很兼容的,如果你发现有什么不同,请告诉我们:源文档,路径表达式,不同实现得到的不同结果要明确。


推荐阅读