xalan and saxon at same time on apache camel

998 views Asked by At

I found this Using Xalan alongside Saxon but I don't get it to work.

I insert the dependecy for camel-saxon in my pom.xml

<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-saxon</artifactId>
    <version>2.14.0</version>
</dependency>

and get this Error:

java.util.ArrayList cannot be cast to org.w3c.dom.NodeList

in this Code:

public NodeList getXPathFromFile(String xpathStr, String xmlfile) {
        NodeList nodes = null;
        try {
            System.setProperty(XPathFactory.DEFAULT_PROPERTY_NAME + ":"
                    + XPathFactory.DEFAULT_OBJECT_MODEL_URI,
                    "org.apache.xpath.jaxp.XPathFactoryImpl");

                XPathFactory jaxpFactory = XPathFactory.newInstance(XPathFactory.DEFAULT_OBJECT_MODEL_URI);

            XPath xpath = jaxpFactory.newXPath(); /*XPathFactory.newInstance()*/
            String expression = xpathStr;
            InputSource inputSource = new InputSource(xmlfile);
            nodes = (NodeList) xpath.compile(expression).evaluate(inputSource, XPathConstants.NODESET); <-- here come's the error
        } catch (XPathExpressionException | XPathFactoryConfigurationException e) { 
            e.printStackTrace();
        }
        return nodes;
    }

If I remove the dependency my code work well. But I need xslt 2.0 for my Camel Routes and don't want to change my code. What do I wrong?

Do I need to IMPORT something?

1

There are 1 answers

2
Michael Kay On BEST ANSWER

It looks to me as if you are picking up Saxon as the XPath factory. (Saxon by default builds its own native tree for the XPath InputSource, not a DOM, and therefore returns nodes in a Java list rather than a DOM NodeList).

Are you really sure you want to parse the XML file every time you execute an XPath expression? Because that is what your code is doing.

I'm not sure why this code is picking up Saxon, given your System.setProperty() settings. Saxon has changed in version 9.6 so it no longer registers itself as a JAXP XPath factory, which eliminates this problem (we decided that people really want to know whether they are getting an XPath 1.0 or 2.0 processor, and the XPath factory mechanism gives you whichever is lying around on the classpath).

Possible solutions are:

(a) instantiate the Apache XPath factory directly rather than relying on the JAXP classpath search (which is very expensive, especially if you do it just to evaluate a single XPath expression)

(b) upgrade Saxon to 9.6

(c) Change this code so it works with Saxon. The easiest change, if you don't care about performance, would be to ensure that the source document is passed as a DOMSource. Although Saxon is much slower when using the DOM, that inefficiency is dwarfed by the cost of creating an XPath factory and parsing the source document each time you execute an XPath. If you want to make the whole thing more efficient, that means looking at code outside the fragment you have shown us.