... until the collector arrives ...

This "blog" is really just a scratchpad of mine. There is not much of general interest here. Most of the content is scribbled down "live" as I discover things I want to remember. I rarely go back to correct mistakes in older entries. You have been warned :)

2008-01-18

XSLT Root Node Problem

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.


Blog Archive