То, к чему это сводится, еще проще, чем ваш тестовый пример выше:
<?php
$html = '<p>ACME’s 27” 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 сущностей.
Я предполагаю, что для фрагмента документа или отдельного узла кодирование считается менее важным, чем для полный документ.