form4 GmbH & Co.KG - Innovative Softwareentwicklung

UTF-8-Zeichen in Nicht-UTF-8-Seiten darstellen
SuchenSitemap

UTF-8-Zeichen in Nicht-UTF-8-Seiten darstellen

Hajo Passon, 29.05.2009

Sollen Inhalte aus verschiedenen Quellen in HTML-Seiten eingebunden werden, tauchen immer wieder Probleme mit den unterschiedlichen Character-Encodings und deren Umwandlung in einander auf. Diese Probleme sind insbesondere mit PHP eher schwer zu handhaben, da die eingebundenen Encoding-Funktionen entweder so voraussetzungsreich sind, dass man keine Chance hat sie bei den verschiedenen Hostern sicher zum Laufen zu bringen (z.B. iconv und recode), oder schlicht etwas anderes tun, als sich nur um das Encoding zu kümmern.

Wenn aus der Datenquelle UTF-8-encodierte Strings kommen (und das sollte bei neuen Anwendungen der Fall sein!) und HTML4 als Format der Datensenke verwendet wird, gibt es einen generischen Weg, UTF-8-Zeichen in Numerische HTML-Entitäten umzurechnen.

Folgende Funktion macht genau das:
function utf8ToHtml4($string) {
$length = strlen($string);
$returnValue = '';
$i = 0;
while($i < $length) {
$tok = substr($string, $i, 1);
if((ord($tok) & 1<<7) msb="" nicht="" gesetzt=""> ASCII char
$returnValue .= $tok;
$i += 1;
} else if ((ord($tok) & 1<<6) == 0) {
// Bit 7 nicht gesetzt : Folge-Byte in UTF-8-Zeichen.
// Das ist ein Fehler.
$i += 1;
} else if ((ord($tok) & 1<<5) == 0) {
// Bit 6 nicht gesetzt : 2 Byte UTF-8-Zeichen
$tok2 = substr($string, $i + 1, 1);
$returnValue .= '&#' .
(((ord($tok) - 192) * 64) + (ord($tok2) - 128)) . ';';
$i += 2;
} else if ((ord($tok) & 1<<4) == 0) {
// Bit 5 nicht gesetzt : 3 Byte UTF-8 Zeichen
$tok2 = substr($string, $i + 1, 1);
$tok3 = substr($string, $i + 2, 1);
$returnValue .= '&#' .
((((ord($tok) - 224) * 64) + (ord($tok2) - 128)) * 64 +
(ord($tok3) - 128)) . ';';
$i += 3;
} else if ((ord($tok) & 1<<3) == 0) {
// Bit 4 nicht gesetzt : 4 Byte UTF-8 Zeichen
$tok2 = substr($string, $i + 1, 1);
$tok3 = substr($string, $i + 2, 1);
$tok4 = substr($string, $i + 3, 1);
$returnValue .= '&#' .
(((((ord($tok) - 240) * 64) + (ord($tok2) - 128))
* 64 + (ord($tok3) - 128))
* 64 + (ord($tok4) - 128)) . ';';
$i += 4;
} else {
$i += 1;
}
}
return $returnValue;
}

Warun das ganze überhaupt funktioniert erklärt sich aus dem Aufbau von UTF-8-Zeichen. Den kann man - bei Bedarf - sehr schön bei Wikipedia nachlesen.

Der obige Code besteht im wesentlichen daraus zu erkennen, wie viele Bytes zu einem Zeichen gehören und aus diesen Bytes die bedeutungstragenden Bits zu extrahieren, die dann zu einer Zahl - dem numerischen Code des Zeichens - zusammengeklebt werden.

Das Schöne an der hier gezeigten Lösung: Der produzierte HTML-Code funktioniert in Seiten mit unterschiedlichem Encoding.