DomDocument и специальные символы
Это мой код:
$oDom = new DOMDocument();
$oDom->loadHTML("èàéìòù");
echo $oDom->saveHTML();
Это результат:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>èà éìòù</p></body></html>
Я хочу этот вывод:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><p>èàéìòù</p></body></html>
Я пробовал с...
$oDom = new DomDocument('4.0', 'UTF-8');
или с 1.0 и другими вещами, но ничего.
Другое дело... Есть способ получить тот же нетронутый HTML? Например, с этим html во входе <p>hello!</p>
получить тот же вывод <p>hello!</p>
используя DOMDocument только для синтаксического анализа DOM и выполнения некоторых подстановок внутри тегов.
Ответы
Ответ 1
Решение:
$oDom = new DOMDocument();
$oDom->encoding = 'utf-8';
$oDom->loadHTML( utf8_decode( $sString ) ); // important!
$sHtml = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
$sHtml .= $oDom->saveHTML( $oDom->documentElement ); // important!
Метод saveHTML()
работает по-разному, указав узел. Вы можете использовать главный узел ($oDom->documentElement
), добавляя нужный !DOCTYPE
вручную. Еще одна важная вещь - utf8_decode()
. Все атрибуты и другие методы класса DOMDocument
, в моем случае, не дают желаемого результата.
Ответ 2
Попробуйте установить тип кодировки после загрузки HTML.
$dom = new DOMDocument();
$dom->loadHTML($data);
$dom->encoding = 'utf-8';
echo $dom->saveHTML();
Другой путь
Ответ 3
Проблема, как представляется, известна, согласно комментариям пользователя на странице руководства на php.net. Предлагаемые решения включают
<meta http-equiv="content-type" content="text/html; charset=utf-8">
в документе перед тем, как вы поместите строки с символами, отличными от ASCII.
Еще один хак предлагает положить
<?xml encoding="UTF-8">
как первый текст в документе, а затем удалить его в конце.
Неприятный материал. Пахнет мне как ошибка.
Ответ 4
Таким образом:
/**
* @param string $text
* @return DOMDocument
*/
private function buildDocument($text)
{
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML('<meta http-equiv="Content-Type" content="text/html; charset=utf-8">' . $text);
libxml_use_internal_errors(false);
return $dom;
}
Ответ 5
Похоже, вам просто нужно установить substituteEntities, когда вы создаете объект DOMDocument.
Ответ 6
Я не знаю, почему отмеченный ответ не сработал для моей проблемы. Но этот сделал.
ref: https://www.php.net/manual/en/class.domdocument.php
<?php
// checks if the content we're receiving isn't empty, to avoid the warning
if ( empty( $content ) ) {
return false;
}
// converts all special characters to utf-8
$content = mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8');
// creating new document
$doc = new DOMDocument('1.0', 'utf-8');
//turning off some errors
libxml_use_internal_errors(true);
// it loads the content without adding enclosing html/body tags and also the doctype declaration
$doc->LoadHTML($content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
// do whatever you want to do with this code now
?>