Использование 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 для оценкиXPath и вернуть TagNode (который я еще не нашел), я могу использовать XML-сериализатор в возвращаемом TagNode и объединить XPaths для достижения желаемой функциональности.
- Я мог бы использовать HTML Cleaner для очистки XML, сериализации его обратно в строку и использовать его с другой библиотекой XPath, но я не могу найти хороший оценщик java XPath, который работает с строкой.
- Используя функции TagNode, такие как getElementsByAttValue, я мог бы, по существу, воссоздать оценку XPath и вставить в функции contains с помощью String.contains
Короткий вопрос: можно ли использовать XPath для HTML внутри существующей библиотеки Java?
Ответы
Ответ 1
Относительно этого:
Я мог бы использовать HTML Cleaner для очистки XML, сериализовать его обратно на string и использовать это с другой библиотекой 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