XPath模棱两可

时间:2015-08-07 12:31:01

标签: java xml oracle xpath

我正在使用XPath的以下片段

ancestor::contribution[1]/preceding-sibling::contribution[@speaker-reference][1]

我的Java应用程序(使用JDOM进行XPath查询)与Oracle数据库(11g)的解释不同。 我能够通过使用括号解决问题,如下所示:

 (ancestor::contribution[1]/preceding-sibling::contribution[@speaker-reference])[1]

所以似乎JDOM正在读取xpath作为"前面的contributions中的第一个具有属性@speaker-reference"而Oracle认为"前面的contribution带有属性@speaker-reference and position()=1"。

我实际上打算第一次解释。我想知道根据XPath规范(无法找到正确的位置)或者规范是否允许表达式含糊不清,这两种解释中的哪一种是正确的。

2 个答案:

答案 0 :(得分:3)

根据XML Path Language Specification,方括号运算符[..]的优先级为19,而斜杠/的优先级为18.这意味着应该应用最后的方括号[1]斜杠/之后的表达式部分,而不是整个表达式。换句话说,甲骨文的解释是正确的。

Java的实现 * ,它为您提供了在/表达式周围没有括号的正确结果,不符合标准。考虑使用简短示例提交错误并解释正在发生的事情。

* 具有讽刺意味的是,这也是Oracle的实施。

答案 1 :(得分:3)

鉴于您的描述,很难看出JDOM和Oracle正在做什么。 但是他们的不同行为显然是由反轴的proximity position的不同实现引起的。

由于ancestor::contribution[1]求值为空节点集或单个节点,我们可以将示例简化为以下情况,使用元素x作为上下文节点:

<doc>
   <contribution speaker-reference="a"/>
   <contribution speaker-reference="b"/>
   <contribution/>
   <x/>
</doc>  

选择preceding-sibling::contribution[speaker-reference]会按文档顺序返回带有speaker-reference属性的两个贡献节点。

选择(preceding-sibling::contribution[speaker-reference])[1]会返回这两个节点中的第一个节点,即speaker-reference = a。

现在必须根据轴顺序解释选择preceding-sibling::contribution[speaker-reference][1]位置谓词[1]。由于preceding-sibling是反向轴,因此必须以反向文档顺序处理所选节点集。此节点集中的第一个位置是speaker-reference = b。

的节点

希望这可以让你澄清哪些实现是正确的。