如何在Tomcat服务器上运行XSLT2转换?

问题描述

我正在尝试从Tomcat v8.0服务器上的XML文件运行XSLT 2.0转换。 但是,我只能成功将其作为XSLT1运行。

每当我尝试使用XSLT2函数时,都会收到这样的错误

org.apache.xml.utils.WrappedRuntimeException:java.lang.NoSuchMethodException:对于扩展功能,找不到方法org.apache.xml.utils.NodeVector.root([ExpressionContext,])。

我正在使用Saxon,这是pom声明:

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

在构建项目时确实已加载库Saxon-HE-10.0.jar。

我的java方法去了(为此尝试,inputFile发送任何格式正确的xml文件):

    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;  
    }

这是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>

这是令人失望的输出

<?xml version="1.0" encoding="UTF-8"?>
xsl:version: 1

解决方法

调用net.sf.saxon.TransformerFactoryImpl.newInstance()时,这是一个静态方法,实际上根本没有调用Saxon方法。您正在调用在javax.xml.transform.TransformerFactory()上定义的方法。我不确定为什么这会为您提供XSLT 1.0转换器工厂(这取决于许多因素,例如类路径上JAR文件的精确顺序),但这当然不是确保您的身份的可靠方法。正在加载撒克逊人。

它也很慢:它涉及搜索类路径。

如果您想加载Saxon,请按照MarcStröbel的建议使用new net.sf.saxon.TransformerFactoryImpl()显式加载。或更妙的是,放弃JAXP并使用Saxon s9api接口,可以更好地访问2.0和3.0功能。