Вопрос по php, html5 – Как заставить HTML5 работать с DOMDocument?

17

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

Но есть несколько проблем, связанных с анализом, что означает, что то, что я отправляю в DOMDocument, не всегда возвращается в той же форме :)

Вот список:

using ->loadHTML:

formats my document regardless of the preserveWhitespace and formatOutput settings (loosing whitespaces on preformatted text) gives me errors when I have html5 tags like <header>, <footer> etc. But they can be supressed, so I can live with this. produces inconsistent markup - for example if I add a <link ... /> element (with a self-closing tag), after parsing/saveHTML the output will be <link .. >

using ->loadXML:

encodes entities like > from <style> or <script> tags: body > div becomes body &gt; div all tags are closed the same way, for example <meta ... /> becomes <meta...></meta>; but this can be fixed with an regex.

Я не пробовал HTML5lib, но я предпочел DOMDocument вместо пользовательского парсера по соображениям производительности

Update:

Таким образом, как упоминается Honeymonster, использование CDATA решает основную проблему с loadXML.

Можно ли как-нибудь предотвратить самозакрытие всех пустых тегов HTML, кроме определенного набора, без использования регулярных выражений?

Прямо сейчас у меня есть:

$html = $dom->saveXML($node);

$html = preg_replace_callback('#<(\w+)([^>]*)\s*/>#s', function($matches){

       // ignore only these tags
       $xhtml_tags = array('br', 'hr', 'input', 'frame', 'img', 'area', 'link', 'col', 'base', 'basefont', 'param' ,'meta');

       // if a element that is not in the above list is empty,
       // it should close like   `<element></element>` (for eg. empty `<title>`)
       return in_array($matches[1], $xhtml_tags) ? "<{$matches[1]}{$matches[2]} />" : "<{$matches[1]}{$matches[2]}></{$matches[1]}>";
}, $html);

который работает, но он также будет выполнять замены в контенте CDATA, который я не хочу ...

Я предполагаю, что, поскольку он написан на PHP, DOMDocument является расширением PHP, написанным на C Alex
У вас есть тестовый фрагмент, с которым мы можем поиграть? John Conde
На самом деле определенные элементы должны иметь их, по крайней мере, в некоторых браузерах Alex
"loosing whitespaces on preformatted text" Я сомневаюсь, что. Пожалуйста, приведите пример, демонстрирующий эту проблему. А что на самом деле не так с «самозакрывающимся тегом»? Я имею в виду, HTML5 не должен иметь его, верно? Или ты имеешь ввиду XHTML5? hakre
Откуда вы знаете, что html5lib работает медленнее, чем DOMDocument, если вы даже не пробовали его? Brad

Ваш Ответ

5   ответов
7

В настоящее время лучшим вариантом кажетсяhttps://github.com/Masterminds/html5-php

Ранее лучший вариант былhttps://github.com/html5lib/html5lib-php но, как говорится в описании, он "в настоящее время не поддерживается". И это состояние с октября 2011 года, поэтому я больше не задерживаю дыхание.

Я не использовалhtml5-php в производстве, поэтому я не могу предоставить какой-либо реальный опыт об этом. Я использовалhtml5lib-php в производстве, и я бы сказал, что он правильно анализирует правильно сформированные документы, но имеет неожиданные ошибки с некоторыми простыми синтаксическими ошибками. С другой стороны, кажется, правильно реализует алгоритм агентства по усыновлению и некоторые другие странные случаи. Еслиhtml5lib-php все еще поддерживали, я все еще предпочел бы это. Однако в настоящее время я предпочитаю использоватьhtml5-php и, возможно, поможет исправить оставшиеся ошибки там.

7

или, к счастью, domdocument разработан так, чтобы не пытаться сохранить форматирование из исходного документа. Это облегчает управление внутренним состоянием синтаксического анализатора, сохраняя все элементы в одном стиле. Afaik большинство парсеров создаст представление дерева в памяти и не будет беспокоиться о форматировании текста, пока пользователь не запросит такое. Вот почему ваши закрытые теги выводятся с отдельными закрывающими тегами. Хорошей новостью является то, что это не имеет значения.

Как получить теги стиля и теги скрипта<> конвертировано в&lt;&gt;вы можете избежать преобразования, окружив содержимое соответствующего элемента рекомендованными тегами cdata следующим образом:

<style>
  /*<![CDATA[*/
    body > div {
      width: 50%;
    }
  /*]]>*/
</style>

Комментарий/* */ вокруг объявлений cdata должны учитываться неработающие клиенты, которые не знают о разделах cdata, и вместо этого обрабатывают объявления как код CSS. Если вы используете документ только для внутреннего использования, вы можете опустить/* */ комментарий окружает и имеет только объявление cdata. Вы можете столкнуться с проблемами с вышеупомянутыми неработающими клиентами, если вы манипулируете документом и затем отправляете его в браузер без проверки, чтобы убедиться, что/* */ комментарии сохраняются; Я не уверен, сохранит ли это документ или нет.

вау, я не могу поверить, что не думал об использовании CDATA :) спасибо, это решает многие проблемы с парсером xml, который я хотел использовать;) Alex
13

html5lib, Он может анализировать HTML5 и создавать DOMDocument. Пример:

require_once '/path/to/HTML5/Parser.php';
$dom = HTML5_Parser::parse('<html><body>...');

Документация

Но html5lib может сохранить документы и вернуть строку с хорошим форматом? Я не видел этого в исходном коде.
-5

$dom = new DOMDocument(5, 'UTF-8');
К сожалению, параметр version не относится к версии HTML.
3

и html5php, но ни тот, ни другой не работали с HTML, который мне предоставили. Альтернатива, которая смогла разобрать HTML, была:https://github.com/ivopetkov/html5-dom-document-php

Основной класс расширяет нативный PHP-DomDocument.

Мой основной вывод из этой конкретной библиотеки был такой:Allows querying the DOM with CSS selectors (currently avaiable: *, tagname, tagname#id, #id, tagname.classname, .classname, tagname[attribute="value"], [attribute="value"], tagname[attribute], [attribute]) - теперь ты можешь$foo = $dom->querySelectorAll('img[srcset]'); - очень полезно.

Похожие вопросы