Intereting Posts
simplexml_load_file – избыточный элемент с пустым значением преобразуется в новый объект SimpleXMLElement Поиск и замена регулярных выражений во всех строках таблицы с помощью Laurvel 4's Fluent or Eloquent Ошибка синтаксиса, неожиданный T_CONSTANT_ENCAPSED_STRING в PHP php: сортировать в алфавитном порядке многомерный массив по его ключу? Использование PHP для минимизации Javascript / HTML / CSS в условиях STRING Как перенаправить ошибки, сгенерированные в Bootstrap, на ErrorController? PHP Проверьте, содержит ли строка письмо Является ли мой IP-адрес в моей базе данных, если так найти временную метку mysqli error – bind_param: количество переменных не совпадает Как использовать AccessDecisionManager в Symfony2 для авторизации произвольных пользователей? Как добавить бэкэнд Java на существующий сайт PHP без добавления сервера tomcat для Java Bridge? PHP: Какова сложность (т. Е. O (1), O (n)] функции «count»? PHP-шифрование с несколькими ключами Проблема сортировки массива в PHP PHP-скрипт для импорта данных csv в mysql

PHP DomDocument не может обрабатывать символы utf-8 (☆)

Вебсервер обслуживает ответы с помощью кодировки utf-8, все файлы сохраняются с помощью кодировки utf-8, и все, что мне известно об установке, было установлено на кодировку utf-8.

Вот быстрая программа, чтобы проверить, работает ли выход:

<?php $html = <<<HTML <!doctype html> <html> <head> <meta charset="utf-8"> <title>Test!</title> </head> <body> <h1>☆ Hello ☆ World ☆</h1> </body> </html> HTML; $dom = new DomDocument("1.0", "utf-8"); $dom->loadHTML($html); header("Content-Type: text/html; charset=utf-8"); echo($dom->saveHTML()); 

Выходной сигнал программы:

 <!DOCTYPE html> <html><head><meta charset="utf-8"><title>Test!</title></head><body> <h1>&acirc;˜† Hello &acirc;˜† World &acirc;˜†</h1> </body></html> 

Который отображает как:

â~ † Hello â~ † World â~ †


Что я могу делать неправильно? Насколько более конкретным я должен сказать, чтобы DomDocument правильно обрабатывал utf-8?

Related of "PHP DomDocument не может обрабатывать символы utf-8 (☆)"

DOMDocument::loadHTML() ожидает строку HTML.

HTML использует ISO-8859-1 кодировку (ISO Latin Alphabet № 1) по умолчанию для своих спецификаций. Это происходит дольше, см. 6.1. Набор символов HTML-документа . На самом деле это более стандартная поддержка Windows-1252 в общих веб-браузерах.

Я возвращаюсь так далеко, потому что PHP DOMDocument основан на libxml и приносит HTMLparser, который предназначен для HTML 4.0.

Я бы сказал, что можно с уверенностью предположить, что вы можете загрузить кодированную по ISO-8859-1 строку.

Ваша строка кодируется UTF-8 . Поверните все символы выше 127 / h7F в HTML-объекты, и все в порядке. Если вы не хотите делать это самостоятельно, это то, что mb_convert_encoding с целевой кодировкой HTML-ENTITIES делает:

  • Те персонажи, у которых есть именованные объекты, получат именованный entitiy. € -> &euro;
  • Другие получают свой цифровой (десятичный) объект, например ☆ -> &#9734;

Ниже приведен пример кода, который делает прогресс более заметным с помощью функции обратного вызова:

 $html = preg_replace_callback('/[\x{80}-\x{10FFFF}]/u', function($match) { list($utf8) = $match; $entity = mb_convert_encoding($utf8, 'HTML-ENTITIES', 'UTF-8'); printf("%s -> %s\n", $utf8, $entity); return $entity; }, $html); 

Эти примерные выходы для вашей строки:

 ☆ -> &#9734; ☆ -> &#9734; ☆ -> &#9734; 

Во всяком случае, это просто для того, чтобы глубже заглянуть в вашу строку. Вы хотите, чтобы он был преобразован в loadHTML с кодировкой, с loadHTML может работать loadHTML . Это можно сделать, преобразовывая все за пределами US-ASCII в HTML-объекты:

 $us_ascii = mb_convert_encoding($utf_8, 'HTML-ENTITIES', 'UTF-8'); 

Позаботьтесь о том, чтобы ваш вход был закодирован в кодировке UTF-8. Если у вас даже смешанные кодировки (что может случиться с некоторыми входами), mb_convert_encoding может обрабатывать только одну кодировку для каждой строки. Я уже изложил выше, как более конкретно выполнять замену строк с помощью регулярных выражений, поэтому теперь я оставляю более подробную информацию.

Другая альтернатива – это намек на кодировку. Это можно сделать в вашем случае, изменив документ и добавив

 <meta http-equiv="content-type" content="text/html; charset=utf-8"> 

который представляет собой Content-Type, определяющий кодировку. Это также лучшая практика для строк HTML, которые недоступны через веб-сервер (например, сохранены на диске или внутри строки, как в вашем примере). Обычно веб-сервер устанавливается как заголовок ответа.

Если вам не нравятся неуместные предупреждения, вы можете просто добавить их перед строкой:

 $dom = new DomDocument(); $dom->loadHTML('<meta http-equiv="content-type" content="text/html; charset=utf-8">'.$html); 

В спецификациях HTML 2.0 элементы, которые могут отображаться только в разделе <head> документа, будут автоматически размещены там. Вот что здесь происходит и здесь. Выход (довольно-печатный):

 <!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta charset="utf-8"> <title>Test!</title> </head> <body> <h1>☆ Hello ☆ World ☆</h1> </body> </html> 

У вас есть более быстрое исправление, после загрузки вашего html-документа в DOMDocument вы просто устанавливаете (или лучше упомянутый сброс) исходную кодировку. Вот пример кода:

 $dom = new DOMDocument(); $dom->loadHTML('<?xml encoding="UTF-8">' . $html); foreach ($dom->childNodes as $item) if ($item->nodeType == XML_PI_NODE) $dom->removeChild($item); $dom->encoding = 'UTF-8'; // reset original encoding 
 <?php header("Content-type: text/html; charset=utf-8"); $html = <<<HTML <!doctype html> <html> <head> <meta charset="utf-8"> <title>Test!</title> </head> <body> <h1>☆ Hello ☆ World ☆</h1> </body> </html> HTML; $html = mb_convert_encoding($html, 'HTML-ENTITIES', "UTF-8"); $dom = new DomDocument("1.0", "utf-8"); $dom->loadHTML($html); header("Content-Type: text/html; charset=utf-8"); echo($dom->saveHTML()); 

Вывод:

 <!DOCTYPE html> <html><head><meta charset="utf-8"><title>Test!</title></head><body> <h1>&#9734; Hello &#9734; World &#9734;</h1> </body></html>