Пространство имен XML по умолчанию, JDOM и XPath - PullRequest
13 голосов
/ 12 февраля 2009

Я хочу использовать 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));
}

Ответы [ 3 ]

26 голосов
/ 12 февраля 2009

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));
}
7 голосов
/ 13 февраля 2009

У меня была похожая проблема, но моя заключалась в том, что у меня была смесь входных данных XML, некоторые из которых определяли пространство имен, а другие - нет. Чтобы упростить мою проблему, я запустил следующий фрагмент JDOM после загрузки документа.

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

После удаления всех пространств имен я смог использовать простой стиль навигации getChild ("elname") или простые запросы XPath.

Я бы не рекомендовал эту технику в качестве общего решения, но в моем случае она была определенно полезной.

1 голос
/ 23 января 2015

Вы также можете сделать следующее

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

Здесь - список полезных запросов xpath.

...