Groups | Blog | Home
all groups > dotnet xml > july 2004 >

dotnet xml : .net framework XSLT processor appears to be broken


a701440 NO[at]SPAM hotmail.com
7/14/2004 7:05:08 AM
I stumbled upon this while developing a custom XPathNavigator.
It appears that copy action for attributes is broken in the .net
framework XSLT processor.

The intent was to just copy the entities and attributes from the
source XML into the output using simple "identity" like XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

This appears to loose the attributes of non-leaf entities when run
over a custom XPathNavigator. The problem appears to be related to the
order of processing. When run over a custom XPathNavigator the child
entities are processed before the attributes in the above XSLT.

The situation can be recreated over a regular XmlDocument using
following XSLT:

This does not work (notice the order of processing - attributes are
processed first):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="*|/">
<xsl:copy>
<xsl:apply-templates select="*" />
<xsl:apply-templates select="@*" />
</xsl:copy>
</xsl:template>

<xsl:template match="@*">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>

This does work (notice the order of processing - attributes are
processed first)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="*|/">
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="*" />
</xsl:copy>
</xsl:template>

<xsl:template match="@*">
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>

Here is a quick and dirty code snippet:
---------------------------------------------------------
String xsltFileName = "test.xslt";
XmlReader transfromReader = new XmlTextReader(xsltFileName);

XslTransform transform = new XslTransform();
transform.Load(transfromReader);

StringBuilder result = new StringBuilder();
TextWriter writer = new StringWriter(result);

String xmltestFileName = "test.xml";
XmlDocument testDocument = new XmlDocument();
testDocument.Load(xmltestFileName);

transform.Transform(testDocument,null,writer);
---------------------------------------------------------

Any XML document with several levels of entity nesting and some
Oleg Tkachenko [MVP]
7/15/2004 10:11:38 AM
[quoted text, click to view]

Well, it works for me (and always worked). Apparently the problem is
with your custom XPathNavigator? Provide more information about it.

[quoted text, click to view]
You meant attributes are processed after elements. This shouldn't work
according to the XSLT spec. Attributes must be processed before child
nodes. Identity transformatio assures it by using
<xsl:apply-templates select="@* | node()"/>
Here xsl:apply-templates instruction processes selected nodes in
document order and attributes go before child nodes in document order by
definition.
--
Oleg Tkachenko [XML MVP]
a701440 NO[at]SPAM hotmail.com
7/15/2004 10:35:28 AM
Thank you for the reply.

[quoted text, click to view]

A custom XPathNavigator does not have any real ability to influence
the
order of processing (attributes vs. child elements). In my case the
XPathNavigator exposes a very complex repository as virtual XML...

The navigator only implements the minimum set of necessary functions
like MoveNext(), etc. It does not implement any custom XPath engine,
etc.

What I observe is that in the case of Identity transformation the
attributes
are processed after the child elements when transforming my
XPathNavigator.

However when the same transformation is used to transform a
XmlDocument
it processes the attributes first.


[quoted text, click to view]
by
Oleg Tkachenko [MVP]
7/19/2004 1:59:09 PM
[quoted text, click to view]

Hmmm, you are right. I wonder how the problem can be traced. Can you
dump a sequence of calls to your XPathNavigator? Try to debug it to see
how it gets moved, sometimes weird things might happen just because of a
single forgotten Clone() call.

[quoted text, click to view]

Try modified identity transformation to find out where the problem is:

<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>

--
Oleg Tkachenko [XML MVP]
AddThis Social Bookmark Button