xml_parse()
Die Funktion xml_parse() ist eine eingebaute PHP-Funktion zum Parsen von XML-Daten mit dem SAX-Parser-Ansatz.
Was ist xml_parse()?
Die Funktion xml_parse() ist eine eingebaute PHP-Funktion zum Parsen von XML-Daten. Sie gehört zur PHP-XML-Parser-Erweiterung und implementiert einen SAX-basierten (Simple API for XML) Streaming-Parser. Im Gegensatz zu baumbasierten Parsern verarbeitet sie XML sequenziell und löst Callback-Funktionen aus, sobald Elemente, Attribute und Zeichendaten auftreten. Dadurch ist sie sehr effizient beim Parsen großer XML-Dateien, ohne das gesamte Dokument in den Speicher laden zu müssen.
Die Funktion xml_parse() ist nützlich, wenn Sie XML-Daten in PHP verarbeiten müssen, zum Beispiel um Daten aus einer XML-Datei zu extrahieren, XML-Daten in ein anderes Format zu transformieren oder XML-Streams in Echtzeit zu verarbeiten.
Syntax
Die Syntax der Funktion xml_parse() lautet wie folgt:
xml_parse($parser, $data, $is_final = false): intParameter
$parser— das XML-Parser-Handle, das vonxml_parser_create()zurückgegeben wird. Dies ist das Objekt, das den Parsing-Zustand enthält.$data— ein Teil (oder der gesamte) XML-Text, der dem Parser übergeben wird.$is_final— auftruesetzen, wenn Sie den letzten Datenteil übergeben. Solange dieser Wertfalseist, behält der Parser seinen Zustand, sodass Siexml_parse()erneut mit dem nächsten Teil aufrufen können.
Rückgabewert
xml_parse() gibt bei Erfolg 1 (truthy) und bei Fehler 0 (falsy) zurück. Die Funktion gibt nicht die geparsten Daten zurück — der geparste Inhalt wird an die registrierten Handler-Callbacks übergeben. Wenn 0 zurückgegeben wird, können Sie den Fehler mit xml_get_error_code() und xml_error_string() untersuchen.
Verwendungsbeispiele
Schauen wir uns einige praktische Beispiele zur Verwendung von xml_parse() in PHP an.
Beispiel 1: XML mit Event-Handlern parsen
xml_parse() ist ein SAX-Parser: Er erstellt kein Dokument für Sie, er löst Ereignisse aus. Um eine Ausgabe zu erhalten, müssen Sie Handler-Funktionen registrieren. Das folgende Beispiel verwendet einen eingebetteten XML-String, sodass es ohne externe Datei direkt ausgeführt werden kann:
<?php
$xml = <<<XML
<?xml version="1.0"?>
<note>
<to>Tove</to>
<from>Jani</from>
</note>
XML;
$parser = xml_parser_create();
// Keep element names in their original case instead of upper-casing them.
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_set_element_handler(
$parser,
fn($p, $name, $attrs) => print("Start: $name\n"),
fn($p, $name) => print("End: $name\n")
);
xml_set_character_data_handler($parser, function ($p, $data) {
$data = trim($data);
if ($data !== "") {
echo "Text: $data\n";
}
});
if (!xml_parse($parser, $xml, true)) {
$code = xml_get_error_code($parser);
echo "Error: " . xml_error_string($code)
. " at line " . xml_get_current_line_number($parser);
}
xml_parser_free($parser);Dies gibt aus:
Start: note
Start: to
Text: Tove
End: to
Start: from
Text: Jani
End: from
End: noteDer Parser durchläuft das Dokument von oben nach unten und ruft Ihre Start-Element-, Zeichendaten- und End-Element-Handler in der Dokumentreihenfolge auf. Wir registrieren sie mit xml_set_element_handler() und xml_set_character_data_handler(), übergeben alles in einem Aufruf ($is_final = true) und geben den Parser mit xml_parser_free() frei.
Beispiel 2: Datei oder Datenstrom in Teilen parsen
Die eigentliche Stärke von xml_parse() liegt im inkrementellen Parsen: Das Dokument wird stückweise eingespeist, sodass selbst eine mehrere Gigabyte große Datei nicht in den Speicher passen muss. Übergeben Sie $is_final = false für jeden Teil außer dem letzten:
<?php
$parser = xml_parser_create();
xml_set_element_handler(
$parser,
fn($p, $name, $attrs) => print("<$name>\n"),
fn($p, $name) => print("</$name>\n")
);
$handle = fopen("data.xml", "r"); // or php://stdin for a stream
while (($chunk = fread($handle, 4096)) !== false) {
$isFinal = feof($handle);
if (!xml_parse($parser, $chunk, $isFinal)) {
$code = xml_get_error_code($parser);
echo "XML error: " . xml_error_string($code)
. " at line " . xml_get_current_line_number($parser);
break;
}
if ($isFinal) {
break;
}
}
fclose($handle);
xml_parser_free($parser);Da der Parser seinen Zustand zwischen den Aufrufen beibehält, kann ein Element in einem Teil beginnen und in einem anderen enden — xml_parse() fügt die Ereignisse korrekt zusammen. Genau das macht die Funktion für große XML-Dateien geeignet, bei denen ein baumbasierter Ansatz wie SimpleXML den Speicher erschöpfen würde.
Beispiel 3 (Referenz): Eine Datei in einem Schritt parsen
Wenn Ihr XML klein genug ist, um in den Speicher zu passen, können Sie es mit file_get_contents() lesen und den gesamten String in einem einzigen Aufruf an xml_parse() übergeben. Handler können auch benannte Funktionen (als Strings) anstelle von Closures sein:
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);
// Define handler functions
function startElement($parser, $name, $attrs) {
echo "Start element: $name\n";
}
function endElement($parser, $name) {
echo "End element: $name\n";
}
function characterData($parser, $data) {
echo "Data: $data\n";
}
// Set handlers
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
$xml_data = file_get_contents("data.xml");
if (!xml_parse($xml_parser, $xml_data, true)) {
$error_message = xml_error_string(xml_get_error_code($xml_parser));
$error_line = xml_get_current_line_number($xml_parser);
echo "XML Parsing Error: $error_message at line $error_line";
}
xml_parser_free($xml_parser);Dieser Code erstellt einen XML-Parser mit xml_parser_create() und deaktiviert die Groß-/Kleinschreibungskonvertierung. Anschließend werden drei Callback-Funktionen definiert: startElement() für öffnende Tags, endElement() für schließende Tags und characterData() für Textinhalte. Diese Handler werden mit xml_set_element_handler() und xml_set_character_data_handler() registriert.
Das Skript liest „data.xml" und übergibt den Inhalt an xml_parse(). Während der Parser durch das XML streamt, ruft er automatisch die registrierten Handler auf. Tritt beim Parsen ein Fehler auf, werden der Fehlercode und die Fehlermeldung mit xml_get_error_code() und xml_error_string() abgerufen und eine beschreibende Fehlermeldung ausgegeben. Abschließend wird der Parser-Speicher mit xml_parser_free() freigegeben.
Häufige Fallstricke
- Keine Handler, keine Ausgabe.
xml_parse()löst nur die von Ihnen registrierten Callbacks aus. Wenn keine Handler gesetzt sind, wird erfolgreich geparst, aber nichts sichtbares ausgegeben. - Zeichendaten kommen stückweise an. Ein einzelner Textknoten kann
xml_set_character_data_handlermehrfach auslösen (z. B. rund um Entity-Referenzen). Akkumulieren Sie den Text daher in einem Puffer, anstatt anzunehmen, dass Sie ihn auf einmal erhalten. - Leerzeichen zählen als Zeichendaten. Einrückungen zwischen Tags lösen den Zeichendaten-Handler aus. Verwenden Sie
trim()(wie in Beispiel 1), wenn Sie nur echten Text benötigen. - Den Parser immer freigeben. Rufen Sie
xml_parser_free()auf, wenn Sie fertig sind. In PHP 8+ ist das Handle einXMLParser-Objekt, das durch den Garbage Collector freigegeben wird, aber explizites Freigeben hält den Speicherbedarf bei langlebigen Skripten gering.
Verwandte Funktionen
xml_parser_create()— erstellt das Parser-Handle, das anxml_parse()übergeben wird.xml_set_element_handler()— registriert Start-/End-Tag-Callbacks.xml_set_character_data_handler()— registriert den Textinhalt-Callback.xml_parse_into_struct()— parst XML in ein flaches Array, anstatt Ereignisse auszulösen.- SimpleXML — eine übergeordnete, baumbasierte Alternative für kleine Dokumente.
Fazit
PHPs Funktion xml_parse() ist der Motor der SAX-basierten XML-Parser-Erweiterung. Anstatt ein Dokument zurückzugeben, streamt sie durch XML und löst die von Ihnen registrierten Handler aus, wobei sie bei Erfolg 1 und bei Fehler 0 zurückgibt. Der Parameter $is_final ermöglicht das Parsen von Daten in Teilen, was die Funktion auch bei sehr großen Dateien speichereffizient macht. In Kombination mit xml_parser_create(), den Handler-Setup-Funktionen und xml_parser_free() ergibt sich eine schnelle und speicherschonende Methode zur XML-Verarbeitung in PHP.