Почему эти две функции DOMDocument ведут себя по-разному? - PullRequest
1 голос
/ 28 января 2020

Существует два подхода к получению внешнего HTML узла DOMDocument, предложенного здесь: Как вернуть внешний html DOMDocument?

Мне интересно, почему они похоже, что HTML сущности обрабатываются по-разному.

ПРИМЕР:

function outerHTML($node) {
    $doc = new DOMDocument();
    $doc->appendChild($doc->importNode($node, true));
    return $doc->saveHTML();
}

$html = '<p>ACME&rsquo;s 27&rdquo; Monitor is $200.</p>';
$dom = new DOMDocument();
@$dom->loadHTML($html);
$el = $dom->getElementsByTagname('p')->item(0);
echo $el->ownerDocument->saveHtml($el) . PHP_EOL;
echo outerHTML($el) . PHP_EOL;

ВЫХОД:

<p>ACME’s 27” Monitor is $200.</p>
<p>ACME&rsquo;s 27&rdquo; Monitor is $200.</p>

Оба метода используют saveHTML(), но по какой-то причине функция сохраняет html сущностей в конечном выводе, в то время как прямой вызов saveHTML() с контекстом узла не делает. Кто-нибудь может объяснить почему - желательно с какой-то авторитетной ссылкой?

1 Ответ

1 голос
/ 28 января 2020

То, к чему это сводится, еще проще, чем ваш тестовый пример выше:

<?php
$html = '<p>ACME&rsquo;s 27&rdquo; Monitor is $200.</p>';
$dom = new DOMDocument();
@$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

echo $dom->saveHtml($dom->documentElement) . PHP_EOL;
echo $dom->saveHtml() . PHP_EOL;

Таким образом, возникает вопрос, почему DomDocument::saveHtml ведет себя по-разному при сохранении всего документа, а не только определенного c узел?

Взглянув на источник PHP, мы находим проверку , работает ли она с одним узлом или целым документом. В первом случае функция htmlNodeDumpFormatOutput вызывается с явно заданной нулевой кодировкой. Для последнего используется функция htmlDocDumpMemoryFormat, кодировка не включена в качестве аргумента этой функции.

Обе эти функции взяты из библиотеки libxml2. Глядя на этот источник, мы видим, что htmlDocDumpMemoryFormat пытается обнаружить документ, кодирующий , и явно устанавливает для него значение ASCII / HTML, если он не может его найти.

Обе функции в итоге вызывают htmlNodeListDumpOutput, передавая ему кодировку, которая была определена; либо null - что приводит к отсутствию кодирования - либо ASCII / HTML - который кодирует с использованием HTML сущностей.

Я предполагаю, что для фрагмента документа или отдельного узла кодирование считается менее важным, чем для полный документ.

...