Cross-processor XSLT extension functions

David Carlisle’s posted a great tip on getting exsl:node-set() to work in IE:

In the above XSL-List thread I casually suggested that an alternative would be to just always use exslt:node-set in the body of the stylesheet and use the msxsl:script extension to define exslt:node-set for IE. That turned out not to be as easy as I thought as node-set isn’t a valid function name in either of the supported extension languages in msxsl (JScript or VBScript). However Julian Reschke came up with the construct needed, use associative array syntax so you can use [‘node-set’] to define the function.

I’ve been having related problems getting my XSLT unit testing framework to work with XSLT 1.0 stylesheets designed to work with MSXML, and specifically to use the msxsl:node-set() function. The solution there was to provide an implementation of msxsl:node-set() using <xsl:function>:

<xsl:function name="msxsl:node-set" as="document-node()" override="no">
  <xsl:param name="items" as="item()*" />
  <xsl:document>
    <xsl:sequence select="$items" />
  </xsl:document>
</xsl:function>

Note the override="no" which marks this as an implementation to be used only when the processor doesn’t support it natively. This is an issue with msxsl:node-set() at the moment, but in the general case if you’re writing a user-defined function that mirrors a vendor’s extension function then you ought to use override="no".

What I should do is add XSLT 2.0 implementations of all the EXSLT functions to the unit testing framework too…

Comments

Re: Cross-processor XSLT extension functions

What I should do is add XSLT 2.0 implementations of all the EXSLT functions to the unit testing framework too…

Better still would be to add them to exslt.org as an implementation of exslt for xslt2 systems. Not so useful long term, as xslt2 has most of the functionality natively but very useful short term either to make stylesheets that run on xslt1+exslt and xslt2 without needing conditional code around every function call, or (very much a concern here at present) as an aid to switching from xslt1 to 2.

We tend to use saxon rather than exslt extensions (for historical reasons mainly) but it’s proved very valuable to have functions like

<xsl:function name="saxon:tokenize">
  <xsl:param name="s"/>
  <xsl:sequence select="tokenize($s,'\s+')"/>
</xsl:function>

<xsl:function name="saxon:node-set">
  <xsl:param name="rtf"/>
  <xsl:sequence select="$rtf"/>
</xsl:function>

<xsl:function name="saxon:distinct">
  <xsl:param name="n"/>
  <xsl:sequence select="distinct-values($n)"/>
</xsl:function>

We’ll remove these (and permanently switch to xslt2) sometime soon, but during the changeover testing such functions allow comparison of results on the old and new processor without changing the stylesheet which is a good thing as there’s over 20K lines of stylesheet(s) in this case…

David

Re: Cross-processor XSLT extension functions

“What I should do is add XSLT 2.0 implementations of all the EXSLT functions to the unit testing framework too…”

Yes please :) That would be FANTASTIC!