Question

I'm using a system which consists of many complex XSL transforms which each work on large XML files. A proprietary program compiles the XSLT on each of the XML files, before passing the XML files to our databases.

The XSL transforms almost always involve C# functions within <msxsl> tags, many which are repeated between several files with the code copied manually. I'm trying to implement a system where a general repository of functions are stored in one file, and then loaded into the XSLT file before being read by the <msxsl> tags.

My problem is that I have been unable to find a way to have the code within <msxsl> loaded from an external file. Here's an example of what I mean:

The transform with the function hard-coded:

...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:msxsl="urn:schemas-microsoft-com:xslt"
            xmlns:cs="urn:my-scripts-csharp">

...

<msxsl:script language="C#" implements-prefix="cs">
  <![CDATA[
    public string emphasise(string input) {
      return input+"!";
    }
  ]]>
</msxsl:script>

...

Whilst I'd like the function loaded externally:

...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:msxsl="urn:schemas-microsoft-com:xslt"
            xmlns:cs="urn:my-scripts-csharp">
...

<msxsl:script language="C#" implements-prefix="cs">
  <--- file loaded here --->
</msxsl:script>

...

Where the source file would be something like:

<![CDATA[
  public string emphasise(string input) {
    return input+"!";
  }
]]>

Is this possible? The functions are generally complex (unlike this example) and cannot be reproduced with XSLT code. Would namespace and using keywords from the external file be read or would I have to include them outside of it with <msxsl:using> tags?

I'm quite new to the use of <msxsl> tags, and if I'm misunderstanding something fundamental then do please let me know!

Was it helpful?

Solution

I. Here is how to do it:

File: C:\temp\delete\c#script.xsl

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:cs="urn:my-scripts-csharp">  
    <msxsl:script language="C#" implements-prefix="cs">
    <![CDATA[
     public string emphasise(string input)
     {
      return input+"!";
      }
      ]]></msxsl:script>
</xsl:stylesheet>

Your transformation:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt"
 xmlns:cs="urn:my-scripts-csharp">

 <xsl:include href="C:\temp\delete\c#script.xsl"/>

 <xsl:template match="/">
  <xsl:value-of select="cs:emphasise('Hello')"/>
 </xsl:template>
</xsl:stylesheet>

When this transformation is performed (on any XML document), the wanted result is produced:

Hello!

Warning: Using inline scripts like these is known to cause memory fragmentation if the transformation is repeated many times and this can lead to memory leaks.

I strongly recommend not to use inline scripts at all. A better, more efficient and safe approach is to have all necessary extension functions in an extension object -- read about the XsltArgumentList class and its AddExtensionObject() method.

OTHER TIPS

You can reference code in external assemblies using : http://msdn.microsoft.com/en-us/library/ms256188.aspx - that could provide a way of moving your code to an external location

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top