HTML-Entities mit PHP zu XML-Entities wandeln

Hallo liebe PHP-Freunde da draußen! Es muss doch eine Möglichkeit geben, einen Text mit lauter sprechenden HTML-Entities in einen XML-kompatiblen Text umzuwandeln, der nur noch numerische Unicode-Entities enthält. Etwa so:

Ich gähnte und schoß dabei über das Ziel hinaus und kaufte mir für € 500,– einen Hammer.

muss so aussehen:

Ich g& #x00E4;hnte und scho& #x00DF;
dabei & #x00FC;ber das Ziel hinaus und kaufte mir
f& #x00FC;r & #x20AC; 500,& #x2013; einen Hammer.

(Natürlich ohne die Leerzeichen, die sind wegen Textile)

Hintergrund: Der Feed von Loudblog muss nun endlich UTF-8 werden und korrektes XML obendrein. Da jedoch aus bestimmten Gründen die Inhalte in der Datenbank größtenteils mit HTML-Entities gespeichert sind, muss man das umwandeln, da XML lediglich normale, unmaskierte Unicode-Zeichen versteht, oder aber hexadezimale Entities.

Folgendes hat nicht geklappt:

  • Die Funktion html_entitiy_decode ist Schrott, zumindest in PHP 4.
  • Wilde RegEx-Erkennungsspielchen und -umrechnereien haben auch nicht geklappt.

Gibt es eine saubere Lösung für PHP 4 (Gerne auch als externe Funktion/Klasse)?

20 Kommentare

e-sven

html_entity_decode ist schonmal der richtige Ansatz. Leider unterstützt das erst ab PHP5 Multibyte (sprich UTF8). Der einfachste Ansatz wäre jetzt das ganze erstmal in ISO umzuwandeln und danach mit utf8_encode nachzubehandeln. (Ohne Gewähr.)

Markus Wulftange

Wenn du UTF-8 verwendest, sind Zeichenreferenzen doch gar nicht mehr nötig. Daher mein Vorschlag:
$string = strtr($string, array_map('utf8_encode', array_flip(get_html_translation_table(HTML_ENTITIES))));

Gerrit

Danke, ihr beiden: Die beiden Lösungen sind von Ergebnis identisch :-) Schon mal nicht übel, wir sind jetzt einen Schritt weiter. Problem ist nun, dass offenbar nicht alle HTML4-Entities in der Translation-Tabelle enthalten sind. Zum Beispiel das wunderbare – udn auch sein Konterpart $#8221;. Wisst Ihr, ob es eine vollständige Ergänzungs-Tabelle gibt, mit der ich die Standard-Tabelle von PHP pimpen kann?

Max

Bei den Kommentaren von php.net findet sich eine ganze Menge zu dem Thema (Einfach mal Volltext nach XML suchen). Ich habe das Ganze aber nicht getestet. Es scheint mir trotzdem vielversprechend zu sein!

Gerrit

Die Kommentare bei php.net haben bei mir eher einen zweifelhaften Ruf … Aber vielleicht muss ich das tatsächlich nochmal komplett durchgehen.

Martin

Das dürfte vollständig sein. Generiert mit einem regulären Ausdruck und ein paar Schleifen aus den Entity-Dateien zu HTML 4.

Jonis

soll jetzt kein »klugscheiß«kommentar werden, aber: in die datenbank immer unveränderte texte (also keine entities), die umwandlung dann bei der ausgabe, erspart viele probleme. :)

Jonis

argh!

Gerrit

@Jonis: Eigentlich sollte man zusätzlich den Originaltext in der DB speichern, richtig. Nur hatte ich Schiss, UTF-8 in MySQL zu verwenden, weil das zu Problemen führen kann. Dachte ich. Eine Umwandlung erst beim Rendern ist unnötiges Gift für die Performance, oder?

Jonis

Leider ist die Dokumentation die ich zum aufbau einer Seite mit UTF-8 gefunden jedes mal mit einem »probier’ das« oder »vielleicht geht es so« verbunden gewesen. momentan baue ich eine 2/3 Sprachige Internetseite mit dem Paradebeispiel für UTF-8: nicht lateinische Zeichen, also kein ISOBLABLA. Wichtig ist eigentlich nur ein paar Dinge zu beachten:
1. Das richtige Charset im Meta-Content-Type der Seite, ggf. auch beim akzeptierten Inhalt eines Formulars
2. Beim Eintragen in die DB -> utf8_encode, beim ausgeben -> utf8_decode
3. Checken ob der Server ein Default-Charset für Inhalte vorgegeben hat. Lässt sich allerdings einfach mit einer HTACCESS-Angabe regeln.

Zu deiner Performance-Frage:
Ich regel das alles innerhalb einer Funktion die ich generell IMMER anwende bevor ich einen Inhalt in die DB eintrage. Schließlich soll weder ein schädlicher Inhalt (Anführungs-/Zollzeichen, SQL-Injection, ...) noch irgendetwas anderes in die DB was nicht dahin gehört. Bei der Ausgabe der Inhalte gibt es bei mir ein str_replace und ein preg_replace die sich um verschiedene Zeichen kümmern (z.B. Typo oder BBCode) ... aber da gibt es natürlich noch einiges mehr das abgecheckt werden muss ;-) Um jetzt aber nicht die Performance leiden zu lassen kannst du die replace-Funktionen mit Arrays füttern, allemal besser als mehrere replaces nacheinander.

Zum Schluss bleibt nur noch das man bei mysql wohl einstellen kann welcher Zeichensatz verwendet werden soll, ich aber gelesen habe, dass das wohl unerheblich ist.

Ich hab glück, mein Hoster sitzt in den US und hat UTF8 als Standard eingestellt.

:-)

Gerrit

Leider kann ich bei Loudblog keine Annahmen über den Server und die Datenbank machen, weil es eben eine Sofwtare zum Herunterladen und selber installieren ist und kein Webservice!

Gerrit

@Martin: Heißen Dank, das war exakt das, was ich gesucht hatte! jetzt klappt alles ganz hervorragend: Siehe hier

Jonis

ähm entschuldigung? was hat mein text mit einem webservice zutun? schön das du eine lösung gefunden hast, werde mir in zukunft die mühe sparen.

Gerrit

@Jonis: Mein Kommentar bezog sich nur nur auf deinen letzten Satz: Ich hab glück, mein Hoster sitzt in den US und hat UTF8 als Standard eingestellt. Das ist eben etwas, was ich bei Loudblog nicht voraussetzen kann. Wenn Loudblog eine zentral gehostete Applikation wie ODEO wäre, dann wäre das alles ein kleineres Problem.

(Ich habe wohl Webservice mit zentral gehosteter Web-Applikation verwechselt. Sorry für das!)

Jens

Gerit guck auch mal in die aktuelle c’t zu dem Thema, die beschäftigen sich grade mit Charsets auf Webseiten. Ein paar Vorraussetzungen musst du für den Webserver schon machen, denn der kann das Default-Charset immer überschreiben.
Ansonsten stell den Feed auf Atom um und definiere eine CDATA. Da solltest du utf-8 ohne Umwandlung reinschreiben können.

Gerrit

Nun, ein valider Podcast-Feed muss aber RSS2.0 sein, soweit ich weiß ...

Marc

Auch wenn du dein Problem anscheinend schon gelöst hast, ist Annes Entity Converter sicherlich auch eine Erwähnung wert …

Gabriel

»Wenn du UTF-8 verwendest, sind Zeichenreferenzen doch gar nicht mehr nötig«
Oh mann, manchmal sieht man echt den Wald vor Bäumen nicht … Danke.

Kommentar verfassen