По умолчанию пространство имен XML, JDOM и XPath

Я хочу использовать JDOM для чтения в XML-файле, а затем использовать XPath для извлечения данных из документа JDOM. Он создает объект Document fine, но когда я использую XPath для запроса документа для списка элементов, я ничего не получаю.

Мой XML-документ имеет пространство имен по умолчанию, определенное в корневом элементе. Самое смешное, когда я удаляю пространство имен по умолчанию, он успешно запускает запрос XPath и возвращает те элементы, которые я хочу. Что еще я должен сделать, чтобы получить запрос XPath для получения результатов?

XML:

   Lord of the Rings: The Fellowship of the Ring 178 Ian Holm Elijah Wood Ian McKellen   The Matrix 136 Keanu Reeves Laurence Fishburne   

Ява:

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

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

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

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

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

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

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

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

Вот список полезных запросов xpath.

  • XPath для выбора элемента на основе дочернего значения childs
  • XPath содержит (текст (), «некоторая строка») не работает при использовании с узлом с более чем одним текстовым подзоном
  • В чем разница между css-selector & Xpath? что лучше (по производительности и для кросс-браузерного тестирования)?
  • Оператор XPath OR для разных узлов
  • XPath - получить узел без дочернего элемента определенного типа
  • Использование XPath, как выбрать узел на основе его текстового содержимого и значения атрибута?
  • Xml пространство имен, разбивающее мой xpath!
  • Существует ли XSLT-элемент?
  • xmllint не может правильно запросить с помощью xpath
  • Как вы выводите текущий путь элемента в XSLT?
  • Как получить текст элемента внутри разметки CDATA через XPath?
  • Давайте будем гением компьютера.