Unicode

Dank der Osterweiterung der EU werden jetzt immer mehr Homepages in mehreren Sprachen angeboten. Hierfür bietet HTML an, den Zeichensatz im Kopf zu definieren. Um alle Zeichensätze darstellen zu können, empfiehlt es sich UTF-8 zu nehmen. Das würde dann wie folgt aussehen:

  1. <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">

Bis jetzt war es noch nichts Weltbewegendes und man kann es überall wie zum Beispiel auf SelfHMTL nachlesen. Das Problem, welches ich mit den ganzen Zeichensätzen hatte, war, dass mir die Daten im Unicode-Format vorlagen und in eine MySQL-Datenbank geschrieben werden mussten, die kein Unicode versteht.

Zu Beginn muss man ersteinmal den Unterschied zwischen Unicode und UTF-8 verstehen, da beide Systeme das gleiche darstellen können, dies aber auf sehr unterschiedlichem Wege machen.
Unicode (Version 1): Hier werden die Zeichen immer mit 2 Bytes geschrieben und am Anfang der Textdatei stehen zwei Bytes (FF FE), die festhalten, dass es sich um eine Unicode-Datei handelt.
UTF-8: Bei UTF-8 verbrauchen die Zeichen unterschiedlich viele Bytes. Für HTML gibt es auch extra Entitys, damit man Zeichen darstellen kann, die man durch die Tastatur nicht tippen kann.

Hat man diesen Unterschied ersteinmal erfasst, dann ist der Rest eigentlich relativ simpel. Man muss nur noch aus dem 2-Byte-Zeichen ein Zeichen machen, dass auf einer Homepage dargestellt werden kann.

Anhand eines kleinen Beispiels möchte ich die "Umrechnung" erläutern:
Als Zeichen habe ich das Zeichen Ƃ genommen. Es entstammt dem Latin extended-B-Satz. In der Unicodedatei wird dieses Zeichen mit den Bytes 82 und 01 dargestellt. Um diese zwei Bytes nach HTML zu konvertieren, müssen wir zum einen die Reihenfolge der Bytes tauschen (82 01 => 01 82) und diesen Wert dann in eine Dezimalzahl umwandeln. Dadurch erhalten wir einen Zahlenwert mit dem wir in HTML auch etwas anfangen können. Aus der 01 82 wird eine 386. Damit HTML diesen Wert jetzt als ein Zeichen interpretieren kann, muss man noch das Kaufmanns-Und und die Raute davor stellen und dahinter mit einem Semikolon abschließen. Dies würde am Beispiel wie folgt aussehen:

&#386;

Um von einem HTML-konformen Ausdruck in Unicode umzuwandeln, muss der oben bechriebene Weg einfach nur Rückwärts gegangen werden. Allerdings muss hierfür beachten, dass man Zahlen nicht zu früh umwandelt, da diese in UTF-8 ja die anderen Zeichen darstellen sollen und man sich somit das eigentliche Zeichen zerhaut.

Soviel zur Theorie. Jetzt muss das ganze noch mit einer Sprache umgesetzt werden, die dazu in der Lage ist. Ich habe hierfür PHP benutzt.

  1. function unicodetoutf8($string) {
  2.    // Latin 1
  3.    $string = str_replace("\xFF\xFE", '', $string); // Unicodeeintrag entfernen
  4.  
  5.    $string = str_replace("\x0D\x00\x0A\x00", '<br />', $string); // konvertiert \r\n zu <br />
  6.    $string = str_replace("\x20\x00", ' ', $string);
  7.    $string = str_replace("\x21\x00", '!', $string);
  8.  
  9.    $string = str_replace("\x22\x00", '"', $string);
  10.    $string = str_replace("\x23\x00", '#', $string);
  11.    $string = str_replace("\x24\x00", '$', $string);
  12.    $string = str_replace("\x25\x00", '%', $string);
  13.  
  14.    $string = str_replace("\x26\x00", '&', $string);
  15.    $string = str_replace("\x27\x00", '\'', $string);
  16.    $string = str_replace("\x28\x00", '(', $string);
  17.    // usw usf
  18.  
  19. }

Das Prinzip der Funktion ist recht simpel. Der Funktion wird ein Unicodestring übergeben und dann soll sie alle Unicode-Zeichen durch entsprechende Zeichen für HTML umwandeln. Für die Umwandlung wird str_replace benutzt. Im ersten Argument werden die Hex-Werte reingeschrieben. Wichtig hierbei ist, dass man ein \x davor schreibt, damit die nachfolgenden Zeichen auch als Hexwert interpretiert werden können.

Das Gesamte funktioniert wunderbar, wenn die Quelle nicht zu groß ist. Ich habe festgestellt, dass, wenn die Unicode-Quelledatei größer als 400KB ist, PHP Problem damit hat, dieses umzuwandeln. Es kommt dann irgendwann zu einem überfüllten Speicher und dann geht gar nichts mehr. Ich habe bis jetzt leider keine Lösung parat :-(

Die Umwandlung von UTF-8 nach Unicode geht dann wie oben nur dass die beiden ersten Argumente vertauscht werden.

Jetzt muss man das ganze nur noch in eine Klasse verpacken und dann kann man es wunderbar einsetzen. Solltet ihr Verbesserungsvorschläge (Speicherproblem zum Beispiel) haben, wäre ich euch sehr dankbar, wenn ihr sie mir mitteilen würdet.

Die Hex-Werte für die Unicode-Datei kann man unter http://www.w3.org/TR/MathML2/chapter6.html (unten) finden

Mit PHP 6.0 soll diese Unicode-Unterstützung direkt in PHP implementiert werden, sodass man sich diesen Spagat mit eigenen Klassen sparen kann.