如何让JDOM/XPath忽略命名空间?

6

我需要处理一个XML DOM,最好使用JDOM,在节点上可以进行XPath搜索。我知道节点名称或路径,但我想完全忽略命名空间,因为有时文档带有命名空间,有时没有,我不能依赖于特定的值。这是否可能?如何实现?


不要忽略它们,您也可以检索并使用它们。请参阅如何使用Xpath检索XML文件中的命名空间 - Matthew Read
4个回答

18
/ns:foo/ns:bar/@baz

变成

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

你懂的,不要期望那是闪电般地快。


我尝试了这里的解决方案:https://dev59.com/4HRB5IYBdhLWcg3wtZIV 它更简单,并且只要根元素声明了任何命名空间,它就可以工作。但如果没有命名空间,则不能工作-因此要么我使用上述方法,要么我需要针对无命名空间的情况有一个单独的解决方案。 - AdSR
@AdSR:您的问题似乎意味着您不了解输入文档的命名空间状态,并且它们是随机的。在这种情况下,上面的方法是“最安全”的,因为它始终有效,但您失去了区分“x:foo”和“ns:foo”的能力。 - Tomalak
谢谢,这个解决方案在jdom 1.x中对我有用(/*:foo不起作用)。 - expert

4
我知道这个问题有点老了,但是对于后来查看此问题的人来说,您可以覆盖一些JDOM默认类来有效地使其忽略名称空间。您可以将自己的JDOMFactory实现传递给SAXBuilder,它会忽略传递给它的所有命名空间值。
然后覆盖SAXBuilder类并实现createContentHandler方法,使其返回一个具有startPrefixMapping方法空定义的SAXHandler。
我尚未在生产设置中使用此功能,但我已经验证它可以在我做过的一些快速和肮脏的XML处理中工作。

4
您可以使用/*:foo(XPath 2.0或更高版本)或/yournamespace:*如此所述。第一种变体选择所有具有匹配名称的节点,无论它们属于什么命名空间,包括没有命名空间的节点。后者选择属于特定命名空间的所有节点,而不考虑节点名称。

@user520567:你的第二个QName测试('NS:*')是有效的XPath 1.0/2.0,但第一个('*:Name')只在XPath 2.0中有效。如果没有这些信息,你的答案价值会降低…… - user357812
它被命名为xpath2-intro ;) 实际上,问题只被第一个表达式回答了。但是当然我应该写下来的。 - akostadinov

4

这里有一个jDOM2解决方案,已经在生产环境中运行了一年,没有出现任何问题。

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;
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接