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



The information in this article applies to:

  • Microsoft XML Classes (included with the .NET Framework 1.0)

This article was previously published under Q318580

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.IO
    Imports System.Data
    Imports System.Data.SqlClient
    Imports System.Xml
    Imports System.Xml.Xsl
    Imports System.Xml.XPath
    
    Module 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 Sub
    End 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:

Modification Type:MajorLast Reviewed:9/22/2003
Keywords:kbBCL kbprb KB318580 kbAudDeveloper