UTF-8 с PHP DOMDocument loadHTML?

Рассмотрим этот пример, test.php :

 <?php $mystr = "<p>Hello, με काचं ça øy jeść</p>"; var_dump($mystr); $domdoc = new DOMDocument('1.0', 'utf-8'); //DOMDocument(); $domdoc->loadHTML($mystr); // already here corrupt UTF-8? var_dump($domdoc); ?> 

Если я запустил это с помощью PHP 5.5.9 (cli), я получаю в терминале:

 $ php test.php string(50) "<p>Hello, με काचं ça øy jeść</p>" object(DOMDocument)#1 (34) { ["doctype"]=> string(22) "(object value omitted)" ... ["actualEncoding"]=> NULL ["encoding"]=> NULL ["xmlEncoding"]=> NULL ... ["textContent"]=> string(70) "Hello, με à¤à¤¾à¤à¤ ça øy jeÅÄ" } 

Очевидно, исходная строка верна как UTF-8, но textContent DOMDocument неправильно закодирован.

Итак, как я могу получить контент как правильный UTF-8 в DOMDocument?

Solutions Collecting From Web of "UTF-8 с PHP DOMDocument loadHTML?"

Расширение DOM было построено на libxml2, чей HTML-парсер был создан для HTML 4 – по умолчанию кодировка для ISO-8859-1. Если он не встретит соответствующий метатег или декларацию XML, в противном случае loadHTML() будет считать контент ISO-8859-1.

Указание кодировки при создании DOMDocument по мере того, как вы не влияете на то, что делает синтаксический анализатор – загрузка HTML (или XML) заменяет как версию xml, так и кодировку, предоставленную вашим конструктором.


обходные:

Сначала используйте mb_convert_encoding() чтобы перевести что-либо выше диапазона ASCII в его эквивалент сущности html.

 $domdoc->loadHTML(mb_convert_encoding($mystr, 'HTML-ENTITIES', 'UTF-8')); 

Или взломайте метатег или объявление xml с указанием UTF-8.

 $domdoc->loadHTML('<meta http-equiv="Content-Type" content="charset=utf-8" />' . $mystr); 
 $domdoc->loadHTML('<?xml encoding="UTF-8">' . $mystr); 

Просто хотел опубликовать код OP с исправлениями, которые работают на меня:

 <?php $mystr = "<p>Hello, με काचं ça øy jeść</p>"; var_dump($mystr); $domdoc = new DOMDocument('1.0', 'UTF-8'); //DOMDocument(); $domdoc->substituteEntities = true; // no effect if hack is done //~ $domdoc->actualEncoding = 'UTF-8'; // Cannot write property $domdoc->encoding = 'UTF-8'; // no effect //~ $domdoc->xmlEncoding = 'UTF-8'; // Cannot write property //~ $domdoc->loadHTML($mystr); // already here corrupt UTF-8? //~ $domdoc->loadHTML(utf8_decode($mystr)); // this gets to <p>Hello, ?? ????? ça øy je??</p>, so not all //~ $domdoc->loadHTML( mb_convert_encoding($mystr, 'utf-8', mb_detect_encoding($mystr)) ); // no dice $domdoc->loadHTML('<?xml encoding="UTF-8">' . $mystr); // hack, http://php.net/manual/en/domdocument.loadhtml.php#95251 // dirty fix foreach ($domdoc->childNodes as $item) if ($item->nodeType == XML_PI_NODE) $domdoc->removeChild($item); // remove hack $domdoc->encoding = 'UTF-8'; // insert proper (sets all three) var_dump($domdoc); print $domdoc->saveXML(); // without ->encoding = 'UTF-8': Hello, &#x3BC;&#x3B5; &#xFEFF;&#x915;&#x93E;&#x91A;&#x902; else OK //~ print mb_convert_encoding($domdoc->saveXML(), 'UTF-8', 'HTML-ENTITIES'); // if without ->encoding = 'UTF-8', this is then OK: <p>Hello, με काचं ça øy jeść</p> ?> 

Эти результаты:

 $ php test.php string(50) "<p>Hello, με काचं ça øy jeść</p>" object(DOMDocument)#1 (34) { ["doctype"]=> string(22) "(object value omitted)" ... ["actualEncoding"]=> string(5) "UTF-8" ["encoding"]=> string(5) "UTF-8" ["xmlEncoding"]=> string(5) "UTF-8" ... ["textContent"]=> string(43) "Hello, με काचं ça øy jeść" } <?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"> <html><body><p>Hello, με काचं ça øy jeść</p></body></html> 

… все хорошо сейчас :)