Search code examples
javaxmldom4j

XPath evaluation in dom4j Document created from org.w3c.dom.Document doesn't work as expected


I'm trying to use dom4j 1.6.1 to traverse the following document using XPath. I'm looking for the number of <query> elements.

<?xml version="1.0" encoding="UTF-8"?>
<reportLineageResponse>
   <querySet expressionLocale="en-us">
      <queries xmlns="http://developer.cognos.com/schemas/report/9.0/">
         <query name="Top 10 Sales Staff List"/>
         <query name="Top 10 Sales Staff by Quantity List"/>
         <query name="Sales Figures America Region Combination Chart"/>
      </queries>
   </querySet>
</reportLineageResponse>

Here is the code invoking dom4j.

int numberOfQueries(org.w3c.dom.Document jaxpDocument) {
    DOMReader domReader = new DOMReader();
    org.dom4j.Document document = domReader.read(jaxpDocument);

    Map<String, String> nsMap = Collections.singletonMap("rep", "http://developer.cognos.com/schemas/report/9.0/");
    XPath queryXp = document.createXPath("/reportLineageResponse/querySet/rep:queries/rep:query")
    queryXp.setNamespaceURIs(nsMap);
    List<Node> queries = queryXp.selectNodes(document);
    return queries.size();
}

I specified the namespace correctly, yet I get 0 results. What could be the problem?


Edit: if I look at the dom4j.Document after creating it, it has the namespaces wrong:

<?xml version="1.0" encoding="UTF-8"?>
<reportLineageResponse>
   <querySet expressionLocale="en-us">
      <queries xmlns="http://developer.cognos.com/schemas/report/9.0/">
         <query xmlns="" name="Top 10 Sales Staff List"/>
         <query xmlns="" name="Top 10 Sales Staff by Quantity List"/>
         <query xmlns="" name="Sales Figures America Region Combination Chart"/>
      </queries>
   </querySet>
</reportLineageResponse>

Edit: here is the code that creates the org.w3c.dom.Document:

Document loadDocument(URL url) {
    InputStream stream = url.openStream();
    DocumentBuilder docBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
    Document result = docBuilder.parse(stream);
    stream.close();
    return result;
}

Solution

  • Change your xml loading as follows:

    DocumentBuilderFactory docBuilderFactor = DocumentBuilderFactory.newInstance();
    docBuilderFactor.setNamespaceAware(true);
    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();