xml_set_character_data_handler()
Die Funktion xml_set_character_data_handler() registriert eine benutzerdefinierte Callback-Funktion für Zeichendaten in einem XML-Parser.
Die Funktion xml_set_character_data_handler() registriert einen benutzerdefinierten Callback, den der XML-Parser jedes Mal aufruft, wenn er auf Zeichendaten trifft — also den Textinhalt, der zwischen XML-Tags steht. Sie gehört zur veralteten xml-Erweiterung, die den ereignisgesteuerten Expat-Parser kapselt, und ist damit Teil von PHPs streambasierter ("SAX-artiger") Parse-API — im Gegensatz zu den baumbasierten Ansätzen DOMDocument oder SimpleXML.
Diese Funktion kommt zum Einsatz, wenn Text innerhalb von Elementen beim Durchströmen des Dokuments erfasst oder transformiert werden soll — etwa um den Titel jedes <item> in einem RSS-Feed zu sammeln oder eine Transformation auf extrahiertem Text durchzuführen, ohne das gesamte Dokument im Speicher aufzubauen. Sie wird fast immer zusammen mit xml_set_element_handler() verwendet, das angibt, zu welchem Element der Text gehört.
Hinweis: Die
xml-Erweiterung gilt als veraltet. Für neuen Code sollteSimpleXMLoderDOMDocumentbevorzugt werden. Verwende diesen Handler, wenn du bestehende Expat-basierte Parser pflegst oder wirklich ereignisgesteuertes Streaming für sehr große Dokumente benötigst.
Syntax
xml_set_character_data_handler(XMLParser $parser, callable $handler): bool$parser— der mitxml_parser_create()erstellte Parser.$handler— der Callback, der für Zeichendaten aufgerufen wird. Übergib einen Funktionsnamen als string, eine Closure oder ein Array für einen Methoden-Callback. Die Übergabe eines leeren Strings""entfernt einen zuvor registrierten Handler.
Die Funktion gibt bei Erfolg true zurück.
Die Handler-Signatur
Dein Handler erhält zwei Argumente — den Parser und den Textabschnitt:
function handler(XMLParser $parser, string $data): voidÄltere Dokumentationen zeigen manchmal einen dritten Parameter $length, doch die Expat-basierte xml-Erweiterung übergibt diesen nicht. Ab PHP 8+ führt ein erforderlicher dritter Parameter zu einem ArgumentCountError — halte deinen Handler daher auf zwei Parameter (oder mache zusätzliche optional).
Verwendungsbeispiele
Beispiel 1: Ein minimaler Zeichendaten-Handler
Erstelle einen Parser, hänge einen Handler an und füttere ihn mit einem XML-String. Der Handler gibt den bereinigten Text aus, den er empfängt:
function handle_character_data($parser, $data) {
echo trim($data);
}
$xml_parser = xml_parser_create();
xml_set_character_data_handler($xml_parser, "handle_character_data");
$xml_data = '<root><item>Hello World</item></root>';
xml_parse($xml_parser, $xml_data, true);
xml_parser_free($xml_parser);
// Output: Hello Worldxml_parser_create() erstellt den Parser, xml_set_character_data_handler() verbindet den Callback, xml_parse() streamt die Daten (das abschließende true markiert es als letzten Chunk), und xml_parser_free() gibt den Parser frei.
Die Chunking-Tücke
Der Parser kann deinen Handler mehrfach für ein einzelnes Element aufrufen, und er wird auch für Whitespace zwischen Elementen ausgelöst. Er übergibt dir keinen ordentlichen String pro Element. Beobachte, was mit zwei Elementen und etwas Einrückung passiert:
function show($parser, $data) {
echo '[' . $data . "]\n";
}
$p = xml_parser_create();
xml_set_character_data_handler($p, "show");
$xml = '<root><item>Hello World</item> <item>Goodbye</item></root>';
xml_parse($p, $xml, true);
xml_parser_free($p);
// Output:
// [Hello World]
// [ ]
// [Goodbye]Der Leerzeichen-Abstand zwischen </item> und dem nächsten <item> löst einen eigenen Aufruf aus. Langer Text kann außerdem über mehrere Aufrufe verteilt ankommen. Deshalb solltest du die Daten immer puffern und erst handeln, wenn du weißt, dass das Element beendet ist.
Beispiel 2: Text mit einem Element-Handler puffern
Das zuverlässige Muster lautet: Puffer beim Start eines Elements zurücksetzen, jeden Zeichendaten-Chunk anhängen und den Puffer beim Ende des Elements auslesen. Deshalb wird xml_set_element_handler() fast immer zusammen mit dieser Funktion verwendet.
$buffer = '';
function start_element($parser, $name, $attrs) {
global $buffer;
$buffer = ''; // start collecting fresh text
}
function character_data($parser, $data) {
global $buffer;
$buffer .= $data; // chunks may arrive in pieces — append
}
function end_element($parser, $name) {
global $buffer;
$text = trim($buffer);
if ($text !== '') {
echo "$name: $text\n";
}
}
$parser = xml_parser_create();
xml_set_element_handler($parser, "start_element", "end_element");
xml_set_character_data_handler($parser, "character_data");
$xml = '<books><title>PHP Basics</title><title>Advanced XML</title></books>';
xml_parse($parser, $xml, true);
xml_parser_free($parser);
// Output:
// TITLE: PHP Basics
// TITLE: Advanced XMLElementnamen werden standardmäßig in Großbuchstaben umgewandelt, da der Parser die Groß-/Kleinschreibung angleicht. Um die ursprüngliche Schreibweise beizubehalten, deaktiviere die Groß-/Kleinschreibungsanpassung mit xml_parser_set_option():
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);Häufige Fallstricke
- Annahme eines einzelnen Aufrufs pro Element. Wie oben gezeigt, können Zeichendaten in mehreren Chunks geliefert werden; immer in einem Puffer akkumulieren.
- Nur-Whitespace-Aufrufe. Einrückungen und Zeilenumbrüche zwischen Tags lösen den Handler mit Leerzeichen aus. Diese vor dem Verarbeiten mit
trim()herausfiltern. - Ein dritter Handler-Parameter. Der Expat-Handler übergibt nur
$parserund$data; ein erforderlicher$length-Parameter verursacht einenArgumentCountError. - Handler nach dem Parsen registrieren. Alle Handler vor dem Aufruf von
xml_parse()registrieren, sonst sind die Ereignisse bereits vorbei.
Fazit
xml_set_character_data_handler() registriert einen Callback für den Text zwischen XML-Tags in PHPs veralteter, Expat-basierter xml-Erweiterung. Der Handler nimmt zwei Argumente entgegen — den Parser und den Daten-Chunk — und kann pro Element viele Male ausgelöst werden, auch für Whitespace. Der zuverlässige Ansatz ist daher, Text zu puffern und ihn beim Ende des Elements über xml_set_element_handler() zu verarbeiten. Für neue Projekte sollte man die modernen APIs SimpleXML oder DOMDocument bevorzugen; diese Funktion eignet sich für die Pflege bestehender Parser oder das Streaming sehr großer Dokumente.