XPath - 属性通配符未返回具有属性名称为value的元素

4

我正在尝试使用XPath(Java)根据以特定值开头的未知属性获取所有未知节点。由于某种原因,它没有返回包含名为value的属性的节点。我还在www.freeformatter.com/xpath-tester.html上进行了测试,并得到了相同的结果。这是我的代码:

XML:

<div>
    <object data="/v1/assets/mp4Video-1" type="video/mp4">
        <param name="webmSource" value="/v1/assets/webmVideo-1" type="REF"/>
    </object>
</div>

XPath 表达式:

//*[starts-with(@*, '/v1/assets/')]

结果 - 返回<object>,但不返回<param>

现在,如果我将XPath表达式更改为//*[starts-with(@*, '/v1/assets/') or starts-with(@value, '/v1/assets/')],它会按预期返回两者。

我想知道的是,value属性有什么特殊之处,使得XPath无法正确识别它作为属性,或者当value属性包含我查询的值时,无法返回该元素?


当我使用你提供的网站,以及你写的XML和XPath表达式时,我在响应中得到了对象和参数元素。 - Sanj
@Sanj - 他的xpath返回Object元素,该元素还返回其子元素。 - PhillyNJ
@PhilVallone 哦,好的,现在明白了,看起来你的答案是正确的。 - Sanj
2个回答

3
你的原始路径表达式无法正常运行的原因是:
//*[starts-with(@*, '/v1/assets/')]

无法正常工作与XPath 1.0中的函数处理超出预期节点的方式有关。 starts-with() 函数期望其第一个参数为单个节点,期望其第二个参数为字符串(或可评估为字符串的节点)。

但在上述表达式中,starts-with() 的第一个参数是一个属性节点的集合,即@*。在这种情况下,此函数仅使用该集合中的第一个属性节点。集合中的所有其他节点都将被忽略。由于XML中未定义属性的顺序,XPath引擎可以选择使用任何属性节点来执行该函数。但您特定的XPath引擎(以及许多其他引擎)似乎一致使用它们出现的顺序中的第一个属性节点。

为了说明这一点(并证明它),请将输入文档更改为:

<div>
    <object data="other" type="/v1/assets/mp4Video-1">
        <param name="/v1/assets/webmVideo-1" value="other" type="REF"/>
    </object>
</div>

如您所见,我已经改变了属性的顺序,包含/v1/assets/的属性现在是object元素的第二个属性,而对于param元素则相反。使用这个输入文档,您原来的XPath表达式只会返回param元素。
同样,这种行为在不同的XPath引擎之间并不一致!使用其他实现XPath的工具可能会产生不同的结果。
您需要使用的XPath表达式是:
//*[@*[starts-with(., '/v1/assets/')]]

用通俗易懂的语言来解释,这句话的意思是在文档中选择元素,但仅当一个元素的所有属性节点中,有一个属性的值以"/v1/assets/"开头。


非常棒的解释。现在完全明白了。谢谢。尽管@PhilVallone先提供了正确的答案,但我必须将这个标记为被接受的答案,因为它给了我很好的解释。 - Ashaelon

2

请尝试

//@*[starts-with(., '/v1/assets/')]

返回所有属性
//*[@*[starts-with(., '/v1/assets/')]]

返回所有元素
这将搜索所有节点的所有属性。

这只会返回属性,而不是属性所属的元素,我需要返回元素。 - Ashaelon
更新为返回所有元素。 - PhillyNJ
好的,你的第二个代码正是我所需要的。你能解释一下它为什么与我的不同吗? - Ashaelon
@Ashaelon 请看我的解释,这是一个有趣的现象。 - Mathias Müller
@MathiasMüller 我回报了你的恩情。 - PhillyNJ
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接