Использование 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