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

问题描述:

我需要处理XML DOM,最好使用JDOM,我可以在节点上执行XPath搜索。我知道节点名称或路径,但我想忽略命名空间完全,因为有时文档带有命名空间,有时没有,并且我不能依赖特定的值。那可能吗?怎么样?如何让JDOM/XPath忽略名称空间?

+0

与其忽略它们,您也可以检索并使用它们。请参阅[如何使用Xpath检索XML文件中的名称空间](http://*.com/q/122463/507761) – 2012-03-13 21:50:44

我知道这个问题有点老了,但对于那些稍后查看的人,您可以重写一些JDOM默认类来有效地忽略命名空间。您可以将自己的JDOMFactory实现传递给SAXBuilder,该SAXBuilder会忽略传入它的所有名称空间值。

然后覆盖SAXBuilder类并实现createContentHandler方法,以便它返回一个SAXHandler,其中包含startPrefixMapping方法的空白定义。

我没有在生产设置中使用这个警告emptor,但我已经验证它可以处理一些我已经完成的快速和肮脏的XML事情。

/ns:foo/ns:bar/@baz 

成为

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

你明白了吧。不要指望它也快如闪电。

+0

我尝试了以下解决方案:http://*.com/questions/543049/default-xml -namespace-jdom-and-xpath 只要根元素声明了任何名称空间,它就简单多了。但是如果没有命名空间,它不会 - 所以我使用上面的,或者我有一个单独的解决方案没有名称空间。 – AdSR 2010-04-09 14:36:34

+0

@AdSR:您的问题似乎意味着您不知道输入文档的名称空间状态,它们随机出现。在这种情况下,以上是“最安全的”,如下所示:它将始终有效,但是您失去了在'x:foo'和'ns:foo'之间区别的能力。 – Tomalak 2010-04-09 15:25:34

+0

谢谢,这个解决方案在jdom 1.x中为我工作(/ *:foo没有工作)。上面的 – expert 2012-08-29 16:42:02

您可以使用/*:foo(XPath 2.0或更高版本)或/yournamespace:*as explained here

第一个变体选择具有匹配名称的所有节点,而不管它们属于哪个名称空间,包括没有名称空间。后者选择属于特定名称空间的所有节点,而不管节点名称如何。

+0

@ user520567:您的第二个QName测试('NS:*')是有效的XPath 1.0/2.0,但第一个('*:Name')只是有效的XPath 2.0。没有这些信息,你的答案价值就会降低...... – 2010-11-25 21:53:32

+0

它被命名为xpath2-intro;) 实际上,问题仅由第一个表达式回答。但是我确定我应该写这个。 – akostadinov 2010-12-02 07:23:23

这是一个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; 
    } 

}