Search code examples
.netxsltembedded-script

Can xsl:script be used with XMLCompiledTransform?


I made an XSL script that used msxml:script for use with XMLCompiledTransform, but the people who need it said the script wouldn't work on their Linux/Perl environment (that's literally as much as I know about how they're using the XSL) because it "uses Microsoft specific extensions". So I'm trying to make the XSL more neutral by using xsl:script. However, I'm having difficulty making it work.

<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:theScript="urn:CustomScript" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xsl theScript fo xs fn">
<xsl:output method="xml" indent="yes" version="1.0" encoding="utf-8" omit-xml-declaration="no"/>
  <xsl:script language="javascript" implements-prefix="theScript">
      <![CDATA[
      function test() {return "test"; }
      ]]>
  </xsl:script>
  <xsl:template match="/">
    <test>
      <xsl:value-of select="theScript:test()" />
    </test>
  </xsl:template>
</xsl:stylesheet>

The above gives me the error "Cannot find the script or external object that implements prefix 'urn:CustomScript'."

If I get rid of xmlns:theScript="urn:CustomScript" it gives me the error "Prefix 'theScript' is not defined."

I've also tried removing all traces of "theScript" prefix and just using implements-prefix="local" but that doesn't work either. It tells me test is an unknown XSLT function.

So am I just doing something wrong here, or does XMLCompiledTransform not support xsl:script?


Solution

  • xsl:script is only defined in XSLT1.1, but this standard was cancelled in favor of XSLT2.0, so realistically if you're looking for portability, I wouldn't recommend using it.

    The most portable form of XSLT is definitely XSLT1.0, as there's far more support for it. Although some things are definitely easier in XSLT2.0, you'll probably find most 'script' code you might want to do can be done in just XSLT alone. XSLT2.0 can define functions, but you can emulate functions using named templates in XSLT1.0, it's just a bit more cumbersome.

    XSLT2.0:

    <xsl:template match="/">
      <xsl:value-of select="test('param')" />
    </xsl:template>
    
    <xsl:function name="test" as="xs:string">
      <xsl:param name="param" as="xs:string" />
      <xsl:text>Test</xsl:text>
    </xsl:function>
    

    XSLT1.0:

    <xsl:template match="/">
      <xsl:call-template name="test">
        <xsl:with-param name="param" select="'param'" />
      </xsl:call-template>
    </xsl:template>
    
    <xsl:template name="test">
      <xsl:param name="param" />
      <xsl:text>Test</xsl:text>
    </xsl:template>
    

    The parameter's not used in this example however, but you get the idea.