PRB: XSL Transformations with XmlDataDocument May Perform More Slowly Than XPathDocument

This article was previously published under Q318580
This article has been archived. It is offered "as is" and will no longer be updated.
Symptoms
XSL transformations (XSLT) with System.Xml.XmlDataDocument may run more slowly than XSLT with XPathDocument or XmlDocument.
Cause
XmlDataDocument is primarily designed to act as the bridge between the DataSet and XML.
Resolution
Run XSL transformations by using the XmlDocument or XPathDocument classes instead of XmlDataDocument. Microsoft recommends that you use XPathDocument, because it is highly optimized for XSL transformations. See the "More Information" section of this article for a code sample that uses the XPathDocument.
Status
This behavior is by design. The XmlDataDocument class is primarily designed for synchronizing XML with DataSet. Microsoft is looking into improving its performance for transformations in the next major release of Visual Studio .NET.
More information
The following is a Visual Basic .NET code sample that shows you how to apply XSL transformations on a DataSet by using the XPathDocument class. The sample initially loads the data from the Customers table and the Order table of the Northwind database into to a DataSet, and then the DataSet is transformed with the XmlDataDocument and XPathDocument classes.

Steps to Reproduce the Behavior

  1. Create a new Visual Basic .NET Console application project.
  2. Copy and paste the following into a file, and then save the file as Transform.xsl in the bin directory of the application:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"><xsl:template match="CustomerOrders">  <HTML>  <STYLE>  BODY {font-family:verdana;font-size:9pt}  TD   {font-size:8pt}  </STYLE>    <BODY>    <TABLE BORDER="1">      <xsl:apply-templates select="Customers"/>    </TABLE>    </BODY>  </HTML></xsl:template><xsl:template match="Customers">    <TR><TD>      <xsl:value-of select="ContactName"/>, <xsl:value-of select="Phone"/><BR/>    </TD></TR>      <xsl:apply-templates select="Orders"/></xsl:template><xsl:template match="Orders">  <TABLE BORDER="1">    <TR><TD valign="top"><B>Order:</B></TD><TD valign="top"><xsl:value-of select="OrderID"/></TD></TR>    <TR><TD valign="top"><B>Date:</B></TD><TD valign="top"><xsl:value-of select="OrderDate"/></TD></TR>    <TR><TD valign="top"><B>Ship To:</B></TD>        <TD valign="top"><xsl:value-of select="ShipName"/><BR/>        <xsl:value-of select="ShipAddress"/><BR/>        <xsl:value-of select="ShipCity"/>, <xsl:value-of select="ShipRegion"/>  <xsl:value-of select="ShipPostalCode"/><BR/>        <xsl:value-of select="ShipCountry"/></TD></TR>  </TABLE></xsl:template></xsl:stylesheet>					
  3. Replace the code in Module1.vb file with the following.
    Imports System.IOImports System.DataImports System.Data.SqlClientImports System.XmlImports System.Xml.XslImports System.Xml.XPathModule Module1   Sub Main()      Try         ' Fill a DataSet with data from Customers and Orders tables of northwind database         Dim nwindConn As SqlConnection = New SqlConnection("Password=;User ID=sa;Initial Catalog=Northwind;Data Source=localhost")         nwindConn.Open()         Dim myDataSet As DataSet = New DataSet("CustomerOrders")         Dim custDA As SqlDataAdapter = New SqlDataAdapter("SELECT * FROM Customers", nwindConn)         custDA.Fill(myDataSet, "Customers")         Dim ordersDA As SqlDataAdapter = New SqlDataAdapter("SELECT * FROM Orders", nwindConn)         ordersDA.Fill(myDataSet, "Orders")         nwindConn.Close()         myDataSet.Relations.Add("CustOrders", _                                 myDataSet.Tables("Customers").Columns("CustomerID"), _                                 myDataSet.Tables("Orders").Columns("CustomerID")).Nested = True         ' Load the stylesheet          Dim xslTran As XslTransform = New XslTransform()         xslTran.Load("transform.xsl")         ' Create a writer to stream the results to a file         Dim writer As XmlTextWriter = New XmlTextWriter("xslt_output.html", System.Text.Encoding.UTF8)         ' I. Transform the DataSet data with XmlDataDocument         Dim startTime As DateTime         ' Synchronize an XmlDataDocument with the DataSet         Dim xmlDataDoc As XmlDataDocument = New XmlDataDocument(myDataSet)         startTime = DateTime.Now         xslTran.Transform(xmlDataDoc, Nothing, writer)         Console.WriteLine("Time taken with XmlDataDocument: " + ((DateTime.Now).Subtract(startTime)).TotalSeconds.ToString())         ' II. WORKAROUND: Use XPathDocument to transform the DataSet data         Dim xpathDoc As XPathDocument = New XPathDocument(New StringReader(myDataSet.GetXml()))         startTime = DateTime.Now         xslTran.Transform(xpathDoc, Nothing, writer)         Console.WriteLine("Time taken with XPathDocument  : " + ((DateTime.Now).Subtract(startTime)).TotalSeconds.ToString() + vbNewLine)         Console.ReadLine()         writer.Close()      Catch e As Exception         Console.WriteLine("{0}", e.Message)      End Try   End SubEnd Module
  4. Modify the connection string to suit your database settings. Compile and run the application. Read the inline comments to understand the functionality of the code.
References
For more information, click the links below to view the Software Developer Kit (SDK) documentation and the Microsoft Knowledge Base articles:
313651 ROADMAP for XML in the .NET Framework
To view the Software Developer Kit (SDK) documentation, visit the following Microsoft Web site:
Properties

Article ID: 318580 - Last Review: 10/26/2013 08:11:00 - Revision: 3.0

  • Microsoft .NET Framework 1.0
  • kbnosurvey kbarchive kbbcl kbprb KB318580
Feedback