Java XPath:使用默认命名空间 xmlns 进行查询

Posted

技术标签:

【中文标题】Java XPath:使用默认命名空间 xmlns 进行查询【英文标题】:Java XPath: Queries with default namespace xmlns 【发布时间】:2012-05-30 00:45:13 【问题描述】:

我想对此文件进行 XPath 查询(显示摘录):

<?xml version="1.0" encoding="UTF-8"?>
<!-- MetaDataAPI generated on: Friday, May 25, 2007 3:26:31 PM CEST -->
<ModelClass xmlns="http://xml.sap.com/2002/10/metamodel/webdynpro" xmlns:IDX="urn:sap.com:WebDynpro.ModelClass:2.0">
    <ModelClass.Parent>
        <Core.Reference package="com.test.mypackage" name="ModelName" type="Model"/>

这是我正在使用的代码的 sn-p:

DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document document = builder.parse(new File(testFile));
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
xpath.setNamespaceContext( new NamespaceContext() 
    public String getNamespaceURI(String prefix) 
...

String result = xpath.evaluate(xpathQueryString, document);
System.out.println(result);

我面临的问题是,当在 XPath 查询中引用默认命名空间时,不会调用 getNamespaceURI 方法来解决它。 例如,此查询不会提取任何内容:

//xmlns:ModelClass.Parent/xmlns:Core.Reference[@type=\"Model\"]/@package

现在我尝试通过用假前缀 d 替换 xmlns 来“欺骗”解析器,然后相应地编写 getNamespaceURI 方法(以便在遇到 d 时返回 http://xml.sap.com/2002/10/metamodel/webdynpro)。在这种情况下,getNamespaceURI 被调用,但 XPath 表达式求值的结果始终为空字符串。

如果我从文件和 XPath 查询表达式中去掉命名空间,我可以得到我想要的字符串 (com.test.mypackage)。

有没有办法让默认命名空间正常工作?

【问题讨论】:

【参考方案1】:

XPath 1.0 规范要求“没有前缀意味着没有命名空间”。因此,为 XPath 1.0 设计的 JAXP 阻止您将“空前缀”绑定到某个非空名称空间是完全正确的。

XPath 2.0 允许您在 XPath 表达式中为非限定名称声明默认命名空间,但要利用这一点,您需要一个利用此功能的 API(例如 Saxon 的 s9api)。

【讨论】:

【参考方案2】:

在您的 Namespace 上下文中,将您选择的前缀(例如 df)绑定到文档中的命名空间 URI

xpath.setNamespaceContext( new NamespaceContext() 
    public String getNamespaceURI(String prefix) 
      switch (prefix) 
        case "df": return "http://xml.sap.com/2002/10/metamodel/webdynpro";
        ...
       
    );

然后在路径表达式中使用该前缀来限定元素名称,例如/df:ModelClass/df:ModelClass.Parent/df:Core.Reference[@type = 'Model']/@package.

【讨论】:

确保在使用命名空间之前还创建了一个命名空间感知 DocumentBuilder docs.oracle.com/javase/6/docs/api/javax/xml/parsers/…。 成功了。我认为 DocumentBuilder 默认情况下知道名称空间。再次感谢您。

以上是关于Java XPath:使用默认命名空间 xmlns 进行查询的主要内容,如果未能解决你的问题,请参考以下文章

使用XPath查询带有命名空间(有xmlns)的XML(转)

python 使用xpath解析含有命名空间(xmlns)的xml

Java中带有命名空间的XPath

jdom xpath定位带xmlns命名空间的节点(转)

使用命名空间对属性进行 XPath 过滤

如何使用Xpath检索XML文件中的命名空间