Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath ambiguity

I am working with the following fragment of an XPath

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

My Java application (using JDOM for XPath queries) interprets this differently from our Oracle database (11g). I was able to solve the problem by using brackets as follows:

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

So it seems that JDOM is reading the xpath as "the first of all preceding contributions with an attribute @speaker-reference" while Oracle thinks "the preceding contribution with an attribute @speaker-reference and position()=1".

I had actually intended the first interpretation. I am wondering which of the two interpretations is correct according to the XPath specification (couldn't find the right place to look) or whether the specification allows expressions to be ambiguous.

like image 859
Bernd Moos Avatar asked Mar 17 '26 03:03

Bernd Moos


2 Answers

According to the XML Path Language Specification, square brackets operator [..] has precedence 19, while slash / has precedence 18. This means that the last square brackets [1] should be applied to the portion of the expression after the slash /, not to the entire expression. In other words, Oracle's interpretation is right.

Java's implementation*, which gives you the correct result without parentheses around the / expression, is not compliant with the standard. Consider filing a bug with a short example and an explanation of what is going on.

* Ironically, that's Oracle's implementation as well.

like image 115
Sergey Kalinichenko Avatar answered Mar 19 '26 17:03

Sergey Kalinichenko


Given your description it is not easy to see what JDOM and Oracle are doing. But their different behaviour is apparently caused by a different implementation of the proximity position of a reverse axis.

Since ancestor::contribution[1] evaluates to an empty node-set or a single node we can simplify your example to the following situation, using element x as context node:

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

Selecting preceding-sibling::contribution[speaker-reference] returns the two contribution nodes with a speaker-reference attribute in document order.

Selecting (preceding-sibling::contribution[speaker-reference])[1] returns the first of these two nodes which is the one with speaker-reference = a.

Selecting preceding-sibling::contribution[speaker-reference][1] the position predicate [1] must now be interpreted according the axis order. Since preceding-sibling is a reverse axis the selected node-set must treated in reverse document order. The first position in this node-set is the node with speaker-reference = b.

Hope this allows you to clarify which implementation has got right.

like image 38
wero Avatar answered Mar 19 '26 17:03

wero



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!