Those who are familiar with XPath know that some axes, such as preceding::
, are reverse axes. And if you put a positional predicate on an expression built with a reverse axis, you may be counting backward instead of forward. E.g.
$foo/preceding-sibling::*[1]
returns the preceding sibling element just before $foo
, not the first preceding sibling element (in document order).
But then you encounter variations where this rule seems to be broken, depending on how far removed the positional predicate is from the reverse axis. E.g.
($foo/preceding-sibling::*)[1]
counts forward from the beginning of the document, not backward from $foo
.
Today I was writing some code where I had an expression like
$foo/preceding::bar[not(parent::baz)][1]
I wanted to be counting backwards from $foo
. But was my positional predicate too far removed from the preceding::
axis? Had the expression lost its reverse direction before I added the [1]
? I thought it probably wouldn't work, so I changed it to
$foo/preceding::bar[not(parent::baz)][last()]
but then I wasn't really sure of the direction, so I put in parentheses to make sure:
($foo/preceding::bar[not(parent::baz)])[last()]
However, the extra parentheses are a bit confusing, and I thought the expression might be less efficient, if it really has to count from the beginning of the (large) input document instead of backward from $foo
. Was it really necessary to do it this way?
Finally I tested the original expression, and found to my surprise that it worked! So the intervening [not(parent::baz)]
had not caused the expression to lose its reverse direction after all.
That problem was solved, but I've come to the point where I'd like to get a better handle on when I can expect the reverse direction of an axis to apply. My question is: At what point(s) does an XPath expression using a reverse axis lose its reverse direction?
I believe I've found the answer now, so I'll answer my own question. But I couldn't find the answer on SO, and it's something that has bothered me long enough that it was worth asking and answering here.