How can I get JDOM/XPath to ignore namespaces?
Asked Answered
R

4

6

I need to process an XML DOM, preferably with JDOM, where I can do XPath search on nodes. I know the node names or paths, but I want to ignore namespaces completely because sometimes the document comes with namespaces, sometimes without, and I can't rely on specific values. Is that possible? How?

Reprehensible answered 9/4, 2010 at 12:40 Comment(1)
Rather than ignoring them you can also retrieve and then use them. See How to retrieve namespaces in XML files using XpathShend
R
4

I know this question is a little old, but for those viewing this later, you can override a few JDOM default classes to effectively make it ignore namespaces as well. You can pass your own JDOMFactory implementation to the SAXBuilder that ignores all Namespace values passed into it.

Then override the SAXBuilder class and implement the createContentHandler method so that it returns a SAXHandler with a blank definition for the startPrefixMapping method.

I haven't used this in a production setting so caveat emptor, but I have verified that it does work on some quick and dirty XML stuff I've done.

Ruysdael answered 18/5, 2010 at 19:42 Comment(0)
D
18
/ns:foo/ns:bar/@baz

becomes

/*[local-name() = 'foo']/*[local-name() = 'bar']/@baz

You get the point. Don't expect that to be lightning-fast either.

Drinkwater answered 9/4, 2010 at 12:52 Comment(3)
I tried the solution from here: #543549 It is much simpler and works as long as the root element has any namespace declared. But if there is no namespace, it doesn't - so either I use the above, or I have a separate solution for no namespaces.Reprehensible
@AdSR: Your question seemed to imply that you have no knowledge of the namespace state of your input documents & they come at random. In this case, the above is the "safest", as in: it will always work, but you lose the ability to make a difference between x:foo and ns:foo.Drinkwater
Thanks, this solution worked for me in jdom 1.x (/*:foo didn't work).Boffin
R
4

I know this question is a little old, but for those viewing this later, you can override a few JDOM default classes to effectively make it ignore namespaces as well. You can pass your own JDOMFactory implementation to the SAXBuilder that ignores all Namespace values passed into it.

Then override the SAXBuilder class and implement the createContentHandler method so that it returns a SAXHandler with a blank definition for the startPrefixMapping method.

I haven't used this in a production setting so caveat emptor, but I have verified that it does work on some quick and dirty XML stuff I've done.

Ruysdael answered 18/5, 2010 at 19:42 Comment(0)
C
4

You can use /*:foo (XPath 2.0 or higher) or /yournamespace:* as explained here.

The first variant selects all nodes with the matching name, regardless of what namespace they belong to, including having no namespace. The latter selects all nodes belonging to a specific namespace, regardless of the node name.

Campground answered 25/11, 2010 at 19:24 Comment(2)
@user520567: Your second QName test (NS:*) is valid XPath 1.0/2.0, but the first one (*:Name) is only valid XPath 2.0. Without this information your answer has less value...Labiovelar
It is named xpath2-intro ;) And actually question is answered by the first expression only. But sure I should have written that.Campground
A
4

Here is a jDOM2 solution that has been running in a production setting for a year with no trouble.

public class JdomHelper {

    private static final SAXHandlerFactory FACTORY = new SAXHandlerFactory() {
        @Override
        public SAXHandler createSAXHandler(JDOMFactory factory) {
            return new SAXHandler() {
                @Override
                public void startElement(
                        String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
                    super.startElement("", localName, qName, atts);
                }
                @Override
                public void startPrefixMapping(String prefix, String uri) throws SAXException {
                    return;
                }
            };
        }
    };


    /** Get a {@code SAXBuilder} that ignores namespaces.
     * Any namespaces present in the xml input to this builder will be omitted from the resulting {@code Document}. */
    public static SAXBuilder getSAXBuilder() {
        // Note: SAXBuilder is NOT thread-safe, so we instantiate a new one for every call.
        SAXBuilder saxBuilder = new SAXBuilder();
        saxBuilder.setSAXHandlerFactory(FACTORY);
        return saxBuilder;
    }

}
Antisepticize answered 9/5, 2014 at 19:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.