Slowly, gradually and with not much loud buzz both modern managed platforms - Java and .NET have switched to compiling XSLT implementations by default. First Java 5.0 made compiling Apache XSLTC processor a default transformer in JAXP 1.3 (instead of interpreting Apache XALAN). Then Microsoft released .NET 2.0 with new XSLT implementation - XslCompiledTransform replacing now obsolete XslTransform (guess what - interpreting one). XSLTC compiles XSLT into Java bytecode just like Java compiler, while XslCompiledTransform compiles XSLT into Microsoft Intermediate Language (MSIL) just like C# or VB compiler. The similarity is striking. Does it mean the era of interpreting XSLT processors is over and XSLT compilation is the future?
Both Java and .NET declare the same reason for adopting XSLT compilation - performance. Here is a snippet from JAXP 1.3 documentation:
o XSLTC, the fast, compiling transformer, which is now the default engine for XSLT processing.
The XSLTC transformer generates a transformation engine, or translet, from an XSL stylesheet. This approach separates the interpretation of stylesheet instructions from their runtime application to XML data.And here is what Microsoft XML Team writes about XslCompiledTransform:
XSLTC works by compiling a stylesheet into Java byte code (translets), which can then be used to perform XSLT transformations. This approach greatly improves the performance of XSLT transformations where a given stylesheet is compiled once and used many times. It also generates an extremely lightweight translet, because only the XSLT instructions that are actually used by the stylesheet are included.
To improve XSLT execution performance in the .NET Framework version 2.0, the XslTransform class has been replaced with a new XSLT 1.0 implementation: the XslCompiledTransform class. XslCompiledTransform compiles XSLT stylesheets to Microsoft Intermediate Language (MSIL) methods and then executes them. Execution time of the new processor is on average 4 times better than XslTransform and matches the speed of MSXML, the native XML processor.
Is it true that only XSLT compilation can provide the best XML transformation performance on managed platforms like Java and .NET? I have no fresh benchmark results, but AFAIR XSLTC was always one of the fastest XSLT processors undeservedly underused because of its unique processing model. And Microsoft also claims that new XslCompiledTransform now matches the speed of MSXML4. But what about Saxon? It's interpreting XSLT engine and it's pretty fast. I believe Saxon is fast only due to numerous very smart and unique optimizations and so can't beat compiling optimizing XSLT processor.
The idea that ideal XSLT engine is optimizing compiling one sounds pretty obvious. XSLT was and is meant to be compiled, not interpreted and despite the fact that for years there was only a single semi-experimental compiling XSLT engine around - Sun's XSLTC (now Apache XSLTC), XSLT 2.0 is still looks like more traditional compiled language than a dynamic one.
Ok, but what about the future? I think that's safe to say that in the future XSLT compilation will be even more pervasive. Apache community (with IBM behind contributing developers) have chosen XSLTC, not XALAN as a basis for their future XSLT 2.0 implementation and I have no doubts that Microsoft will implement XSLT 2.0 only as a compiling engine too. And I love it. I predict that in a near future we will be compiling XSLT stylesheets as we do with ordinary Java or C# classes and call "translets" at run time as usual classes without bothering to load stylesheet sources first.
Btw, it should be noted that for Java users the switch to another default XSLT engine went mostly unnoticed thanks to JAXP, while Microsoft has no JAXP analog so users have to migrate to the XslCompiledTransform explicitly modifying their code. I'll address that in a separate post though.
Mahesh, first make sure you really need to transform into XmlReader. In .NET 1.X transforming to XmlReader was the way to transform into XmlDocument, now in .NET 2.0 you can do it via XmlWriter returned by doc.CreateNavigator().AppendChild().
If you really need XmlReader, take a look at XslReader from the Mvp.Xml library.
See http://blogs.msdn.com/xmlteam/articles/Introducing_XslCompiledTransform.aspx for more info.
Question:- How do I get the results of the XSLCompiledTransform.Transform method into an XML.XMLreader object?
Hi,
I ran into following situation when migrating my framework 1.1 codes to 2.0:
Old situation (.net v1.1):
==========xslt file=============
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/TR/xslt.html#strip">
<xsl:output method="text" version="1.0"
encoding="UTF-8" indent="no"/>
<xsl:variable name="SelectedStateId" />
<xsl:template match="Jurisdictions">
<xsl:param name="iSelectedStateId" select="$SelectedStateId" />
<script type="text/javascript">
//Array for List items
//Xsl-Param:SelectedStateId: <xsl:value-of select="$iSelectedStateId" />
var tmpCityArr = new Array(3);
tmpCityArr[0] =
<xsl:for-each select="Country[JurisId=50001]">
new Array('<xsl:value-of select="JurisName" />|<xsl:value-of select="JurisId" />'<xsl:for-each select="State">,
new Array('<xsl:value-of select="JurisName" />|<xsl:value-of select="JurisId" />'<xsl:if test="JurisId = $SelectedStateId"><xsl:for-each select="City">,
new Array('<xsl:value-of select="JurisName" />|<xsl:value-of select="JurisId" />')<!-- SELECTED -->
</xsl:for-each></xsl:if>)</xsl:for-each></xsl:for-each>
);
tmpCityArr[1] =
<xsl:for-each select="Country[JurisId=50002]">
new Array('<xsl:value-of select="JurisName" />|<xsl:value-of select="JurisId" />'<xsl:for-each select="State">,
new Array('<xsl:value-of select="JurisName" />|<xsl:value-of select="JurisId" />'<xsl:if test="JurisId = $SelectedStateId"><xsl:for-each select="City">,
new Array('<xsl:value-of select="JurisName" />|<xsl:value-of select="JurisId" />')<!-- SELECTED -->
</xsl:for-each></xsl:if>)</xsl:for-each></xsl:for-each>
);
tmpCityArr[2] =
new Array('International|' <xsl:for-each select="Country[JurisId != 50001 and JurisId != 50002]">,
new Array('<xsl:value-of select="JurisName" />|<xsl:value-of select="JurisId" />'<xsl:if test="JurisId = $SelectedStateId"><xsl:for-each select="State">,
new Array('<xsl:value-of select="JurisName" />|<xsl:value-of select="JurisId" />')
</xsl:for-each></xsl:if>)</xsl:for-each>
);
</script>
</xsl:template>
</xsl:stylesheet>
===================================
==============aspx page codebehind========
private XmlReader __prepareXmlData(IXPathNavigable inputXml, string xslTransform, object[] xslParams )
{
//get transform
XslTransform xt = new XslTransform();
xt.Load(Server.MapPath(xslTransform));
XsltArgumentList xslArgs = new XsltArgumentList();
if (null != xslParams)
{
for (int i = 0; i < xslParams.Length; i++)
xslArgs.AddParam((string)xslParams[i], tring.Empty, xslParams[++i]);
}
//transform string
XmlUrlResolver resolver = new XmlUrlResolver();
resolver.Credentials = System.Net.CredentialCache.DefaultCredentials;
XmlReader xr = xt.Transform(inputXml, xslArgs, resolver);
Retrurn(xr);
}
=============================
Facts in the ASP 2.0 world are:
1 Now, new and shiny XslCompiledTransform class doesn't support this feature anymore, transformation output is now only Stream, TextWriter or XmlWriter
2) XslTransform objects (class) is obsolete as well.
Note: for the above method we are Storing the Xslt file in resources is fine. When you need the file the easiest solution is to write the resource to file and use the XslCompiledTransform.Load (String) where String is path of file.
All above code is working fine in .net 1.1 but it's not working in .net 2.0.
Hope you can help?
Thanks.
best regards
Mahesh
Hello - I am trying to find more about compiled XSLTs as the performance is poor when we have scripts embedded in the XSLT. Any reason why?
Balaji