Использование XPath Содержит против HTML в Java

Я собираю значения с HTML-страниц, используя XPath внутри java-программы, чтобы добраться до определенного тега, и иногда использую регулярные выражения для очистки данных, которые я получаю.

После некоторых исследований я нашел HTML Cleaner ( http://htmlcleaner.sourceforge.net/) как наиболее надежный способ для анализа необработанного HTML в хороший формат XML. HTML Cleaner, однако, поддерживает только XPath 1.0, и я чувствую, что нуждаюсь в таких функциях, как "contains". например, в этом фрагменте XML:

<div>
  <td id='1234 foo 5678'>Hello</td>
</div>

Я хотел бы иметь возможность получить текст "Hello" со следующим XPath:

//div/td[contains(@id, 'foo')]/text()

Есть ли способ получить эту функциональность? У меня есть несколько идей, но я бы предпочел не изобретать велосипед, если мне не нужно:

  • Если есть способ вызвать метод оценки HTML Cleaner и использовать TagNode (который я не нашел), я могу использовать сериализатор XML для возвращенного TagNode и соединить вместе XPath для достижения желаемой функциональности.
  • Я мог бы использовать HTML Cleaner для очистки в XML, сериализации обратно в строку и использовать его с другой библиотекой XPath, но я не могу найти хорошего оценщика Java XPath, который работает со строкой.
  • Используя функции TagNode, такие как getElementsByAttValue, я мог бы по существу воссоздать оценку XPath и вставить в функцию содержимого, используя String.contains

Короткий вопрос: есть ли способ использовать XPath, содержащийся в HTML внутри существующей библиотеки Java?

1 ответ

Решение

В соответствии с этим:

Я мог бы использовать HTML Cleaner для очистки в XML, сериализации обратно в строку и использовать его с другой библиотекой XPath, но я не могу найти хорошего оценщика Java XPath, который работает со строкой.

Это именно то , что я бы сделал (за исключением того, что вам не нужно работать со строкой (см. Ниже)).

Многие анализаторы HTML пытаются сделать слишком много. HTMLCleaner, например, неправильно / полностью не реализует спецификацию XPath 1.0 (contains (например) является функцией XPath 1.0). Хорошей новостью является то, что вам это не нужно. Все, что вам нужно от HTMLCleaner - это проанализировать искаженный ввод. Как только вы это сделаете, лучше использовать стандартные интерфейсы XML для работы с получающимся (теперь правильно сформированным) документом.

Сначала преобразовать документ в стандарт org.w3c.dom.Document как это:

TagNode tagNode = new HtmlCleaner().clean(
        "<div><table><td id='1234 foo 5678'>Hello</td>");
org.w3c.dom.Document doc = new DomSerializer(
        new CleanerProperties()).createDOM(tagNode);

А затем используйте стандартные интерфейсы JAXP для запроса:

XPath xpath = XPathFactory.newInstance().newXPath();
String str = (String) xpath.evaluate("//div//td[contains(@id, 'foo')]/text()", 
                       doc, XPathConstants.STRING);
System.out.println(str);

Выход:

Hello
Другие вопросы по тегам