Обновление : html5lib
(внизу вопроса), похоже, приближается, мне просто нужно улучшить свое понимание того, как оно используется.
Я пытаюсь найти HTML5-совместимый парсер DOM для PHP 5.3. В частности, мне нужно получить доступ к следующему HTML-подобному CDATA в теге скрипта:
<script type="text/x-jquery-tmpl" id="foo"> <table><tr><td>${name}</td></tr></table> </script>
Большинство парсеров перестают разбираться преждевременно, потому что HTML 4.01 завершает парсинг тегов скриптов, когда он находит ETAGO ( </
) внутри <script>
. Однако HTML5 позволяет использовать </
before </script>
. Все синтаксические анализаторы, которые я пробовал до сих пор, либо потерпели неудачу, либо они настолько плохо документированы, что я не понял, работают ли они или нет.
Мои требования:
Входные данные:
<script id="foo"><td>bar</td></script>
Пример выхода с ошибкой (без закрытия </td>
):
<script id="foo"><td>bar</script>
Некоторые парсеры и их результаты:
Источник:
<?php header('Content-type: text/plain'); $d = new DOMDocument; $d->loadHTML('<script id="foo"><td>bar</td></script>'); echo $d->saveHTML();
Вывод:
Warning: DOMDocument::loadHTML(): Unexpected end tag : td in Entity, line: 1 in /home/adam/public_html/2010/10/26/dom.php on line 5 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html><head><script id="foo"><td>bar</script></head></html>
Источник:
<?php header('Content-type: text/plain'); require_once 'FluentDOM/src/FluentDOM.php'; $html = "<html><head></head><body><script id='foo'><td></td></script></body></html>"; echo FluentDOM($html, 'text/html');
Вывод:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html><head></head><body><script id="foo"><td></script></body></html>
Источник:
<?php header('Content-type: text/plain'); require_once 'phpQuery.php'; phpQuery::newDocumentHTML(<<<EOF <script type="text/x-jquery-tmpl" id="foo"> <td>test</td> </script> EOF );
echo (string) pq ('# foo');
Вывод:
<script type="text/x-jquery-tmpl" id="foo"> <td>test </script>
Возможно многообещающий. Могу ли я получить содержимое script#foo
tag?
Источник:
<?php header('Content-type: text/plain'); include 'HTML5/Parser.php'; $html = "<!DOCTYPE html><html><head></head><body><script id='foo'><td></td></script></body></html>"; $d = HTML5_Parser::parse($html); echo $d->saveHTML();
Вывод:
<html><head></head><body><script id="foo"><td></td></script></body></html>
У меня была такая же проблема, и, видимо, вы можете взломать свой путь через это, загрузив документ в формате XML и сохраните его как HTML 🙂
$d = new DOMDocument; $d->loadXML('<script id="foo"><td>bar</td></script>'); echo $d->saveHTML();
Но, конечно, разметка должна быть безошибочной для работы loadXML.
Re: html5lib
Вы нажимаете на вкладку загрузки и загружаете PHP-версию синтаксического анализатора .
Вы распаковываете архив в локальной папке
tar -zxvf html5lib-php-0.1.tar.gz x html5lib-php-0.1/ x html5lib-php-0.1/VERSION x html5lib-php-0.1/docs/ ... etc
Вы меняете каталоги и создаете файл с именем hello.php
cd html5lib-php-0.1 touch hello.php
Вы поместите следующий PHP-код в hello.php
$html = '<html><head></head><body> <script type="text/x-jquery-tmpl" id="foo"> <table><tr><td>${name}</td></tr></table> </script> </body></html>'; $dom = HTML5_Parser::parse($html); var_dump($dom->saveXml()); echo "\nDone\n";
Вы запускаете hello.php
из командной строки
php hello.php
Парсер проанализирует дерево документов и вернет объект DOMDocument, который можно манипулировать как любой другой объект DOMDocument.
FluentDOM использует DOMDocument, но блокирует уведомления о загрузке и предупреждения. У него нет собственного парсера. Вы можете добавить свои собственные загрузчики (например, тот, который использует html5lib).
Я добавил теги комментариев ( <!-- ... -->
) в моих блоках шаблона jQuery (блоки CDATA также не удалось), а DOMDocument не коснулся внутреннего HTML.
Затем, прежде чем я использовал шаблоны jQuery, я написал сценарий для удаления комментариев.
$(function() { $('script[type="text/x-jquery-tmpl"]').text(function() { // The comment node in this context is actually a text node. return $.trim($(this).text()).replace(/^<!--([\s\S]*)-->$/, '$1'); }); });
Не идеально, но я не был уверен в лучшем обходном пути.
Я столкнулся с этой точной проблемой.
PHP Dom Document анализирует html внутри тега скрипта и фактически может привести к совершенно другому dom.
Поскольку я не хотел использовать другую библиотеку, кроме DomDocument. Я написал несколько строк, которые разбивают содержимое любого скрипта, а затем вы делаете то, что вам нужно делать с документом dom, а затем вы возвращаете содержимое этого скрипта.
Очевидно, что содержимое скрипта недоступно для вашего объекта dom, потому что оно пустое.
Со следующими строками php-кода вы можете «исправить» эту проблему. Будьте предупреждены, что теги скриптов в тегах скриптов вызовут ошибку.
$scripts = array(); // this will select all script tags non-greedy. If you have a script tag in your script tag, it will cause problems. preg_match_all("/((<script.*>)(.*))\/script>/sU", $html, $scripts); // Make content of scripts empty $html = str_replace($scripts[3], '', $html); // Do DOM Document stuff here // Put script contents back $html = str_replace($scripts[2], $scripts[1], $html);
Надеюсь, это поможет некоторым людям :-).