LINUX.ORG.RU

Парсинг невалидного (не по стандартам) DOM

 , , , ,


0

3

Использую простую схему:


        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = null;
        try {
            db = dbf.newDocumentBuilder();
        } catch (ParserConfigurationException e) {
            throw new HtmlProcessorException(e);
        }
        Document xml = null;
        try {
            xml = db.parse(new ByteArrayInputStream(html.getBytes(StandardCharsets.UTF_8)));
        } catch (SAXException e) {
            throw new HtmlToXmlConvertionException("Html parsing exception", e);
        } catch (IOException e) {
            throw new HtmlToXmlConvertionException("Html reading exception", e);
        }

Но HTML содержит ноду с неопределенным атрибутом:

<link href="https://..." mask rel="icon" sizes="any">

В этом примере - mask не определен, выбрасывается эксепшн:

Caused by: org.xml.sax.SAXParseException; lineNumber: 1; columnNumber: 1442; Attribute name "mask" associated with an element type "link" must be followed by the ' = ' character.

Не могу нагуглить, есть ли способы заставить парсер воспринимать такие ситуации правильно, т.е. считать, что если нет ="", то атрибут с пустым значением? Или все-таки придется еще регекспами искать такое и вставлять это «дефолтное» значение?

★★★★★
Ответ на: комментарий от bvn13

Прям XPath я ничего не помню, но если это не обязательное требование, то посмотри на jsoup. Он поддерживает CSS selector в качестве языка запроса.

hippi90 ★★★★★
()
Ответ на: комментарий от bvn13

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

UPD: лорчую jsoup

buddhist ★★★★★
()
Последнее исправление: buddhist (всего исправлений: 1)
Ответ на: комментарий от buddhist

Сам ты рипнулся, никто не мешает использовать его в новой вёрстке.

Moondancer
()
Ответ на: комментарий от bvn13

Это не так. HTML и XML это разные языки разметки, пусть и похожие и произошедшие от общего предка SGML. XHTML это действительно XML и его можно парсить с помощью XML-парсера. Но у тебя не этот вариант. Тебе нужен именно HTML-парсер.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)

Если бы HTML можно было безбоязнено парсить как XML - никто бы не писал regex-парсеры для html.

Deleted
()

Я тырил код для кусков html отсюда( подходит ли это для полновесного html х.з.) -

https://stackoverflow.com/questions/9022140/using-xpath-contains-against-html...

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

//And then use the standard JAXP interfaces to query it:

XPath xpath = XPathFactory.newInstance().newXPath();
String str = (String) xpath.evaluate("//div//td[contains(@id, 'foo')]/text()", 
                       doc, XPathConstants.STRING);
System.out.println(str);
vtVitus ★★★★★
()
Последнее исправление: vtVitus (всего исправлений: 2)
Ответ на: комментарий от hippi90

XPath я ничего не помню

И влезаешь.

jsoup поддерживает CSS selector

А xpath поддерживает любые атрибуты и значения в них, в том числе id и class.

deep-purple ★★★★★
()

Вообще, по идее, оно должно было интерпретировать «mask» как «булевый» атрибут, например как <input type=«file» multiple>

Но это зависит от DTD и XSD описывающим тип документа и правила. В целом, для html5 допустимы кастомные атрибуты. Т.е. по сути твой парсер сломался не потому, что документ не валиден, а потому, что ты ему режим парсинга правильный не поставил.

deep-purple ★★★★★
()
Ответ на: комментарий от Deleted

Отнюдь. Писать регекспы для парсинга хтмл — это говнокод, ССЗБ и даже хуже, чем писать регекспы для парснга хмл, в котором больше порядка, чем в хтмл.

deep-purple ★★★★★
()
Ответ на: комментарий от anonymous

Он его распарсить не может — парсер с ошибкой вываливается. Дальше, конечно, xpath будет использовать.

deep-purple ★★★★★
()

Парсинг невалидного

- очевидно сделать валидным, где возможно конечно.

Есть ряд инструментов: htmltidy, «распрекрасное мыло» ...

anonymous
()
Ответ на: комментарий от deep-purple

Не должно. В XML булевые атрибуты должны указываться как attr=«attr». ОП применяет XML парсер, к нему хипстерные нововведения HTML неприменимы.

anonymous
()
Ответ на: комментарий от deep-purple

Ты про :is() (бывший :matches()) или о чём речь?

anonymous
()
Ответ на: комментарий от deep-purple

Ты тоже не знаешь отличий HTML от XML? Я сегодня добрый, держи прямую ссылку, где прекрасно видно, что знак «=» и значение атрибута не являются опциональными в XML.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)

пока не так много кода - переполз на jsoup

bvn13 ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

В примере именно XML парсер, написанный для того, чтобы парсить XML. И никаким DTD ты это не исправишь. Если это более гибкий парсер, позволяющий парсить нестандартные XML-подобные языки, вопросов нет. Но в Java я про такое не слышал, xerces и прочее такого функционала не имеют. Очень интересно посмотреть на пример, где через DocumentBuilder парсится атрибут без значения.

Legioner ★★★★★
()
Последнее исправление: Legioner (всего исправлений: 1)
Ответ на: комментарий от Legioner

А это уже смотрите в доках к парсеру, умеет он в нужные опции или нет.

deep-purple ★★★★★
()
Ответ на: комментарий от upcFrost

Поверьте, я сам не в восторге от них :)

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.