Sven Rautenberg: Umlaute bei SAX

Beitrag lesen

Moin!

Dein Irrtum liegt darin, dass du glaubst, für den Textblock "Entität" würde dein Eventhandler für "character data" garantiert nur ein einziges Mal aufgerufen. Diese Annahme ist falsch. SAX könnte durchaus deinen Eventhandler für jeden Buchstaben einzeln aufrufen!

Was gibt das für einen Sinn? Wenn keine Umlaute vorkommen, erzeugt ein Textknoten doch auch nur ein Ereignis.

Ob das Vorgehen von SAX dir sinnvoll erscheint oder nicht, hat ja nichts damit zu tun, ob es den Entwicklern sinnvoll erschien. :) Mir erscheint es jedenfalls sehr sinnvoll, wenn man sich folgendes überlegt: SAX ist ein nichtspeichernder Parser, d.h. es wird kein XML-Dokumentenbaum aufgebaut, der im Speicher gehalten werden muß, sondern es werden alle Datenbruchstücke, die in SAX hineingegeben werden, direkt durch eventgesteuerte Aktionen sofort wieder rausgegeben. Denn es ist ja durchaus erlaubt und möglich, eine riesige XML-Datei in mundgerechte Stückchen á 1024 Byte in SAX einzuspeisen - bei solch einer Vorgehensweise ist nie garantiert, dass ein Textknoten immer vollständig übergeben wird, d.h. er kann auch in zwei Arbeitsgängen übergeben werden. SAX merkt sich nur, in welchem Zustand es nach dem Aufruf war, d.h. welche Tags geöffnet waren, und ob der Datenstrom ggf. mitten in einem Tag fortgesetzt wird, usw.

Das bedeutet aber, dass der auswertende Code eben damit rechnen muß, dass ein Textknoten in mehreren Schüben an den entsprechenden Eventhandler übergeben wird. Und offenbar passiert genau das auch ohne Unterbrechung des Datenstromes an den Stellen, wo sowas wie "Sonderzeichen" vorkommen.

Diese Vorgehensweise ist übrigens in der PHP-Doku auch beschrieben.

Link?

Ich habe nur das gefunden:

xml_set_character_data_handler()

Genau dort. :) http://de.php.net/manual/en/function.xml-set-character-data-handler.php

Character data is roughly all the non-markup contents of XML documents, including whitespace between tags. Note that the XML parser does not add or remove any whitespace, it is up to the application (you) to decide whether whitespace is significant.

Character data handler is called for every piece of a text in the XML document. It can be called multiple times inside each fragment (e.g. for non-ASCII strings).

"multiple times inside each fragment"...

Ohne Angaben zum Encoding wird der Browser "irgendwas" benutzten - in deinem Fall wohl ISO-8859-1.

Das hat in der Tat nichts mit der Zweiteiligkeit deines Parsergebnisses zu tun, aber mit der falschen Ausgabe des Umlauts schon.

Mag sein. Aber der Umlaut wird schon falsch im Array gespeichert. Das habe ich mit strlen() geprüft, was für den Umlaut zwei Zeichen statt eines ergibt. Oder wird ein UTF-8-Umlaut mit zwei Bytes gespeichert?

Ja natürlich. UTF-8 verwendet zwischen einem und vier Bytes pro Zeichen. Da PHP das Unicode in den normalen Stringfunktionen nicht "versteht", sondern nur byteorientiert arbeitet, gibt strlen() halt einen Wert zurück, den du nicht "erwartest", der aber hinsichtlich des Speicherbedarfs korrekt ist.

Die korrekte Stringlänge in ZEICHEN erhälst du, wenn du die Multibyte-Stringfunktionen verwendest. Die analoge Funktion zur herkömmlichen PHP-Stringfunktion erhälst du grundsätzlich, indem du "mb_" voranstellst, und damit dann in der Doku suchst. Für strlen z.B.: http://de.php.net/manual/en/function.mb-strlen.php.

- Sven Rautenberg

--
"Love your nation - respect the others."