32

I would like to get all the content in between the tags but I do not know how to do this because of the urn: namespace.

<urn:ResponseStatus version="1.0" xmlns:urn="urn:camera-org">

<urn:requestURL>/CAMERA/Streaming/status</urn:requestURL>
<urn:statusCode>4</urn:statusCode>
<urn:statusString>Invalid Operation</urn:statusString>
<urn:id>0</urn:id>

</urn:ResponseStatus>

Any ideas?

2
  • 1
    What library are you using? Have you tried to prefix your query with urn: ? Commented Dec 4, 2012 at 12:17
  • Using javax.xml.xpath.XPath; I've tried with urn: but that didn't help. Commented Dec 4, 2012 at 12:19

2 Answers 2

74
  1. Short answer: use XPath local-name(). Like this: xPathFactory.newXPath().compile("//*[local-name()='requestURL']/text()"); will return /CAMERA/Streaming/status
  2. Or you can implement a NamespaceContext that maps namespaces names and URIs and set it on the XPath object before querying.
  3. Take a look at this blog article, Update: the article is down, you can see it on webarchive

Solution 1 sample:

XPath xpath = XPathFactory.newInstance().newXPath();
String responseStatus = xpath.evaluate("//*[local-name()='ResponseStatus']/text()", document);
System.out.println("-> " + responseStatus);

Solution 2 sample:

// load the Document
Document document = ...;
NamespaceContext ctx = new NamespaceContext() {
    public String getNamespaceURI(String prefix) {
        return prefix.equals("urn") ? "urn:camera-org" : null; 
    }
    public Iterator getPrefixes(String val) {
        return null;
    }
    public String getPrefix(String uri) {
        return null;
    }
};
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(ctx);
String responseStatus = xpath.evaluate("//urn:ResponseStatus/text()", document);
System.out.println("-> " + responseStatus);

Edit

This is a complete example, it correctly retrieve the element:

String xml = "<urn:ResponseStatus version=\"1.0\" xmlns:urn=\"urn:camera-org\">\r\n" + //
        "\r\n" + //
        "<urn:requestURL>/CAMERA/Streaming/status</urn:requestURL>\r\n" + //
        "<urn:statusCode>4</urn:statusCode>\r\n" + //
        "<urn:statusString>Invalid Operation</urn:statusString>\r\n" + //
        "<urn:id>0</urn:id>\r\n" + //
        "\r\n" + //
        "</urn:ResponseStatus>";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new java.io.ByteArrayInputStream(xml.getBytes()));
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new NamespaceContext() {
    public String getNamespaceURI(String prefix) {
        return prefix.equals("urn") ? "urn:camera-org" : null;
    }

    public Iterator<?> getPrefixes(String val) {
        return null;
    }

    public String getPrefix(String uri) {
        return null;
    }
});
XPathExpression expr = xpath.compile("//urn:ResponseStatus");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
    Node currentItem = nodes.item(i);
    System.out.println("found node -> " + currentItem.getLocalName() + " (namespace: " + currentItem.getNamespaceURI() + ")");
}
Sign up to request clarification or add additional context in comments.

6 Comments

