GarlicBread
GarlicBread

Reputation: 2009

XPath expression unable to match

I'm trying to parse out some information from XML using XPath in Java (v 1.7). My XML looks like this:

<soap:Fault xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <faultcode>code</faultcode>
    <faultstring>string</faultstring>
    <detail>detail</detail>
</soap:Fault>

My code:

final InputSource inputSource = new InputSource(new StringReader(xmlContent));
final DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
final Document document = documentBuilder.parse(inputSource);

final XPath xPath = XPathFactory.newInstance().newXPath();
final String faultCode = xPath.compile("/soap:Fault/faultcode/text()[1]").evaluate(document);

I have tried the XPath expression in an online checker with the XML content and it suggests that a match is made. However, when I run it in a wee stand-alone program, I get no value in "faultCode".

This issue is probably something simple, but I am unable to identify what the problem is.

Thanks for any assistance.

Upvotes: 2

Views: 737

Answers (3)

Markus
Markus

Reputation: 3397

First you need a namespace aware document builder factory:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);

Then you need a namespace context:

NamespaceContext nsContext = new NamespaceContext() {
    @Override
    public Iterator getPrefixes(String namespaceURI) {
        return null;
    }
    @Override
    public String getPrefix(String namespaceURI) {
        return "soap";
    }
    @Override
    public String getNamespaceURI(String prefix) {
        return "http://schemas.xmlsoap.org/soap/envelope/";
    }
};
xPath.setNamespaceContext(nsContext);

With these additions, your code should work.

Regarding namespace contexts, I suggest you read http://www.ibm.com/developerworks/xml/library/x-nmspccontext/index.html.

Upvotes: 1

It may be because of the namespaces effect. You can try namespace independent tags by matching with the local-name giving the syntax below:

   /*[local-name()='Fault' and namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/']/*[local-name()='faultcode']/text()[1]

Upvotes: 0

Michael Kay
Michael Kay

Reputation: 163587

You should bind the namespace prefix "soap" to the URI "http://schemas.xmlsoap.org/soap/envelope/" using the XPath.setNamespaceContext() method.

Upvotes: 2

Related Questions