d-man
d-man

Reputation: 58103

Java XPath expression for pom

java - xpath - pom.xml

I am using following pom.xml file as xml dom resource, i want to get value of tag <version> without iterating in my code that's why i am using xpath but i guess my xpath express is not correct that's why it is not returning any value. any help appreciated.

java code

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

    DocumentBuilder builder = domFactory.newDocumentBuilder();
    Document doc = builder.parse("C:\\projects\\pom.xml");
    XPath xpath = XPathFactory.newInstance().newXPath();

    XPathExpression expr = xpath.compile("project/version");
    Object result = expr.evaluate(doc, XPathConstants.NODESET);
    NodeList nodes = (NodeList) result;
    for (int i = 0; i < nodes.getLength(); i++) {
        System.out.println(nodes.item(i).getNodeValue());
    }

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.dc.app</groupId>
  <artifactId>rum</artifactId>
  <packaging>war</packaging>
  <version>12.54-SNAPSHOT</version>
  <name>rum</name>
  <description>rum</description>
</project>

Upvotes: 2

Views: 3195

Answers (1)

flup
flup

Reputation: 27103

Make a javax.xml.NamespaceContext and feed it to your xpath:

xpath.setNamespaceContext(ctx);

So:

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

DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("blah.pom");
XPath xpath = XPathFactory.newInstance().newXPath();
Map<String, String> namespaces = new HashMap<String, String>();
namespaces.put("pom", "http://maven.apache.org/POM/4.0.0");

xpath.setNamespaceContext(
        new NamespaceContextImpl("http://maven.apache.org/POM/4.0.0", 
                namespaces));

XPathExpression expr = xpath.compile("/pom:project/pom:version");
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i = 0; i < nodes.getLength(); i++) {
    System.out.println(nodes.item(i).getTextContent());
}

yields:

12.54-SNAPSHOT

EDIT: an implementation of the NamespaceContext:

public class NamespaceContextImpl implements NamespaceContext {
   private final Map<String, String> namespaces;
   private final String defaultNamespaceURI;

   public NamespaceContextImpl(String defaultNamespaceURI,
                               Map<String, String> namespaces) {
      this.defaultNamespaceURI = defaultNamespaceURI;
      this.namespaces = namespaces;
   }

   public Iterator getPrefixes(String namespaceURI) {
      throw new IllegalStateException("Not Implemented.");
   }

   public String getPrefix(String namespaceURI) {
      throw new IllegalStateException("Not Implemented.");
   }

   public String getNamespaceURI(String prefix) {
      if (prefix == null) {
         throw new IllegalArgumentException();
      }
      if (prefix.equals(XMLConstants.XMLNS_ATTRIBUTE)) {
         return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
      }
      if (prefix.equals(XMLConstants.XML_NS_PREFIX)) {
         return XMLConstants.XML_NS_URI;
      }
      if (prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
         return defaultNamespaceURI;
      }
      String result = namespaces.get(prefix);
      if (result == null) {
         result = XMLConstants.NULL_NS_URI;
      }
      return result;
   }
}

Upvotes: 5

Related Questions