Comment puis-je convertir des références de caractères HTML (& # x5E3;) en UTF-8 ordinaire?
-
01-10-2019 - |
Question
J'ai des sites Web hébreux qui contient des références de personnages comme: נוף
Je ne peux afficher ces lettres que si j'enregistre le fichier sous .html et affiche dans le codage UTF-8.
Si j'essaie de l'ouvrir en tant que fichier texte régulier, le codage UTF-8 n'affiche pas la sortie appropriée.
J'ai remarqué que si j'ouvre un éditeur de texte et que j'écris l'hébreu dans UTF-8, chaque personnage prend deux octets pas de 4 octets dans cet exemple (ו
)
Des idées s'il s'agit de l'UTF-16 ou de tout autre type de représentation UTF des lettres?
Comment puis-je le convertir en lettres normales si possible?
En utilisant la dernière version PHP.
La solution
Ce sont Références de caractère qui se réfèrent au caractère dans ISO 10646 en spécifiant le point de code de ce caractère en décimal (&#n;
) ou hexadécimal (&#xn;
) notation.
Vous pouvez utiliser html_entity_decode
qui décode ces références de caractère ainsi que les références d'entité pour entités définies pour HTML 4, donc d'autres références comme <
, >
, &
sera également décodé:
$str = html_entity_decode($str, ENT_NOQUOTES, 'UTF-8');
Si vous souhaitez simplement décoder les références de caractères numériques, vous pouvez l'utiliser:
function html_dereference($match) {
if (strtolower($match[1][0]) === 'x') {
$codepoint = intval(substr($match[1], 1), 16);
} else {
$codepoint = intval($match[1], 10);
}
return mb_convert_encoding(pack('N', $codepoint), 'UTF-8', 'UTF-32BE');
}
$str = preg_replace_callback('/&#(x[0-9a-f]+|[0-9]+);/i', 'html_dereference', $str);
Comme Yurikolovsky et trente-trente ont souligné une autre question, il semble que les fournisseurs de navigateurs se soient `` silencieusement '' d'accord sur quelque chose concernant la cartographie des références de caractère, qui diffère de la spécification et est assez sans papiers.
Il semble y avoir des références de personnages qui seraient normalement mappées sur le Supplément latin 1 Mais cela est en fait mappé sur différents personnages. Cela est dû au mappage qui préfère résulter de la cartographie des caractères de Windows-1252 au lieu de l'ISO 8859-1, sur lequel le jeu de caractères Unicode est construit. Jukka Korpela a écrit un Article étendu sur ce sujet.
Voici maintenant une extension de la fonction mentionnée ci-dessus qui gère cette bizarrerie:
function html_character_reference_decode($string, $encoding='UTF-8', $fixMappingBug=true) {
$deref = function($match) use ($encoding, $fixMappingBug) {
if (strtolower($match[1][0]) === "x") {
$codepoint = intval(substr($match[1], 1), 16);
} else {
$codepoint = intval($match[1], 10);
}
// @see http://www.cs.tut.fi/~jkorpela/www/windows-chars.html
if ($fixMappingBug && $codepoint >= 130 && $codepoint <= 159) {
$mapping = array(
8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249,
338, 141, 142, 143, 144, 8216, 8217, 8220, 8221, 8226,
8211, 8212, 732, 8482, 353, 8250, 339, 157, 158, 376);
$codepoint = $mapping[$codepoint-130];
}
return mb_convert_encoding(pack("N", $codepoint), $encoding, "UTF-32BE");
};
return preg_replace_callback('/&#(x[0-9a-f]+|[0-9]+);/i', $deref, $string);
}
Si fonctions anonymes ne sont pas disponibles (introduits avec 5.3.0), vous pouvez également utiliser create_function
:
$deref = create_function('$match', '
$encoding = '.var_export($encoding, true).';
$fixMappingBug = '.var_export($fixMappingBug, true).';
if (strtolower($match[1][0]) === "x") {
$codepoint = intval(substr($match[1], 1), 16);
} else {
$codepoint = intval($match[1], 10);
}
// @see http://www.cs.tut.fi/~jkorpela/www/windows-chars.html
if ($fixMappingBug && $codepoint >= 130 && $codepoint <= 159) {
$mapping = array(
8218, 402, 8222, 8230, 8224, 8225, 710, 8240, 352, 8249,
338, 141, 142, 143, 144, 8216, 8217, 8220, 8221, 8226,
8211, 8212, 732, 8482, 353, 8250, 339, 157, 158, 376);
$codepoint = $mapping[$codepoint-130];
}
return mb_convert_encoding(pack("N", $codepoint), $encoding, "UTF-32BE");
');
Voici une autre fonction qui essaie de se conformer au Comportement de HTML 5:
function html5_decode($string, $flags=ENT_COMPAT, $charset='UTF-8') {
$deref = function($match) use ($flags, $charset) {
if ($match[1][0] === '#') {
if (strtolower($match[1][0]) === '#') {
$codepoint = intval(substr($match[1], 2), 16);
} else {
$codepoint = intval(substr($match[1], 1), 10);
}
// HTML 5 specific behavior
// @see http://dev.w3.org/html5/spec/tokenization.html#tokenizing-character-references
// handle Windows-1252 mismapping
// @see http://www.cs.tut.fi/~jkorpela/www/windows-chars.html
// @see http://dev.w3.org/html5/spec/tokenization.html#table-charref-overrides
$overrides = array(
0x00=>0xFFFD,0x80=>0x20AC,0x82=>0x201A,0x83=>0x0192,0x84=>0x201E,
0x85=>0x2026,0x86=>0x2020,0x87=>0x2021,0x88=>0x02C6,0x89=>0x2030,
0x8A=>0x0160,0x8B=>0x2039,0x8C=>0x0152,0x8E=>0x017D,0x91=>0x2018,
0x92=>0x2019,0x93=>0x201C,0x94=>0x201D,0x95=>0x2022,0x96=>0x2013,
0x97=>0x2014,0x98=>0x02DC,0x99=>0x2122,0x9A=>0x0161,0x9B=>0x203A,
0x9C=>0x0153,0x9E=>0x017E,0x9F=>0x0178);
if (isset($windows1252Mapping[$codepoint])) {
$codepoint = $windows1252Mapping[$codepoint];
}
if (($codepoint >= 0xD800 && $codepoint <= 0xDFFF) || $codepoint > 0x10FFFF) {
$codepoint = 0xFFFD;
}
if (($codepoint >= 0x0001 && $codepoint <= 0x0008) ||
($codepoint >= 0x000E && $codepoint <= 0x001F) ||
($codepoint >= 0x007F && $codepoint <= 0x009F) ||
($codepoint >= 0xFDD0 && $codepoint <= 0xFDEF) ||
in_array($codepoint, array(
0x000B, 0xFFFE, 0xFFFF, 0x1FFFE, 0x1FFFF, 0x2FFFE, 0x2FFFF,
0x3FFFE, 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, 0x5FFFF, 0x6FFFE,
0x6FFFF, 0x7FFFE, 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, 0x9FFFF,
0xAFFFE, 0xAFFFF, 0xBFFFE, 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE,
0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, 0xFFFFF, 0x10FFFE, 0x10FFFF))) {
$codepoint = 0xFFFD;
}
return mb_convert_encoding(pack("N", $codepoint), $charset, "UTF-32BE");
} else {
return html_entity_decode($match[0], $flags, $charset);
}
};
return preg_replace_callback('/&(#(?:x[0-9a-f]+|[0-9]+)|[A-Za-z0-9]+);/i', $deref, $string);
}
J'ai également remarqué que dans PHP 5.4.0 le html_entity_decode
fonction a été ajouté un autre drapeau nommé Ent_html5 Pour le comportement HTML 5.
Autres conseils
Ce sont XML Référence du personnages. Vous voulez les décoder en utilisant html_entity_decode()
:
$string = html_entity_decode($string, ENT_QUOTES, 'UTF-8');
Pour plus d'informations, vous pouvez rechercher à Google l'entité en question. Voir ces quelques exemples: