简体   繁体   中英

How to transform XML with XSL using Java

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.

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 .

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?

Thanks,

Andez

Try Saxon instead.

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

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

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

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.

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

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

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.

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.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM