默认 XML 命名空间、JDOM 和 XPath

发布于 2024-07-13 12:33:49 字数 1188 浏览 3 评论 0原文

我想使用 JDOM 读取 XML 文件,然后使用 XPath 从 JDOM 文档中提取数据。 它很好地创建了 Document 对象,但是当我使用 XPath 查询 Document 中的元素列表时,我什么也没得到。

我的 XML 文档在根元素中定义了一个默认命名空间。 有趣的是,当我删除默认名称空间时,它成功运行 XPath 查询并返回我想要的元素。 我还必须做什么才能让我的 XPath 查询返回结果?

XML:

<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.foo.com">
<dvd id="A">
  <title>Lord of the Rings: The Fellowship of the Ring</title>
  <length>178</length>
  <actor>Ian Holm</actor>
  <actor>Elijah Wood</actor>
  <actor>Ian McKellen</actor>
</dvd>
<dvd id="B">
  <title>The Matrix</title>
  <length>136</length>
  <actor>Keanu Reeves</actor>
  <actor>Laurence Fishburne</actor>
</dvd>
</collection>

Java:

public static void main(String args[]) throws Exception {
    SAXBuilder builder = new SAXBuilder();
    Document d = builder.build("xpath.xml");
    XPath xpath = XPath.newInstance("collection/dvd");
    xpath.addNamespace(d.getRootElement().getNamespace());
    System.out.println(xpath.selectNodes(d));
}

I want to use JDOM to read in an XML file, then use XPath to extract data from the JDOM Document. It creates the Document object fine, but when I use XPath to query the Document for a List of elements, I get nothing.

My XML document has a default namespace defined in the root element. The funny thing is, when I remove the default namespace, it successfully runs the XPath query and returns the elements I want. What else must I do to get my XPath query to return results?

XML:

<?xml version="1.0" encoding="UTF-8"?>
<collection xmlns="http://www.foo.com">
<dvd id="A">
  <title>Lord of the Rings: The Fellowship of the Ring</title>
  <length>178</length>
  <actor>Ian Holm</actor>
  <actor>Elijah Wood</actor>
  <actor>Ian McKellen</actor>
</dvd>
<dvd id="B">
  <title>The Matrix</title>
  <length>136</length>
  <actor>Keanu Reeves</actor>
  <actor>Laurence Fishburne</actor>
</dvd>
</collection>

Java:

public static void main(String args[]) throws Exception {
    SAXBuilder builder = new SAXBuilder();
    Document d = builder.build("xpath.xml");
    XPath xpath = XPath.newInstance("collection/dvd");
    xpath.addNamespace(d.getRootElement().getNamespace());
    System.out.println(xpath.selectNodes(d));
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

━╋う一瞬間旳綻放 2024-07-20 12:33:49

XPath 1.0 不支持默认命名空间的概念(XPath 2.0 支持)。
任何无前缀的标记始终被假定为无名称命名空间的一部分。

当使用XPath 1.0时,你需要这样的东西:

public static void main(String args[]) throws Exception {
    SAXBuilder builder = new SAXBuilder();
    Document d = builder.build("xpath.xml");
    XPath xpath = XPath.newInstance("x:collection/x:dvd");
    xpath.addNamespace("x", d.getRootElement().getNamespaceURI());
    System.out.println(xpath.selectNodes(d));
}

XPath 1.0 doesn't support the concept of a default namespace (XPath 2.0 does).
Any unprefixed tag is always assumed to be part of the no-name namespace.

When using XPath 1.0 you need something like this:

public static void main(String args[]) throws Exception {
    SAXBuilder builder = new SAXBuilder();
    Document d = builder.build("xpath.xml");
    XPath xpath = XPath.newInstance("x:collection/x:dvd");
    xpath.addNamespace("x", d.getRootElement().getNamespaceURI());
    System.out.println(xpath.selectNodes(d));
}
银河中√捞星星 2024-07-20 12:33:49

我遇到了类似的问题,但我的问题是 XML 输入的混合,其中一些输入定义了命名空间,而另一些则没有。 为了简化我的问题,我在加载文档后运行了以下 JDOM 片段。

for (Element el : doc.getRootElement().getDescendants(new ElementFilter())) {
    if (el.getNamespace() != null) el.setNamespace(null);
}

删除所有命名空间后,我能够使用简单的 getChild("elname") 样式导航或简单的 XPath 查询。

我不会推荐这种技术作为通用解决方案,但就我而言,它绝对有用。

I had a similiar problem, but mine was that I had a mixture of XML inputs, some of which had a namespace defined and others that didn't. To simplify my problem I ran the following JDOM snippet after loading the document.

for (Element el : doc.getRootElement().getDescendants(new ElementFilter())) {
    if (el.getNamespace() != null) el.setNamespace(null);
}

After removing all the namespaces I was able to use simple getChild("elname") style navigation or simple XPath queries.

I wouldn't recommend this technique as a general solution, but in my case it was definitely useful.

寂寞陪衬 2024-07-20 12:33:49

您还可以执行以下操作


/*[本地名称() = '集合']/*[本地名称() = 'DVD']/

这里是列表有用的 xpath 查询。

You can also do the following


/*[local-name() = 'collection']/*[local-name() = 'dvd']/

Here is list of useful xpath queries.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文