Я пытаюсь разобрать HTML-код с DOMDocument, сделать что-то вроде изменений в нем, а затем собрать его обратно в строку, которую я отправляю на вывод.
Но есть несколько вопросов, касающихся разбора, что означает, что то, что я отправляю в DOMDocument, не всегда возвращается в том же виде 🙂
Вот список:
используя -> loadHTML :
preserveWhitespace
и formatOutput
(теряя пробелы в предварительно отформатированном тексте) <header>
, <footer>
и т. д. Но они могут быть подавлены, поэтому я могу жить с этим. <link ... />
(с самозакрывающимся тегом), после разбора / сохраненияHTML вывод будет <link .. >
using -> loadXML :
>
из тегов <style>
или <script>
: body > div
становится body > div
body > div
<meta ... />
становится <meta...></meta>
; но это может быть исправлено с помощью регулярного выражения. Я не пробовал HTML5lib, но я бы предпочел DOMDocument вместо настраиваемого анализатора по причинам производительности
Так, как 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, чего я не хочу …
К сожалению, или, возможно, к счастью, domdocument разработан, чтобы не пытаться сохранить форматирование из исходного документа. Это упрощает управление внутренним состоянием парсера, сохраняя все элементы одного и того же стиля. Afaik most parsers создаст представление дерева в памяти и не беспокоится о текстовом форматировании, пока пользователь не запросит такие. Вот почему ваши закрытые теги выводятся с отдельными закрывающими тегами. Хорошая новость заключается в том, что это не имеет значения.
Что касается тегов стиля и тегов скриптов, получивших <>
преобразованный в <>
, вы можете избежать конверсии, окружая содержимое элемента, о котором идет речь, с рекомендуемыми тегами cdata:
<style> /*<![CDATA[*/ body > div { width: 50%; } /*]]>*/ </style>
Комментарий /* */
вокруг деклараций cdata заключается в том, чтобы разрешить разбитым клиентам, которые не знают о разделах cdata, и вместо этого обрабатывать объявления как код CSS. Если вы используете документ только внутри, вы можете опустить окружения /* */
comment и иметь только объявление cdata. Вы можете столкнуться с проблемами с вышеупомянутыми сломанными клиентами, если вы манипулируете документом, а затем отправляете его в браузер, не проверяя, чтобы /* */
комментарии сохранялись; Я не уверен, сохранит ли domdocument эти или нет.
Используйте html5lib . Он может анализировать html5 и производить DOMDocument. Пример:
require_once '/path/to/HTML5/Parser.php'; $dom = HTML5_Parser::parse('<html><body>...');
Документация
Если вы хотите поддерживать HTML5, не трогайте DOMDocument.
В настоящее время лучшим вариантом является https://github.com/Masterminds/html5-php
Раньше лучшим вариантом был https://github.com/html5lib/html5lib-php, но, как говорится в описании, он «в настоящее время не поддерживается». И это был статус с октября 2011 года, поэтому я больше не задерживаю дыхание.
Я не использовал html5-php
в производстве, поэтому я не могу представить реальный мир об этом. Я использовал html5lib-php
в производстве, и я бы сказал, что он правильно html5lib-php
хорошо сформированные документы, но он имеет неожиданные ошибки с некоторыми простыми синтаксическими ошибками. С другой стороны, кажется, что алгоритм внедрения агентства принятия решений и некоторые другие странные угловые случаи правильно. Если html5lib-php
все еще поддерживался, я бы предпочел это. Однако, поскольку в настоящее время я предпочитаю использовать html5-php
и, возможно, помогать исправлять оставшиеся ошибки там.
Я пробовал как html5lib, так и html5php, но ни один из них не работал с HTML, который мне предоставили. Альтернативой, которая могла анализировать HTML, была: https://github.com/ivopetkov/html5-dom-document-php
Основной класс расширяет собственный DomDocument PHP.
При инициализации domDocument выполните следующие действия:
$dom = new DOMDocument(5, 'UTF-8');