DOM, который позволяет использовать тег </ in <script> HTML5

Обновление : 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> . Все синтаксические анализаторы, которые я пробовал до сих пор, либо потерпели неудачу, либо они настолько плохо документированы, что я не понял, работают ли они или нет.

Мои требования:

  1. Настоящий парсер, а не регулярные выражения.
  2. Возможность загрузки полных страниц или фрагментов HTML.
  3. Возможность вывести содержимое скрипта обратно, выбрав атрибут id тега.

Входные данные:

 <script id="foo"><td>bar</td></script> 

Пример выхода с ошибкой (без закрытия </td> ):

 <script id="foo"><td>bar</script> 

Некоторые парсеры и их результаты:

DOMDocument (сбой)

Источник:

 <?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> 

FluentDOM (сбой)

Источник:

 <?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> 

phpQuery (сбой)

Источник:

 <?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> 

html5lib (проходит)

Возможно многообещающий. Могу ли я получить содержимое 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); 

Надеюсь, это поможет некоторым людям :-).