Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XPath with namespace in Java

Tags:

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?

like image 323
Sergiu Avatar asked Dec 04 '12 12:12

Sergiu


People also ask

What is namespace in XPath?

XPath queries are aware of namespaces in an XML document and can use namespace prefixes to qualify element and attribute names. Qualifying element and attribute names with a namespace prefix limits the nodes returned by an XPath query to only those nodes that belong to a specific namespace.


1 Answers

  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() + ")"); } 
like image 199
Alex Avatar answered Sep 25 '22 13:09

Alex