W3docs

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 sollte SimpleXML oder DOMDocument bevorzugt 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 mit xml_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 World

xml_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 XML

Elementnamen 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 $parser und $data; ein erforderlicher $length-Parameter verursacht einen ArgumentCountError.
  • 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.

Übungen

Übung
Was macht die Funktion 'xml_set_character_data_handler()' in PHP?
Was macht die Funktion 'xml_set_character_data_handler()' in PHP?
Was this page helpful?