Thursday, April 2, 2015

Avoiding XPathParser.initXPath(...) infinite loop in Apache Xalan XSLT

An explicit mention of the problem and solution mention in this link: http://marc.info/?l=xalan-j-users&m=104758138708998.

During XSLT transformation using org.apache.xalan.processor.TransformerFactoryImpl, org.apache.xpath.compiler.XPathParser.initXPath() goes into infinite loop if the XLS file is invalid.

The solution is to set an error listener on the TransformerFactory and rethrow the exception from the listener.

Sample Code:
    String xslFilePath = "/path/to/xsl/file";
    String inputXmlPath = "/path/to/input/xml";
    String outputXmlPath = "/path/to/input/xml";
    TransformerFactory factory = new org.apache.xalan.processor.TransformerFactoryImpl()
    factory.setErrorListener(new ErrorListener() {
        public void warning(TransformerException exception) throws TransformerException {
            throw exception;
        }
        public void fatalError(TransformerException exception) throws TransformerException {
            throw exception;
        }
        public void error(TransformerException exception) throws TransformerException {
            throw exception;
        }
    });

    /*
     * TransformerFactory factory = TransformerFactory.newInstance();
     * uses org.apache.xalan.xsltc.trax.TransformerFactoryImpl which doensn't
     * have the infinite loop problem.
     */

    StreamSource xslStream = new StreamSource(xslFilePath);
    Transformer transformer = factory.newTransformer(xslStream);
    StreamSource in = new StreamSource(inputXmlPath);
    StreamResult out = new StreamResult(outputXmlPath);
    HashMap context = new HashMap();
    // set context values into map
    transformer.setParameter("context", context);
    transformer.transform(in, out);