XslCompiledTransform Caching

On a project i'm working, we use lots of XSLT for XML tranformation.

Because XsltCompiledTransform has a very slow load, we are trying to reach the best "caching" method, in a way that all xsl files be loaded in a object  we can use once the web application starts.

The idea we're trying to implement is to have an outsider application(or not) which will browse all xsl files, load them using XslCompiledTransform, and save the objects in an hashtable. The problem is, that we would like to serialize the hashtable, but XslCompiledTransform is not marked as serializable. We've already tried using a surrogate (implementing the ISerializationSurrogate) and custom serialization (implementing the ISerializable interface), but always get the same message: XsltCompiledTransform is not marked as serializable.

So, i would like to know first, if we are jumping some basic steps of the new XslCompiledTransform class (in .net framework 2.0) in terms of xsl caching, and if we can serialize the XslCompiledTransform objects in some way...

Thanks in advance,

Luis Neves



Answer this question

XslCompiledTransform Caching

  • talshac

    Compiling each XSLT to assembly on disk, like VB and C#, would be helpful, assuming there will be way of getting all compiled transforms into a collection or similar, abling to serialize one object only. Then we would just need to affect a static variable or add an item to global cache (which is better, by the way ) with the deserialized object when the web application starts . Then, on user page request, we'll access the "collection", and get the correct compiled tranform for the XML transformation.

    If the XSLT compilation for each stylesheet is meant for individual serialization, can help too, but if i understood, will force to read each file on runtime, or when the application starts all the files have to be read for deserialization in way of getting all compiled transforms (imagine 800 files)...

    I still don't get, why don't i have better performance using XslCompiledTransform class than XslTransform, even using a static hashtable for compiled transforms reuse. And stranger is the fact that i've tested this application with framework 2.0 beta 2, and it was way faster! Unfortunatelly lost that code.

    Anyway, are your efforts for a short time solution, or in way to include in a future framework update

    I would be very thankful if we could change ideas in order to get the best solution for this matter.

    Luis Neves.


  • Mohamed Kishk

    We've decided to add xslCompiledTransform objects to Web cache instead of into an hashtable.

     

    XslCompiledTransform xsltObject = new XslCompiledTransform();

    xsltObject.Load(sPath, null,resolver);

    HttpContext.Current.Cache.Insert(XSLFilePath, xsltObject, new CacheDependency( XSLFilePath), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable,null);

     

    By the way, i would like to get some opinions on this approach.

    Luis Neves

     

     


  • Miguel Ortiz Falcón

    We currently don't support any pre-compiled version of xslt stylesheets, and serialization of XslCompiledTransform is not possible, yet. We are working on it. The best way is to compile and keep them in global cache, as long as the web server restarts they will be there.

    Thanks



  • PDagent

    Hi,

    Do you have the code to store XslCompiledTransform objects in a hastable Would be much appreciated.

    Cheers,
    THal


  • khanhpt

    Luis,

    This is something that I have been pushing the XML/Webdata team to implement. I don't know if it will ever happen, but it is something the some of the XML MVPs have been asking to add to .Net, making things like XSLT and XSD first class languages within .Net.

    Don Demsak

    MVP-XML

    www.donxml.com


  • Simon Harriyott

    I don't think we would be able to ship any improvements to XslCompiledTransform soon. Unfortunately.

    Currently we are looking for the way to help you efficiently use existent product and fund way we could improve in long term.

    XslCompiledTransform is much faster then XslTransform, unless you recompile your stylesheet before each run.



  • prgMan

    XslCompiledTransform.Load() actually compiles XSLT to IL. Its not easy (impossible) to serialize compiled assembly. The best you can do now is to cache compiled transforms. When you decided to drop stylesheet best you can do now is compile it again.

    We have another customer who needs XSLT serialization. We'd be happy to hear more details about your requirements. For example will it help you if we compile XSLT to assembly on disk as VB and C# does



  • Orjan Lindberg

    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" />

    &lt;script type="text/javascript"&gt;

    //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>

    );

    &lt;/script&gt;

    </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)xslParamsIdea, 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.

    BUT How do I get the results of the XSLCompiledTransform.Transform method into an XML.XMLreader object

    Hope you can help
    Thanks.
    best regards
    Mahesh



  • XslCompiledTransform Caching