Kirk Evans Blog

.NET From a Markup Perspective

XSLT Geekery – Moving to the Root Node of the Transform Source?

Gary ponders in the microsoft.public.dotnet.xml forum, why System.Xml.Xsl.XslTransform in .NET moves to the document element of the transformation source document before transforming, while its MSXML counterparts did not.

In MSXML, two methods existed for transforming XML from the DOM:  TransformNode and TransformNodeToObject, and these methods do exactly what they advertise.  Both methods transform the current node and its context using the supplied stylesheet.  According to the DOM Level 1 IDL, and DOM Level 2 core IDL, TransformNode and TransformNodeToObject are not part of the W3C recommendation. This is a Microsoft extension to the DOM and, as such, is subject to changes in implementation.  This is a fact of life when using vendor-specific extensions.  If it’s not part of the W3C rec, then it is vendor-specific and open to interpretation and change, and not even guaranteed to be present between major versions. Microsoft did not alter these methods’ signatures or core behaviors between versions.  In fact, the DOMDocument and XslTransform classes are very dissimilar and not representative of a version release: .NET is a completely new platform.  System.Xml and its child namespaces share no common code with MSXML.

Despite the obvious platform differences, the fact remains that XslTransform and MSXML were written by the same teams and used the same test cases.  Why such a seemingly gaping difference in interpretation?  I don’t have any insight to answer this, but I can offer some background from the specs and offer my interpretation.

Section 5.1 of the XSLT recommendation states “Implementations are free to process the source document in any way that produces the same result as if it were processed using this processing model.” So, moving to the document root or processing the current node forward is open to interpretation.

Personally, I think that moving to the document root is the correct behavior. A great example is the template application:

< xsl:apply-templates select =” //doc />

This matches all “doc” descendants of the document root. Further, according to the XPath rec, “//doc” matches “all ‘doc’ elements in the same document as the context node. Given the relative *document* context, that means that it is appropriate to move to the root of *the document* and not the root of *the current node list*.

This seems contradictory when passing a node-set as a parameter to a stylesheet. By the same logic, the processor should move to the root node of the document containing the node-set passed into the stylesheet as a parameter. Instead, I think this is not contradictory at all: passing a node list as a parameter should cause the document context of the node list to be removed, creating a “sub document” or “fragment” (not the same as a result tree fragment, mind you). Moving to the root node of the context simply means moving to the root node of the node-set passed as a parameter.

In essence, the node-set becomes its own document.