У меня проблемы с кодировкой символов. Я упростил этот сценарий ниже:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> </head> <body> <?php $string = 'Stans'; echo $string.'<br><br>'; // Stan's echo html_entity_decode($string).'<br><br>'; // Stan's echo html_entity_decode($string, ENT_QUOTES, 'UTF-8'); // Stans ?> </body> </html>
Я хотел бы использовать последнее echo
. Однако он удаляет '
почему?
Я пробовал все три варианта ENT_COMPAT
, ENT_QUOTES
, ENT_NOQUOTES
и он удаляет '
во всех случаях».
Проблема в том, что ’
декодирует символ Unicode U + 0092, UTF-8 C2 92
, известный как ЧАСТНОЕ ИСПОЛЬЗОВАНИЕ ДВА:
$ php test.php | xxd 0000000: 5374 616e c292 73 Stan..s
То есть, это не расшифровывается до обычного апострофа.
html_entity_decode($string)
работает, потому что он фактически не декодирует объект, так как целевая кодировка по умолчанию – latin-1, которая не может представлять этот символ. Если вы укажете UTF-8 в качестве целевой кодировки, объект фактически декодируется.
Целью этого объекта является кодировка Windows-1252:
echo iconv('cp1252', 'UTF-8', html_entity_decode('Stan’s', ENT_QUOTES, 'cp1252')); Stan's
Цитата Википедии :
Числовые ссылки всегда относятся к кодам Unicode, независимо от кодировки страницы. Запрещается использование числовых ссылок, которые ссылаются на постоянно неопределенные символы и управляющие символы, за исключением символов перевода строки, табуляции и возврата каретки. То есть символы в шестнадцатеричных диапазонах 00-08, 0B-0C, 0E-1F, 7F и 80-9F не могут использоваться в HTML-документе, даже не по ссылке, поэтому
™
, например, не допускается. Однако для обратной совместимости с ранними авторами HTML и браузерами, которые игнорировали это ограничение, необработанные символы и числовые ссылки на символы в диапазоне 80-9F интерпретируются некоторыми браузерами как представляющие символы, сопоставленные байтам 80-9F в кодировке Windows-1252.
Таким образом, вы имеете дело с устаревшими объектами HTML здесь, что, по-видимому, PHP не работает так же, как это делают «некоторые» браузеры. Вы можете проверить, находятся ли декодированные объекты в указанном выше диапазоне, что вы перекодируете / сокращаете их в Windows-1252, а затем конвертируете в UTF-8. Или попросите своих пользователей передать действительный HTML.
Эта функция должна обрабатывать как устаревшие, так и обычные объекты HTML:
function legacy_html_entity_decode($str, $quotes = ENT_QUOTES, $charset = 'UTF-8') { return preg_replace_callback('/&#(\d+);/', function ($m) use ($quotes, $charset) { if (0x80 <= $m[1] && $m[1] <= 0x9F) { return iconv('cp1252', $charset, html_entity_decode($m[0], $quotes, 'cp1252')); } return html_entity_decode($m[0], $quotes, $charset); }, $str); }