0

I am trying to run a XSLT 2.0 transformation from a XML file on a Tomcat v8.0 Server. However, I only succeed in running it as XSLT1.

Anytime I try to use a XSLT2 function, I get such an error:

org.apache.xml.utils.WrappedRuntimeException: java.lang.NoSuchMethodException: For extension function, could not find method org.apache.xml.utils.NodeVector.root([ExpressionContext,] ).

I am using Saxon, here is the pom declaration:

        <dependency>
            <groupId>net.sf.saxon</groupId>
            <artifactId>Saxon-HE</artifactId>
            <version>10.0</version>
        </dependency>

The library Saxon-HE-10.0.jar is indeed loaded when I build the project.

My java method goes (for the sake of this try, inputFile sends any well-formed xml file):

    public File transfoTest(InputStream inputFile) throws Exception  {
        logger.debug("Begin transformation test");
        File output =  File.createTempFile("output", ".xml");
        output.deleteOnExit();
        InputStream xslFile = getClass().getResourceAsStream("/xslTransformerFiles/transfoXSLT.xsl");
        OutputStream osOutputFile = FileUtils.openOutputStream(output);
        PrintStream printStream = new PrintStream(osOutputFile);
        StreamSource xsrc = new StreamSource(xslFile);
        TransformerFactory transformerFactory = net.sf.saxon.TransformerFactoryImpl.newInstance();      
        Transformer xsltTransformer = transformerFactory.newTransformer(xsrc);
        xsltTransformer.transform(new StreamSource(inputFile), new StreamResult(printStream));
        inputFile.close();
        xslFile.close();
        osOutputFile.close();
        printStream.close();
        logger.debug("End transformation test");
        return output;  
    }

Here is transfoXSLT.xsl:

<?xml version="1.1" encoding="UTF-8" ?>
<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />
    <xsl:template match="/">
        <xsl:value-of select="'xsl:version: '" />
        <xsl:value-of select="system-property('xsl:version')" />
    </xsl:template>
</xsl:stylesheet>

And here is the disappointing output:

<?xml version="1.0" encoding="UTF-8"?>
xsl:version: 1
Evargalo
  • 126
  • 6
  • 1
    please try using `TransformerFactory transformerFactory = new net.sf.saxon.TransformerFactoryImpl();` instead of `TransformerFactory transformerFactory = net.sf.saxon.TransformerFactoryImpl.newInstance();` https://stackoverflow.com/questions/11314604/how-to-set-saxon-as-the-xslt-processor-in-java – Marc Stroebel Aug 26 '20 at 09:52

1 Answers1

1

When you call net.sf.saxon.TransformerFactoryImpl.newInstance(), this is a static method, and you're not actually calling a Saxon method at all; you're calling a method defined on javax.xml.transform.TransformerFactory(). I'm not sure exactly why this is giving you an XSLT 1.0 transformer factory (it depends on many factors, such as the precise order of JAR files on your classpath), but it certainly isn't a reliable way of ensuring that you are loading Saxon.

It's also slow: it involves searching the classpath.

If you know you want to load Saxon, load it explicitly using new net.sf.saxon.TransformerFactoryImpl() as suggested by Marc Ströbel. Or better still, abandon JAXP and use the Saxon s9api interfaces, which give much better access to 2.0 and 3.0 capabilities.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164