13

我想使用 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>

爪哇:

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));
}
4

3 回答 3

26

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));
}
于 2009-02-12T20:36:35.310 回答
7

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

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

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

我不建议将此技术作为通用解决方案,但在我的情况下它绝对有用。

于 2009-02-12T23:13:39.737 回答
1

您还可以执行以下操作

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

是有用的 xpath 查询列表。

于 2015-01-23T03:30:31.020 回答