Hi, Andy. Andy Chambers <achambers.h...@googlemail.com> wrote on 2009-02-06 05:24:42 AM: > Consider the following stylesheet.... > > <?xml version="1.0" encoding="UTF-8"?> > <xsl:stylesheet version="1.0" > xmlns:xsl="http://www.w3.org/1999/XSL/Transform" > xmlns:str="http://exslt.org/strings"> > > <xsl:template match="/"> > <root> > <xsl:choose> > <xsl:when test="function-available('str:tokenize')"> > <!-- called when run by xalan --> > <xsl:value-of select="str:tokenize('date math str')"/> > </xsl:when> > <xsl:otherwise> > <!-- called when run by saxon --> > <xsl:value-of select="tokenize('date math str')"/> > </xsl:otherwise> > </xsl:choose> > </root> > </xsl:template> > > </xsl:stylesheet> > > My specific problem is that saxon supports the use of XSLT2's tokenize > which is supported in xalan using the exslt str extension. > > I need my stylesheet to work in both and my plan was to use > function-available('str:tokenize') to determine which one to use. The > problem is that even though xalan wouldn't enter the second branch, it > detects that it can't call tokenize and throws the following > error. > > SystemId Unknown; Line #15; Column #55; Could not find function: tokenize > SystemId Unknown; Line #15; Column #55; function token not found. > (Location of error unknown)java.lang.NullPointerException
XSLT 1.0 is a bit vague on how references to unknown functions that are in no namespace should be handled. Section 2.5 on Forwards-Compatible Processing[1] states, "If an expression occurs in an attribute that is processed in forwards-compatible mode, then an XSLT processor must recover from errors in the expression as follows: ... if the expression calls a function with an unprefixed name that is not part of the XSLT library, then an error must not be signaled unless the function is actually called." So this seems to imply that the processor should raise an error for the reference to tokenize when not in forwards-compatible mode, but the recommendation never actually comes out and states that explicitly anywhere. Having said that, Xalan-Java has a bug and still reports that same error when the stylesheet is processed in forwards-compatible mode (i.e., the version attribute on the xsl:stylesheet element has the value "2.0".) However, Xalan-J does not have this same problem with extension functions - the processor will only report an error for an extension function that it does not recognize if it attempts to evaluate the function. The functions in XSLT 2.0 and XPath 2.0 are actually in a namespace that's used implicitly by an XSLT 2.0 processor, but the namespace can be made explicit in an XSLT 2.0 stylesheet. So, if you change your stylesheet to explicitly use that namespace on the reference to the tokenize function, it will appear to Xalan-J as an extension function. The following stylesheet should work with Xalan-Java: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:str="http://exslt.org/strings"> <xsl:template match="/"> <root> <xsl:choose> <xsl:when test="function-available('str:tokenize')"> <!-- called when run by xalan --> <xsl:value-of select="str:tokenize('date math str')"/> </xsl:when> <!-- called when run by saxon --> <xsl:otherwise> <xsl:value-of select="fn:tokenize('date math str')"/> </xsl:otherwise> </xsl:choose> </root> </xsl:template> </xsl:stylesheet> I hope that helps. Thanks, Henry [1] http://www.w3.org/TR/xslt#forwards ------------------------------------------------------------------ Henry Zongaro XML Transformation & Query Development IBM Canada Lab T/L 313-6044; Phone +1 905 413-6044 mailto:zong...@ca.ibm.com