Good answer! (That blog post would have been more useful if the code were indented and the example XML weren't been eaten by his own server. Oh well, still a helpful list at the end.)
Thanks a ton !! I parsed a huge complex xml file using this logic and It worked for me.
getNamespaceURI should be returning XMLConstants.NULL_NS_URI (which is an empty string) rather than null when it doesn't match any registered prefixes.
The blog.davber.com website is only returning an Internal Server Error now.
All: I updated the answer with a link to the original blog post in point 3 via webarchive
|
1

XML xpath with Namespace

Simple XML

String namespaceXML = "<?xml version='1.0' ?><information><person id='1'><name>Deep</name><age>34</age><gender>Male</gender></person>  <person id='2'><name>Kumar</name><age>24</age><gender>Male</gender></person> <person id='3'><name>Deepali</name><age>19</age><gender>Female</gender></person><!-- more persons... --></information>";
String jsonString = "{}";
String expression = "//information";

Name space XML

String namespaceXML = "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><m:NumberToDollarsResponse xmlns:m=\"http://www.dataaccess.com/webservicesserver/\"><m:NumberToDollarsResult>nine hundred and ninety nine dollars</m:NumberToDollarsResult></m:NumberToDollarsResponse></soap:Body></soap:Envelope>";
String jsonString = "{'soap':'http://schemas.xmlsoap.org/soap/envelope/', 'm':'http://www.dataaccess.com/webservicesserver/'}";
String expression = "//m:NumberToDollarsResponse/m:NumberToDollarsResult/text()";

Supply namespace xml file as a string, to asscerionXpath(namespaceXML, jsonString, expression) method and get result in the form of text/node.

text() : nine hundred and ninety nine dollars

node : <m:NumberToDollarsResult xmlns:m="http://www.dataaccess.com/webservicesserver/"> nine hundred and ninety nine dollars </m:NumberToDollarsResult>

public static String asscerionXpath(String namespaceXML, String jsonString, String expression){
    if(namespaceXML.indexOf("><") > -1) namespaceXML = namespaceXML.replace("><", ">\r\n<");
    if(jsonString.indexOf("'") > -1)    jsonString = jsonString.replace("'", "\"");

    System.out.println("namespaceXML : \n"+namespaceXML);
    System.out.println("nsmespaces : \n"+jsonString);

    DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
    factory.setValidating(false);
    factory.setNamespaceAware(true);
    factory.setIgnoringComments(true);
    factory.setIgnoringElementContentWhitespace(true);
    try {
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document source = builder.parse( string2Source(namespaceXML) );
        XPath xpath = XPathFactory.newInstance().newXPath();

        addNameSpaces(jsonString, xpath);
        // An XPath expression is not thread-safe. Make sure it is accessible by only one Thread.
        XPathExpression expr = xpath.compile(expression);

        // The NodeList interface provides the abstraction of an ordered collection of nodes,
        NodeList nodes = (org.w3c.dom.NodeList) expr.evaluate(source, XPathConstants.NODESET);;
        Node tree_base = nodes.item(0);
        return document2String(tree_base);
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (SAXException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ParserConfigurationException e) {
        e.printStackTrace();
    } catch (XPathExpressionException e) {
        System.out.println("If the expression cannot be evaluated.");
    }
    return "";
}
static InputSource string2Source( String str ) {
    InputSource inputSource = new InputSource( new StringReader( str ) );
    return inputSource;
}
static void addNameSpaces(String jsonString, XPath xpath) {
    JSONParser parser = new JSONParser();
    try {
        JSONObject namespaces = (JSONObject) parser.parse(jsonString);

        if (namespaces.size() > 0) {
            final JSONObject declaredPrefix = namespaces; // To access in Inner-class.
            NamespaceContext nameSpace = new NamespaceContext() {
                // To get all prefixes bound to a Namespace URI in the current scope, XPath 1.0 specification
                // --> "no prefix means no namespace"
                public String getNamespaceURI(String prefix) {
                    Iterator<?> key = declaredPrefix.keySet().iterator();
                    System.out.println("Keys : "+key.toString());
                    while (key.hasNext()) {
                        String name = key.next().toString();
                        if (prefix.equals(name)) {
                            System.out.println(declaredPrefix.get(name));
                            return declaredPrefix.get(name).toString();
                        }
                    }
                    return "";
                }
                public Iterator<?> getPrefixes(String val) {
                    return null;
                }
                public String getPrefix(String uri) {
                    return null;
                }
            };// Inner class.

            xpath.setNamespaceContext( nameSpace );
        }

    } catch ( org.json.simple.parser.ParseException e) {
        e.printStackTrace();
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.