Почему PHP DOM не включает косую черту на самозакрывающихся тегах? - PullRequest
9 голосов
/ 30 июня 2010

Я использовал PHP DOM для загрузки HTML-шаблона, изменения его и вывода. Недавно я обнаружил, что самозакрывающиеся (пустые) теги не включают закрывающую косую черту, хотя в файле шаблона это и есть.

, например

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"`"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
</body>
</html>

становится:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
</body>
</html>

Это ошибка или настройка, или проблема типа документа?

Ответы [ 3 ]

20 голосов
/ 30 июня 2010

DOMDocument->saveHTML() берет ваш информационный набор XML DOM и записывает его в формате старой школы, а не XML. Не следует использовать saveHTML() вместе с типом документа XHTML, так как его вывод не будет правильно сформированным XML.

Если вместо этого вы используете saveXML(), вы получите правильный XHTML. Хорошо, если этот вывод XML предоставляется совместимым со стандартами браузером, если вы задаете ему заголовок Content-Type: application/xhtml+xml. Но, к сожалению, IE6-8 не сможет это прочитать, поскольку они по-прежнему могут обрабатывать только HTML старой школы под типом text/html.

Обычное компромиссное решение - обслуживать text/html и использовать «HTML-совместимый XHTML», как описано в Приложении C спецификации XHTML 1.0. Но, к сожалению, не существует PHP DOMDocument->saveXHTML() метода для генерации правильного вывода для этого.

Есть несколько вещей, которые вы можете сделать, чтобы убедить saveXML() создать совместимый с HTML вывод для некоторых распространенных случаев. Основным является то, что вы должны убедиться, что только элементы, определенные в HTML4 как имеющие модель содержимого EMPTY (<img>, <br> и т. Д.), Действительно имеют пустой контент, что приводит к самозакрывающемуся синтаксису (<img/>) использоваться. Другие элементы не должны использовать самозакрывающийся синтаксис, поэтому, если они пусты, вы должны поставить пробел в их текстовом содержимом, чтобы они не были такими:

<script src="x.js"/>           <-- no good, confuses HTML parser and breaks page
<script src="x.js"> </script>  <-- fine

Еще одна вещь, на которую стоит обратить внимание, - это обработка встроенных элементов <script> и <style>, которые являются обычными элементами в XHTML, но специальными CDATA -контентными элементами в HTML. Некоторая обтекание /*<![CDATA[*/.../*]]>*/ требуется, чтобы любые < или & символы внутри них вели себя в основном согласованно, хотя учтите, что вам все равно следует избегать последовательностей ]]> и </.

Если вы действительно хотите сделать это правильно, вам придется написать свой собственный сериализатор HTML-совместимых XHTML. В долгосрочной перспективе это, вероятно, будет лучшим вариантом. Но для небольших простых случаев взлом вашего ввода, чтобы он не содержал ничего, что могло бы выйти на другой конец сериализатора XML как несовместимое с HTML, - это, вероятно, быстрое решение.

Это или просто смириться с этим и жить с не-XML HTML старой школы, очевидно.

2 голосов
/ 30 июня 2010

проблема с типом документа, так как это text / html закрывающая косая черта не нужна, закрывающая косая черта нужна, только если это документ в формате xhtml

отметил, что вы обновились, чтобы добавить в doctype, но PHP dom также просматривает тот метатег, который у вас там есть, и content = "text / html; charset = utf-8" явно не основан на XML просто текст / html:)

в сторону: DOM api также берет кодировку оттуда

0 голосов
/ 05 августа 2015

Это старый вопрос, но ...
Как уже говорили другие, PHP DOM оставляет желать лучшего ...
Вот regEx, чтобы закрыть «пустые» теги, если вы этого хотите

$voidTags = array('area','base','br','col','command','embed','hr','img','input','keygen','link','meta','param','source','track','wbr');
$regEx = '#<('.implode('|', $voidTags).')(\b[^>]*)>#';
$html = preg_replace($regEx, '<\\1\\2 />', $html);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...