Unable to evaluate expression in XPath

Muhammed Refaat picture Muhammed Refaat · May 20, 2013 · Viewed 16.6k times · Source

I;m using XPath to parse XML document returned by a URL, when i run my code with given inputs it works but when giving it inputs as a user input it throws an exception. The Code:

    class{
        private String generalQuery =  "//@*";
    method(){
        System.out.println("Enter URL");
        url = scan.nextLine();
        URL oracle = new URL(url);
        InputStream is = oracle.openStream();

        org.w3c.dom.Document doc = null;
        DocumentBuilderFactory domFactory;
        DocumentBuilder builder;

        try {
            domFactory = DocumentBuilderFactory.newInstance();
            domFactory.setNamespaceAware(true);
            builder = domFactory.newDocumentBuilder();
            doc = builder.parse(is);
        } catch (Exception ex) {
            System.err.println("unable to load XML: " + ex);
        }

    Map <String, String> params = new HashMap<String, String> ();

            XPathFactory factory = XPathFactory.newInstance();
            XPath xpath = factory.newXPath();
            xpath.setNamespaceContext(new NameSpaces(doc));
            XPathExpression expr = xpath.compile(generalQuery);
            Object result = expr.evaluate(doc, XPathConstants.NODESET); // exception thrown here

            NodeList nl = (NodeList) result;

            for (int i = 0 ; i < nl.getLength() ; i++){
                Node n = (Node)nl.item(i);
                params.put(n.getNodeName(), n.getNodeValue());
            }

            return params;
}
}

The Exception:

javax.xml.transform.TransformerException: Unable to evaluate expression using this context

The class NameSpaces :

import java.util.Iterator;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
import org.w3c.dom.Document;

public class NameSpaces implements NamespaceContext {
    private Document sourceDocument;

    public NameSpaces(Document document) {
        sourceDocument = document;
    }

    @Override
    public String getNamespaceURI(String prefix) {
        if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
            return sourceDocument.lookupNamespaceURI(null);
        } else {
            return sourceDocument.lookupNamespaceURI(prefix);
        }
    }

    @Override
    public String getPrefix(String namespaceURI) {
        return sourceDocument.lookupPrefix(namespaceURI);
    }

    @Override
    public Iterator<String> getPrefixes(String namespaceURI) {
        return null;
    }
}

Answer

yankee picture yankee · Feb 13, 2014

The exception "Unable to evaluate expression using this context" may also result from a null document when trying to evaluate an XPath expression. (I had the same error and it took me a while to figure out I did not initialize my document properly).

In your code you have

try {
  // load document
}
catch (Exception ex) {
  System.err.println("unable to load XML: " + ex);
}

// happily continue

This is a call for trouble. If an exception happens during initialization you should STOP right there and you should not continue. If you have absolutely no idea how to handle the error, use catch(Exception e) { throw new Error(e); }. This will cause exceptions to bubble up and hopefully be handled by the default exception handler which prints a stack trace and exits.

As the reader of your question I don't even know where the exception was thrown. You should provide this information. Note that you can also use someException.printStackTrace(); to get the stack trace which points you to the correct line.