如何使用 Java 使用 XSL 转换 XML

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4095287/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 11:34:21  来源:igfitidea点击:

How to transform XML with XSL using Java

javaxmltransformxslt

提问by Andez

I am currently using the standard javax.xml.transform library to transform my XML to CSV using XSL. My XSL file is large - at around 950 lines. My XML files can be quite large also.

我目前正在使用标准的 javax.xml.transform 库使用 XSL 将我的 XML 转换为 CSV。我的 XSL 文件很大 - 大约 950 行。我的 XML 文件也可能很大。

It was working fine in the prototype stage with a fraction of the XSL in place at around 50 lines or so. Now in the 'final system' when it performs the transform it comes up with the error Branch target offset too large for short.

它在原型阶段运行良好,只有大约 50 行左右的 XSL 的一小部分。现在,在“最终系统”中,当它执行转换时,会出现错误Branch target offset too large for short

private String transformXML() {
    String formattedOutput = "";
    try {

        TransformerFactory tFactory = TransformerFactory.newInstance();            
        Transformer transformer =
                tFactory.newTransformer( new StreamSource( xslFilename ) );

        StreamSource xmlSource = new StreamSource(new ByteArrayInputStream( xmlString.getBytes() ) );
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        transformer.transform( xmlSource, new StreamResult( baos ) );

        formattedOutput = baos.toString();

    } catch( Exception e ) {
        e.printStackTrace();
    }

    return formattedOutput;
}

I came across a few postings on this error but not too sure what to do.
Am I doing anything wrong code wise? Are there any alternative 3rd Party transformers available that could do this?

我遇到了一些关于此错误的帖子,但不太确定该怎么做。
我在代码方面做错了什么吗?是否有任何替代的 3rd Party 变压器可以做到这一点?

Thanks,

谢谢,

Andez

安德斯

采纳答案by Andez

I came across a post on the net that mentioned apache XALAN. So I added the jars to my project. Everything has started working since even though I do not directly reference any XALAN classes in my code. As far as I can tell it still should use the jaxax.xml classes.

我在网上看到一篇提到 apache XALAN 的帖子。所以我将罐子添加到我的项目中。尽管我没有在我的代码中直接引用任何 XALAN 类,但一切都开始工作了。据我所知,它仍然应该使用 jaxax.xml 类。

Not too sure what is happening there. But it is working.

不太确定那里发生了什么。但它正在起作用。

回答by dogbane

Try Saxoninstead.

试试撒克逊人吧

Your code would stay the same. All you would need to do is set javax.xml.transform.TransformerFactoryto net.sf.saxon.TransformerFactoryImplin the JVM's system properties.

您的代码将保持不变。您需要做的就是在 JVM 的系统属性中设置javax.xml.transform.TransformerFactorynet.sf.saxon.TransformerFactoryImpl

回答by khachik

Use saxon. offtop: if you use the same stylesheet to transform many XML files, you might want to consider templates (pre-compiled stylesheets):

使用撒克逊。offtop:如果您使用相同的样式表来转换许多 XML 文件,您可能需要考虑模板(预编译的样式表):

javax.xml.transform.Templates style = tFactory.newTemplates(xslSource);
style.newTransformer().transform(...);

回答by Ga???

As an alternative to Saxon, you can split up your large template into smaller templates.

作为 Saxon 的替代方案,您可以将大型模板拆分为较小的模板。

Template definitions contained in XSLT stylesheets are compiled by SAP JVM's XSLT compiler "Xalan" into Java methods for faster execution of transformations. Java bytecode branch instructions contained in these Java methods are limited to 32K offsets. Large template definitions can now lead to very large Java methods, where the branch offset would need to be larger than 32K. Therefore these stylesheets cannot be compiled to Java methods and therefore cannot be used for transformations.

XSLT 样式表中包含的模板定义由 SAP JVM 的 XSLT 编译器“Xalan”编译成 Java 方法,以便更快地执行转换。这些 Java 方法中包含的 Java 字节码分支指令仅限于 32K 偏移量。大型模板定义现在可以导致非常大的 Java 方法,其中分支偏移量需要大于 32K。因此,这些样式表不能编译为 Java 方法,因此不能用于转换。

Solution

解决方案

Since each template definition of an XSLT stylesheet is compiled into a separate Java method, using multiple smaller templates can be used as solution. A very large template can be broken into multiple smaller templates by using the "call-template" element.

由于 XSLT 样式表的每个模板定义都被编译成一个单独的 Java 方法,因此可以使用多个较小的模板作为解决方案。通过使用“ call-template”元素,可以将一个非常大的模板分解为多个较小的模板。

It is described in-depth in this article Size limitation for XSLT stylesheets.

这篇文章对 XSLT 样式表的大小限制进行了深入描述。

Sidenote: I would only recommend this as a last resortif saxon is not available, as this requires quite a few changes to your xsl file.

旁注:如果 saxon 不可用,我只会建议将此作为最后的手段,因为这需要对您的 xsl 文件进行大量更改。