从不同的网站提供的XPath语法是不同的,主要是需要“ / text()” 后缀。
引用语法无需后缀:
引用语法带有的后缀:
据我所知,不同的库也只能在带有或不带有后缀的情况下工作(在使用和不使用后缀的情况下,我都没有遇到过。)
不需要后缀:
需要后缀:
似乎很可能是要用于XML的XPath库实现和要用于DOM的XPath库实现之间有区别? 如果是这样,有什么区别?在哪里可以找到区别?
答案 0 :(得分:3)
我认为您误诊了这种情况,而误诊的原因(将类推延伸得太多了)是因为您查看的是大约7名患者的症状,而不是去医学院上学并学习了解剖学。
这里的“解剖”是XDM数据模型,它支持XPath的语义。请特别注意
(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%一致。但是主流实现非常兼容,如果发现不同之处,请告诉我们:明确说明源文档,路径表达式以及在不同实现中获得的不同结果。
答案 1 :(得分:0)
如果您查看相关的规范,则会发现XPath 1.0 https://www.w3.org/TR/xpath-10/#node-tests和XPath 2.0规范https://www.w3.org/TR/xpath20/#node-tests都将您称为“后缀”的内容定义为“节点测试” text()
用于选择任何“文本节点”。
没有一个规范要求使用text()
,但是语言当然是语言选择并且需要选择文本节点的一种选择,例如,元素的混合内容以及文本和/或注释在其中仅选择文本节点的子级是有原因的。
对于实现,我认为Java的XPath 1.0实现不需要您使用它,这是某些较早的DOM特定代码使用foo/text()
而不是简单地使用foo
来读取字符串的唯一原因例如的元素内的内容<foo>some example</foo>
是在较旧的DOM实现中,如果选择一个Element
节点,则没有属性或方法以字符串形式访问元素的文本内容,因此人们使用foo/text()
来选择Text
的{{1}}子节点,然后可以使用Element
属性(Javascript)或nodeValue
方法(Java)使用{{1} }。但是,多年来DOM在getNodeValue()
节点上提供属性some example
,因此,如今,您可以将textContent
用作XPath并获得Element
节点并读出{{1 }}或foo
分别具有字符串Element
。
MSXML DOM和XPath也相当老,并且从未更新为DOM Level 3 W3C规范,但是Microsoft从一开始就在元素节点上拥有自己专有的textContent
属性,您可以在那里使用它而不是标准化的getTextContent()
。不过,在那种情况下,我已经看到了类似的尝试,即明确地读出some example
作为节点列表,然后可以在该列表上以字符串的形式访问每个文本节点的.text
。
如果您想将XPath选择直接映射到Python字符串列表,则在Python的lxml库中使用textContent
而不是foo/text()
的唯一实现特定的“首选项”在在这种情况下,例如nodeValue
这样的表达式foo/text()
在Python方面会为您提供两个包含foo
和foo/text()
的Python字符串的列表,而使用<data><foo>a</foo><foo>b</foo></data>
会给您一个包含两个元素节点的列表。因此,在这种情况下,根据您在主机语言方面的需求,可以更轻松地使用a
,但是您需要注意,像b
这样的输入将为您提供包含三个字符串的列表。>