4

尝试将 XPath 与具有为根节点声明的默认命名空间的 XML 文件一起使用。

示例代码:

    final SAXBuilder builder = new SAXBuilder();
    final Document document = builder.build(originalFile);

    final XPathFactory xFactory = XPathFactory.instance();

    final String expression = String.format("//section[@label='%s']/section/section", LABEL);
    final XPathExpression<Element> sectionExpression = xFactory.compile(expression, Filters.element());
    final List<Element> sections = sectionExpression.evaluate(document);

部分为空。

XML 的片段

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://www.stellent.com/sitestudio/Project/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.stellent.com/sitestudio/Project/ http://www.stellent.com/sitestudio/ss_project_schema.xsd">
    <section label="Index">
        <section label="xyz">
           <section label="child">
           ...
           </section>
        </section>
    </section>
</project>

删除xmlns="http://www.stellent.com/sitestudio/Project/"作品但不是解决方案!

为什么 XPath 不能知道这个默认命名空间?还有,为什么在乎?

更好的是,我一般如何解决这个问题?

感谢您的任何见解。

4

1 回答 1

9

JDOM 正在做正确的事情。这是一个常见问题解答,不仅适用于 JDOM,而且适用于一般的 XPath。XPath 规范(在某种程度上)对此很清楚(我已将相关部分加粗)

使用来自表达式上下文的命名空间声明将节点测试中的 QName 扩展为扩展名称。这与对开始和结束标记中的元素类型名称进行扩展的方式相同,只是不使用使用 xmlns 声明的默认命名空间:如果 QName 没有前缀,则命名空间 URI 为空(这是相同的方式属性名称被扩展)。如果 QName 具有在表达式上下文中没有名称空间声明的前缀,则这是一个错误。

从 XPath 的角度来看,这意味着 XPath 表达式中规则的命名空间处理实际上与 XML 中的节点不同。对于所有 XPath 表达式,您需要为表达式定义(复制)名称空间上下文,并且用于表达式的前缀实际上完全独立于实际 XML 文档中使用的前缀。

您需要为默认命名空间“发明”一个命名空间前缀,并在表达式中使用该前缀(这里我发明了命名空间前缀ns):

final String expression = String.format("//ns:section[@label='%s']/ns:section/ns:section", LABEL);
final XPathExpression<Element> sectionExpression = xFactory.compile(expression, Filters.e, null,
         Namespace.getNamespace("ns", "http://www.stellent.com/sitestudio/Project/"))
于 2014-07-04T12:22:57.957 回答