0

I try to get element from an XML using XPath in Java.

Without a schema definition / declaration everything works fine as expected:

Example from https://www.w3schools.com/xml/schema_howto.asp

<?xml version="1.0"?>
<note>
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

XPath : /note/heading returns an element

After declaring an xml Schema:

<?xml version="1.0"?>

<note
xmlns="https://www.w3schools.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.w3schools.com/xml note.xsd">
  <to>Tove</to>
  <from>Jani</from>
  <heading>Reminder</heading>
  <body>Don't forget me this weekend!</body>
</note>

XPath /note/heading is not working any more !!

Java example from XPathTutorial

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true); // never forget this!
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("inventory.xml");

//Create XPath

XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath();

System.out.println("n//1) Get book titles written after 2001");

    XPathExpression expr = xpath.compile("/note/heading/text()");
    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());
    }
kjhughes
  • 106,133
  • 27
  • 181
  • 240
Thorsten Niehues
  • 13,712
  • 22
  • 78
  • 113
  • So many people fall into this trap! I've chosen one of many hundreds of examples as a duplicate; you can find others by searching for "XPath default namespace". – Michael Kay Sep 21 '21 at 14:40

1 Answers1

0

In XPath 1 a step like note selects elements named note in no namespace, you have put the elements into a namespace so your path with "unqualified" names (i.e. without a prefix) doesn't select any input elements. Your Java code needs to bind a prefix (e.g. w3s to the namespace URI (i.e. https://www.w3schools.com) and then use that prefix with e.g. w3s:note.

Or use an XPath 2 or 3 or XQuery implementation where you can declare a default element namespace for path expressions so that your step note would select the elements in that default element namespace you set up as e.g. https://www.w3schools.com.

If you want to ignore the namespace for XPath evaluation, due to the prefix hassle for XPath 1, you might get away with explicitly not using a namespace aware document builder but rather one that is not namespace aware.

With XPath 2 or later or XQuery 1 or later you can also use namespace wildcards like *:note.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110