After 17 years of experience we still run into dummy bugs in xslt (xpath in fact).
The latest one is related to order of nodes produced by ancestor-or-self axis.
Consider the code:
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <xsl:template match="/"> <xsl:variable name="data" as="element()"> <a> <b> <c/> </b> </a> </xsl:variable> <xsl:variable name="item" as="element()" select="($data//c)[1]"/> <xsl:message select="$item!ancestor-or-self::*!local-name()"/> <xsl:message select="$item!local-name(), $item!..!local-name(), $item!..!..!local-name()"/> </xsl:template> </xsl:stylesheet>
We expected to have the following outcome
c b a
But correct one is
a b c
Here is why:
ancestor-or-self::* is an AxisStep. From XPath ยง3.3.2: [Definition: An axis step returns a sequence of nodes that are reachable from the context node via a specified axis. Such a step has two parts: an axis, which defines the "direction of movement" for the step, and a node test, which selects nodes based on their kind, name, and/or type annotation.] If the context item is a node, an axis step returns a sequence of zero or more nodes; otherwise, a type error is raised [err:XPTY0020]. The resulting node sequence is returned in document order.
ancestor-or-self::*
For some reason we were thinking that reverse axis produces result in reverse order. It turns out the reverse order is only within predicate of such axis.
See more at https://saxonica.plan.io/boards/3/topics/7312