[Webinar] Streamline your web hosting managementRegister Today

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 388
  • Last Modified:

How to avoid compiling xsl file everytime invoking XslCompiledTransform.Transform?

hi,

I am using XslCompiledTransform.Transform function to transform an xml into another xml file using an XSL.
When I invoke the Transform function it is taking several minutes everytime to compile the xsl file.

Is there any way to save the compiled xsl and use the compiled version when invoking Transform function?

Thanks for any help.
0
ipjyo
Asked:
ipjyo
  • 7
  • 4
5 Solutions
 
käµfm³d 👽Commented:
The Load() method of XslCompiledTransform actually compiles the stylesheet. As long as you maintain a reference to the original object and do not call Load() again, then the stylesheet should remain compiled.
0
 
ipjyoAuthor Commented:
Thanks for the useful information.

I dont maintain a reference to the original object.
I have the transform function defined in another project and I am referencing that assembly and invoking a method called DoTransform() with two parameters (XSL, XML) which in turn does the load and transform methods.
Is it possible to serialize the compiled XSL transform and when I invoke DoTransform() it will check if the xsl that is passed to DoTransform() and the deserialized xsl are same. If they are same avoid Load() otherwise Load() again. Is this scenario possible?

Thanks for the help.
0
The new generation of project management tools

With monday.com’s project management tool, you can see what everyone on your team is working in a single glance. Its intuitive dashboards are customizable, so you can create systems that work for you.

 
käµfm³d 👽Commented:
I'm not sure. But to me, that sounds overly complicated.

It seems to me that you have multiple stylesheets that you want to be able to call on demand without having to compile them each time they are used. The following could be a potential solution, but depending on how many stylesheets you have, could use a good bit of memory (change "outfile.xml" to fit your situation):
public class TransformClass
{
    private Dictionary<string, XslCompiledTransform> transformers;

    public TransformClass()
    {
        this.transformers = new Dictionary<string, XslCompiledTransform>();
    }

    public void DoTransform(string xsl, string xml)
    {
        if (!this.transformers.Keys.Contains(xsl))
        {
            this.transformers.Add(xsl, new XslCompiledTransform());
            this.transformers[xsl].Load(xsl);
        }

        this.transformers[xsl].Transform(xml, "outfile.xml");
    }
}

Open in new window

0
 
käµfm³d 👽Commented:
Looking back, I suppose the above is what you described...   the mention of "serialization" threw me off a bit   :)
0
 
ipjyoAuthor Commented:
Hi,
My requirement is similar to what you have suggested.
Based on the description and code above, My understanding is that when a particular xsl is modified and invoke DoTransform() I need to pass a new key associated with the modified xsl and then load that xsl into the dictionary with that new key.

I am more concerned about what happens when the stylesheet is modified rather than being able to maintain multiple stylesheets? How would I know if it is modified from the previous version? I need to be able to compile the xsl only when it is modified.

Thank you.
0
 
ipjyoAuthor Commented:
I was also reading the link you provided.
It says "especially for server applications, to cache an XslCompiledTransform instance if the same stylesheet is likely to be executed again."

If you have any idea Could you tell me how to implement caching mechanism in windows application?
Thanks.
0
 
käµfm³d 👽Commented:
The path to the XSL is what I used as the key--you can of course use whatever key you like, but I thought the path would be unique between stylesheets.

As to modifications...   Even if you maintain one XslCompiledTransform object, how would it know that the stylesheet has change? Without calling the Load() method each time, the XslCompiledTransform object is going to have the last stylesheet it was given compiled into memory when you call Transform().

Unless someone can speak otherwise, my guess would be that you would need to keep track of when your XSL changes. You could probably get away with some checksum'ing:
public class TransformClass
{
    private byte[] stylesheetChecksum;
    private XslCompiledTransform transformer;

    public TransformClass()
    {
        this.transformer = new XslCompiledTransform();
    }

    public void DoTransform(string xsl, string xml)
    {
        byte[] incomingChecksum = GetStylesheetChecksum(xsl);

        if (this.stylesheetChecksum == null)
        {
            this.stylesheetChecksum = incomingChecksum;
        }

        if (!CompareCheckSums(incomingChecksum))
        {
            this.transformer.Load(xsl);
        }

        this.transformer.Transform(xml, "outfile.xml");
    }

    private byte[] GetStylesheetChecksum(string XSL)
    {
        byte[] hash;

        using (System.IO.FileStream stylesheet = new System.IO.FileStream(XSL, System.IO.FileMode.Open))
        {
            System.Security.Cryptography.MD5 checksum = new System.Security.Cryptography.MD5CryptoServiceProvider();
            hash = checksum.ComputeHash(stylesheet);
        }

        return hash;
    }

    private bool CompareCheckSums(byte[] newCheckcsum)
    {
        if (this.stylesheetChecksum.Length != newCheckcsum.Length) return false;

        for (int i = 0; i < newCheckcsum.Length; i++)
        {
            if (this.stylesheetChecksum[i] != newCheckcsum[i])
            {
                return false;
            }
        }

        return true;
    }
}

Open in new window

0
 
käµfm³d 👽Commented:
Slight modification to my DoTransform() above:
public void DoTransform(string xsl, string xml)
{
    byte[] incomingChecksum = GetStylesheetChecksum(xsl);

    if (this.stylesheetChecksum == null)
    {
        this.stylesheetChecksum = incomingChecksum;
        this.transformer.Load(xsl);
    }

    if (!CompareCheckSums(incomingChecksum))
    {
        this.transformer.Load(xsl);
    }

    this.transformer.Transform(xml, "outfile.xml");
}

Open in new window

0
 
ipjyoAuthor Commented:
Thank you very much for all your help.
I appreciate your help on this post.



0
 
käµfm³d 👽Commented:
NP.  I enjoy assisting others when I can  :)
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 7
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now