带有 XPath 的 JDOM2 不适用于命名空间 [英] JDOM2 with XPath doesn't work with namespace

查看:27
本文介绍了带有 XPath 的 JDOM2 不适用于命名空间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Attempting to use XPath with an XML file that has a default namespace declared for the root node.

示例代码:

    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/" 有效,但不是解决方案!

Removing the xmlns="http://www.stellent.com/sitestudio/Project/" works but isn't a solution!

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

Why isn't XPath able to know about this default namespace? Also, why does it care?

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

Better yet, how can I generically fix this?

感谢您的任何见解.

推荐答案

JDOM 正在做正确的事情.这是一个常见问题解答,不仅适用于 JDOM,还适用于一般的 XPath.XPath 规范对此(有些)清楚(我已将相关部分加粗):

JDOM is doing the right thing. This is a FAQ, and not just for JDOM, but for XPath in general. The XPath specification is (somewhat) clear on this (I have bolded the relevant part):

节点测试中的 QName 使用表达式上下文中的命名空间声明扩展为扩展名.这与对开始和结束标签中的元素类型名称进行扩展的方式相同除了不使用用 xmlns 声明的默认命名空间:如果 QName 没有前缀,则命名空间 URI 为空(这与扩展属性名称的方式相同).如果 QName 具有在表达式上下文中没有命名空间声明的前缀,则会出错.

A QName in the node test is expanded into an expanded-name using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared with xmlns is not used: if the QName does not have a prefix, then the namespace URI is null (this is the same way attribute names are expanded). It is an error if the QName has a prefix for which there is no namespace declaration in the expression context.

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

From an XPath perspective, what this means is that the Namespace handling for rules in the XPath expression are not actually the same as the nodes in the XML. For all XPath expressions you need to define (duplicate) the namespace context for the expression, and the prefixes you use for the expression are actually completely independent to the ones used in the actual XML document.

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

You need to 'invent' a namespace prefix for your default namespace, and use that prefix in your expression (Here I have invented the namespace prefix 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/"))

这篇关于带有 XPath 的 JDOM2 不适用于命名空间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