Я пытаюсь проанализировать некоторый HTML-код, возвращенный внешней системой с XOM.HTML-код выглядит следующим образом:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<body>
<div>
Help I am trapped in a fortune cookie factory
</div>
</body>
</html>
(На самом деле он значительно более запутанный, но в нем есть объявление DOCTYPE, а также объявления пространств имен и языка, а в приведенном выше коде HTML та же проблема, что и в реальном HTML.)
Я хочу извлечь содержимое <div>
, но объявление пространства имен, похоже, сбивает с толку XPath.Если я удаляю объявление пространства имен (вручную, из файла), следующий код находит <div>
, без проблем:
Document document = ...
Nodes divs = document.query("//div");
Но с пространством имен возвращаемый Nodes
имеет размериз 0.
Хорошо, а как насчет того, чтобы программно обрезать пространство имен?
Element rootElement = document.getRootElement();
rootElement.removeNamespaceDeclaration(rootElement.getNamespacePrefix());
... выглядит так, как будто оно должно работать, но ничего не делает.Из javadoc :
Этот метод удаляет только дополнительные пространства имен, добавленные с addNamespaceDeclaration.
Хорошо, я думал, я предоставлю пространство именк запросу:
XPathContext context =
XPathContext.makeNamespaceContext(document.getRootElement());
Nodes divs = document.query("//div", context);
Размер по-прежнему равен нулю.
Как насчет создания контекста пространства имен вручную?
XPathContext context = context = new XPathContext(
rootElement.getNamespacePrefix(), rootElement.getNamespaceURI());
Nodes divs = document.query("//div", context);
Конструктор XPathContext
взрывается с помощью:
nu.xom.NamespaceConflictException:
XPath expressions do not use the default namespace
Итак, я ищу:
- способ заставить этот запрос работать или
- способ программным образом обрезать объявления пространства именили
- объяснение правильного подхода, предполагая, что оба они неверны.
Обновление: На основании Ответ Льва Левицкого и Jaxen FAQ Я придумал следующий взлом:
XPathContext context = new XPathContext(
"foo",
document.getRootElement().getNamespaceURI());
Nodes divs = document.query("//foo:div");
Это все еще кажется мне немного сумасшедшим, но я предполагаю, что Джексен хочет, чтобы вы это делаливещи.
Обновление № 2: Как отмечено ниже и по всему Интернету , это не вина Джаксена;просто XPath - это XPath.
Итак, пока этот хак работает, я все же хотел бы отменить объявление пространства имен.Желательно, не доходя до XSLT.