OO-Mango
OO-Mango

Reputation: 35

Why won't my xpath work?

I have the following xml:

<?xml version="1.0" encoding="UTF-8"?>
<prefix:someName xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:prefix="someUri" xsi:schemaLocation="someLocation.xsd">
        <prefix:someName2>
            ....
        </prefix:someName2>
    </prefix:someName>

And my code looks like this:

private Node doXpathThingy(Document doc) {
     final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
     dbf.setNamespaceAware(true);

     XPath xPath = XPathFactory.newInstance().newXPath();

     xPath.setNamespaceContext(new NamespaceContext(){
        @Override
        public String getNamespaceURI(String prefix) {
            if (prefix == null) {
                throw new NullPointerException("Null prefix");
            }

            return doc.lookupNamespaceURI(prefix);
        }

        @Override
        public String getPrefix(String namespaceURI) {
            return null;
        }

        @Override
        public Iterator getPrefixes(String namespaceURI) {
            return null;
        }
     });

    try {
        XPathExpression expr = xPath.compile(xpathString);
        return (Node)expr.evaluate(doc, XPathConstants.NODESET);
    } catch (Exception e) {
        ....        }
}

I'm trying to get this to work with any valid xpath. It works with these xpaths:

"prefix:someName"

"."

But NOT with: "prefix:someName2". It returns null.

I guess I'm still not getting something about namespaces, but I don't understand what? I've tried leaving out the prefixes from my xpath but then nothing works at all. I've also checked if the correct uri is returned for the prefix at doc.lookupNamespaceURI(prefix), and it is.

Any help would be greatly appreciated.

Upvotes: 1

Views: 339

Answers (2)

Michael Kay
Michael Kay

Reputation: 163585

The query prefix:XXX means child::prefix:XXX, that is, find an element child of the context node whose name is prefix:XXX. Your context node is the document node at the root of the tree. The document node has a child named prefix:someName, but it doesn't have a child named prefix:someName2. If you want to find a grandchild of the document node, try the query */prefix:someName2.

Upvotes: 2

Darrel Miller
Darrel Miller

Reputation: 142222

Can't say I'm familiar with the Java way of doing XPath, but it looks like you are making an XPath query from the root of the document, so what you are seeing is the expected behavior.

Try this to find someName2 anywhere in the doc

//prefix:someName2

or this to find it as the child of someName2

/prefix:someName/prefix:someName2

or this to find it as the direct child of any root element

/*/prefix:someName2

Upvotes: 2

Related Questions