I am stumped by what appears to be a bug in both the IE7 and Saxon6.5.5 - which leads to wonder if it is not a bug at all but rather my misunderstanding of the way things work. I tried to write a recursive XSLT template that worked its way up the element hierarchy, recursing until the node set '..' was empty. To my surprise, an endless recursion occurred. If I run Saxon in the debugger, I get the following expected results when the context has '.' bound to the top-most XML element:
local-name(.) -> test-checklist (my outermost element name)
local-name(*[1]) -> category (the element name of the first child element)
count(. | /) -> 2 (this node is not the root)
count(.. | /) -> 1 (the parent node is the root)
count(/..) -> 0 (the root has no parent)
However, if I then try <xsl:apply-templates select=".."/>
, '.'
is still bound to the document's outermost element (test-checklist in
this case).
I tried the Xalan and .NET 1.0 transformers as well. Everyone agrees - an endless loop occurs. I don't understand this, and I've scoured both the XSLT and XPath specifications to find an explanation (without success). As a workaround, I changed the termination test to 2 = count(.. | /).
Update: I found it. My template was matching '*'. '*' does not match '/'. Thus, once my code recursed up to the root, the default template rule for '*|/' kicked in. The default rule invokes apply-templates on the context node's children. Thus, execution would just rattle around on the top-most element. Subtle.