Start · Sprachen · PHP · Referenz · xml_set_element_handler

xml_set_element_handler

Funktion

Registriert Callback-Funktionen für öffnende und schließende XML-Elemente in einem expat-basierten XML-Parser.

seit PHP 4.0.0 Kategorie: xml

Signatur

xml_set_element_handler(XMLParser $parser, callable|string|null $start_handler, callable|string|null $end_handler): bool

Beschreibung

xml_set_element_handler() legt fest, welche PHP-Funktionen aufgerufen werden, wenn der XML-Parser ein öffnendes Tag (Start-Element) oder ein schließendes Tag (End-Element) findet. Diese Funktion ist essenziell, um mit dem SAX-Parsing-Modell von PHP XML-Dokumente effizient zu verarbeiten, ohne den gesamten Dokument-Baum im Speicher aufzubauen.

Der Start-Handler erhält als Argumente die Parser-Ressource, den Element-Namen sowie ein assoziatives Array aller Attribute des Elements. Der End-Handler erhält nur den Parser und den Element-Namen. Beide Callbacks können als null übergeben werden, um einen zuvor gesetzten Handler zu entfernen.

Typischer Einsatz ist die Verarbeitung großer XML-Dokumente (z. B. RSS-Feeds, SOAP-Antworten oder Daten-Importe), bei denen ein DOM-basierter Ansatz zu viel Speicher verbrauchen würde. Die Callbacks werden event-gesteuert ausgeführt, sobald xml_parse() den entsprechenden Tag-Beginn oder das Tag-Ende liest.

Seit PHP 8.0 ist der erste Parameter ein XMLParser-Objekt statt einer Ressource.

Parameter

Name Typ Default Beschreibung
$parser Pflicht XMLParser Eine gültige XML-Parser-Instanz, erzeugt mit xml_parser_create() oder xml_parser_create_ns().
$start_handler Pflicht callable|string|null Callback für öffnende Tags. Wird aufgerufen mit (XMLParser $parser, string $name, array $attributes). null entfernt einen vorhandenen Handler.
$end_handler Pflicht callable|string|null Callback für schließende Tags. Wird aufgerufen mit (XMLParser $parser, string $name). null entfernt einen vorhandenen Handler.

Rückgabewert

Typ
bool
Beschreibung
Gibt true bei Erfolg zurück, false wenn der übergebene Parser ungültig ist.

Beispiele

Einfaches SAX-Parsing eines XML-Dokuments

<?php
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
  <book id="1" lang="de">
    <title>PHP-Referenz</title>
  </book>
  <book id="2" lang="en">
    <title>PHP Manual</title>
  </book>
</catalog>
XML;

$parser = xml_parser_create('UTF-8');

function startElement(XMLParser $parser, string $name, array $attrs): void {
    echo "Öffnendes Tag: &lt;{$name}&gt;";
    if (!empty($attrs)) {
        foreach ($attrs as $key => $value) {
            echo " {$key}=\"{$value}\"";
        }
    }
    echo PHP_EOL;
}

function endElement(XMLParser $parser, string $name): void {
    echo "Schließendes Tag: &lt;/{$name}&gt;" . PHP_EOL;
}

xml_set_element_handler($parser, 'startElement', 'endElement');

if (!xml_parse($parser, $xml, true)) {
    echo 'Fehler: ' . xml_error_string(xml_get_error_code($parser));
}

xml_parser_free($parser);
Öffnendes Tag: <CATALOG> Öffnendes Tag: <BOOK> ID="1" LANG="de" Öffnendes Tag: <TITLE> Schließendes Tag: </TITLE> Schließendes Tag: </BOOK> Öffnendes Tag: <BOOK> ID="2" LANG="en" Öffnendes Tag: <TITLE> Schließendes Tag: </TITLE> Schließendes Tag: </BOOK> Schließendes Tag: </CATALOG>

Verwendung mit Objekt-Methoden als Callbacks

<?php
class RssFeedParser {
    private array $items = [];
    private string $currentTag = '';
    private array $currentItem = [];

    public function parse(string $xml): array {
        $parser = xml_parser_create('UTF-8');
        xml_set_element_handler(
            $parser,
            [$this, 'onStart'],
            [$this, 'onEnd']
        );
        xml_set_character_data_handler($parser, [$this, 'onData']);
        xml_parse($parser, $xml, true);
        xml_parser_free($parser);
        return $this->items;
    }

    public function onStart(XMLParser $parser, string $name, array $attrs): void {
        $this->currentTag = $name;
        if ($name === 'ITEM') {
            $this->currentItem = [];
        }
    }

    public function onEnd(XMLParser $parser, string $name): void {
        if ($name === 'ITEM' && !empty($this->currentItem)) {
            $this->items[] = $this->currentItem;
        }
        $this->currentTag = '';
    }

    public function onData(XMLParser $parser, string $data): void {
        $data = trim($data);
        if ($data !== '' && in_array($this->currentTag, ['TITLE', 'LINK'], true)) {
            $this->currentItem[$this->currentTag] = $data;
        }
    }
}

$xml = '<?xml version="1.0"?><rss><channel>'
     . '<item><title>Eintrag 1</title><link>https://example.com/1</link></item>'
     . '<item><title>Eintrag 2</title><link>https://example.com/2</link></item>'
     . '</channel></rss>';

$rssParser = new RssFeedParser();
$items = $rssParser->parse($xml);

foreach ($items as $item) {
    echo $item['TITLE'] . ' => ' . $item['LINK'] . PHP_EOL;
}
Eintrag 1 => https://example.com/1 Eintrag 2 => https://example.com/2

// Wichtig · Fallstricke

Groß-/Kleinschreibung: Standardmäßig konvertiert der XML-Parser alle Element- und Attribut-Namen in Großbuchstaben. Dieses Verhalten kann mit xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false) deaktiviert werden, wenn die originale Schreibweise benötigt wird.

Attribute-Array: Das Array im Start-Handler enthält Attribut-Namen als Schlüssel und deren Werte als Strings. Ist kein Attribut vorhanden, wird ein leeres Array übergeben.

Kein Rückgabewert aus Callbacks: Rückgabewerte der Handler-Callbacks werden ignoriert. Um Daten zwischen Callbacks auszutauschen, empfiehlt sich die Verwendung einer Klassen-Instanz als Kontext (wie im zweiten Beispiel gezeigt) oder globaler Variablen.

Alternative: Für kleinere oder komplex verschachtelte Dokumente ist SimpleXML oder DOMDocument oft komfortabler. xml_set_element_handler() glänzt bei großen Datenmengen mit minimalem Speicherbedarf.