Showing posts with label XslCompiledTransform. Show all posts
Showing posts with label XslCompiledTransform. Show all posts

December 21, 2014

Weak References with Compiled Transforms

There is a good description of this generic WeakReference<> class here.
Here is an example of using WeakReferences for caching XslCompiledTransform's:
private static Dictionary<string, WeakReference<XslCompiledTransform>> xsltLookupTable = 
  new Dictionary<string, WeakReference<XslCompiledTransform>>();

public XslCompiledTransform GetCompiledTransform(string xslFileName)
{
    XslCompiledTransform xct = null;
    bool found = xsltLookupTable.ContainsKey(xslFileName);
    if (found) // IF the transform is already cached
    {   // Try and get it
        WeakReference<XslCompiledTransform> xctWr = xsltLookupTable[xslFileName] 
           as WeakReference<XslCompiledTransform>;
        xctWr.TryGetTarget(out xct); // Try and get it from the WeakReference
        m_logger.WriteTrace("Found XslCompiledTransform entry for \'" + 
           xslFileName + "\' in the cache");
        // Note the entry maybe null (if the weak reference expired)
    }
        
    if (xct == null) // IF the compiled transform was not already cached
    {
        // Create it
        xct = new XslCompiledTransform();
        xct.Load(xslFileName, 
          new XsltSettings { EnableDocumentFunction = true }, 
          new XmlUrlResolver());
        // Insert it into a WeakReference
        WeakReference<XslCompiledTransform> wr = new 
          WeakReference<XslCompiledTransform>(xct);
        if (found)
        {
          m_logger.WriteTrace("Removing XslCompiledTransform entry for \'" + 
              xslFileName + "\' as it was null in the cache");
          xsltLookupTable.Remove(xslFileName);
        }
        xsltLookupTable.Add(xslFileName, wr); // Add the WeakReference to the cache
        m_logger.WriteTrace("Adding XslCompiledTransform entry for \'" + 
          xslFileName + "\'");
    }
    return xct;
}
It uses the new generic WeakReference<> class (available in .NET 4.5?). This class could be further refactored into a generic caching class if it was required.

February 13, 2006

XslCompiledTransform

New replacement for XslTransform in .NET version 2.0 is XslCompiledTransform. This is apparently faster. Here is a sample to prepare it:
private XslCompiledTransform xctCached = null;

private XslCompiledTransform GetXsltTransform()
{
  if (this.xctCached == null)
  {
    // Retrieve the xslt
    string xslt = RetrieveEmbeddedStringResource(
        "ViewNUnitTestResults.Resources.NUnitTestResultsToHtml.xsl");
    XmlTextReader xsltReader = new XmlTextReader(new
        StringReader(xslt));                        
    // Create the compiled xslt transform
    this.xctCached = new XslCompiledTransform();
    this.xctCached.Load(xsltReader);
  }
  return this.xctCached;
}
and then use it:
public string ApplyXslTransform(
    string sourceXml, XslCompiledTransform xct)
{
  // read XML
  XmlTextReader xmlReader = new XmlTextReader(
    new StringReader(sourceXml));

  //create the output stream
  StringBuilder sb = new StringBuilder();
  using (StringWriter outputWriter = new StringWriter(sb))
  {
    // Do the transform
    XsltArgumentList args = new XsltArgumentList();
    xct.Transform(xmlReader, args, outputWriter);
  }

  return sb.ToString();
}
You can still use the XslTransform class though:
#region Using XslTransform

public string ApplyXslFromManifest(string sourceXml)
{
    XslTransform xslt = GetXslTransform();
    return ApplyXslTransform(sourceXml, xslt);
}

private XslTransform xtCached = null;

private XslTransform GetXslTransform()
{
    if (this.xtCached == null)
    {
        string xsltString = RetrieveEmbeddedStringResource(
            "ViewNUnitTestResults.Resources.NUnitTestResultsToHtml.xsl");
        XmlTextReader xsltReader = new XmlTextReader(new 
            StringReader(xsltString));
        this.xtCached = new XslTransform();
        this.xtCached.Load(xsltReader);
    }
    return this.xtCached;
}

public static string ApplyXslTransform(
    string sourceXml, XslTransform xslt)
{
    // read XML
    XmlTextReader xmlReader = new XmlTextReader(new
    StringReader(sourceXml));

    //create the output stream
    StringBuilder sb = new StringBuilder();
    TextWriter outputWriter = new StringWriter(sb);

    // Transform the Xml
    XPathDocument xPathDocument = new XPathDocument(xmlReader);
    xslt.Transform(xPathDocument, null, outputWriter, null);

    //get result
    return sb.ToString();
}

#endregion Using XslTransform
Althouh the documentation says it is obsolete, I think if the xslt is only going to be used once only it would be slightly faster to use the XslTransform class. The compiled transform is best when the compiled xslt object is going to be used multiple times, see the article "Properly Utilizing XslCompiledTransform". Check this article on a thorough analysis of the 2 different XSLT transforms in .NET, their speed differences and some recommendations on when to use which.