W3docs

PHP libxml-Bibliothek Referenzhandbuch

PHP libxml-Erweiterung: Fehler erfassen, XML mit SimpleXML oder DOM parsen und validieren, XXE bei fremden Eingaben vermeiden.

Dieses Handbuch behandelt die PHP libxml-Erweiterung: was sie ist, wie PHPs XML-Parser Fehler darüber melden und wie XML sicher geparst, validiert und bearbeitet werden kann. Der zentrale Gedanke ist, dass libxml die gemeinsame Fehlerbehandlungs- und Konfigurationsschicht unter SimpleXML, DOM und XMLReader ist — wer sie versteht, kann jede XML-Erweiterung in PHP leichter debuggen.

Was ist PHP libxml?

libxml ist die C-Bibliothek, die PHP für nahezu die gesamte XML-Verarbeitung verwendet. Die PHP libxml-Erweiterung stellt die Fehlerbehandlung und Parser-Optionen dieser Bibliothek im eigenen Code zur Verfügung. Man ruft sie selten direkt auf — stattdessen verwendet man eine übergeordnete Erweiterung, die darauf aufbaut:

  • SimpleXML — die schnelle, array-ähnliche Methode zum Lesen von XML.
  • DOM (DOMDocument) — vollständiger Lese-/Schreibzugriff auf den Dokumentenbaum.
  • XMLReader / XMLWriter — streaming, speichereffizientes Parsen großer Dateien.

Wenn eine dieser Erweiterungen auf fehlerhaftes XML trifft, wird das Problem über libxml gemeldet. Mit den libxml_*-Funktionen lassen sich diese Fehler erfassen, untersuchen und löschen.

PHP libxml installieren

Die libxml-Erweiterung ist gebündelt und standardmäßig aktiviert — es muss nichts installiert werden. Die Aktivierung lässt sich zur Laufzeit überprüfen:

<?php
var_dump(extension_loaded('libxml')); // bool(true)
echo LIBXML_DOTTED_VERSION;            // e.g. "2.9.14" — the linked libxml2 version
?>

Wenn ein benutzerdefinierter Build false meldet, PHP mit --with-libxml neu kompilieren (älteres PHP verwendete --enable-libxml).

libxml-Fehler behandeln

Dies ist der wichtigste Teil der Erweiterung. Standardmäßig gibt ein fehlerhaftes Dokument PHP-Warnungen aus, was in der Produktion schwierig zu handhaben ist. Stattdessen sollte in den internen Fehlermodus gewechselt werden: libxml sammelt dann Fehler in einem Puffer, den man selbst ausliest.

<?php
// Stop warnings; buffer errors instead.
libxml_use_internal_errors(true);

$broken = '<root><item>unclosed</root>';
$xml = simplexml_load_string($broken);

if ($xml === false) {
  foreach (libxml_get_errors() as $error) {
    // Each $error is a LibXMLError object.
    printf(
      "[%s] line %d: %s",
      $error->level === LIBXML_ERR_FATAL ? 'fatal' : 'warning',
      $error->line,
      trim($error->message)
    );
    echo PHP_EOL;
  }
  libxml_clear_errors(); // Empty the buffer so it doesn't leak into later parses.
}
?>

Ein LibXMLError stellt level (LIBXML_ERR_WARNING, LIBXML_ERR_ERROR, LIBXML_ERR_FATAL), code, message, line, column und file zur Verfügung. Verwandte Funktionen:

XML-Dokumente parsen

Die häufigste Verwendung von XML in PHP ist das Lesen eines Dokuments. simplexml_load_string() (und sein Datei-Pendant simplexml_load_file()) gibt bei Fehler false zurück, daher immer mit dem internen Fehlermodus kombinieren:

<?php
libxml_use_internal_errors(true);

$source = '<catalog><book id="1">PHP Basics</book></catalog>';
$xml = simplexml_load_string($source);

if ($xml === false) {
  echo "Failed to parse XML." . PHP_EOL;
  foreach (libxml_get_errors() as $error) {
    echo trim($error->message) . PHP_EOL;
  }
  libxml_clear_errors();
} else {
  echo "Loaded: " . $xml->book . PHP_EOL;      // Loaded: PHP Basics
  echo "id = " . $xml->book['id'] . PHP_EOL;    // id = 1
}
?>

Parser-Optionen (libxml-Konstanten)

Die meisten XML-Funktionen akzeptieren eine $options-Bitmaske aus LIBXML_*-Konstanten. Sie werden mit dem bitweisen ODER-Operator (|) kombiniert:

<?php
$xml = simplexml_load_string(
  '<a>  <b>text</b>  </a>',
  'SimpleXMLElement',
  LIBXML_NOCDATA | LIBXML_NOBLANKS // drop CDATA wrappers + ignore whitespace-only nodes
);
echo $xml->b; // text
?>

Häufig verwendete Optionen:

KonstanteWirkung
LIBXML_NOBLANKSLeere (nur Leerzeichen enthaltende) Knoten entfernen.
LIBXML_NOCDATACDATA-Abschnitte als reinen Text zusammenführen.
LIBXML_NOERROR / LIBXML_NOWARNINGFehler / Warnungen unterdrücken.
LIBXML_COMPACTKleinknotenoptimierung für große Dokumente.
LIBXML_NOENTEntities ersetzen — gefährlich bei nicht vertrauenswürdigen Eingaben (siehe unten).

Sicherheit: nicht vertrauenswürdiges XML und XXE

XML eXternal Entity (XXE)-Angriffe ermöglichen es einem bösartigen Dokument, lokale Dateien zu lesen oder Netzwerkanfragen auszulösen. Das Laden von Entities bei nicht kontrollierten Eingaben sollte niemals aktiviert werden. Die sicheren Standardeinstellungen in modernem PHP (7.0+) deaktivieren das Laden externer Entities bereits, daher gilt die einfache Regel:

  • Nicht LIBXML_NOENT oder LIBXML_DTDLOAD beim Parsen nicht vertrauenswürdiger XML verwenden.
  • Bei PHP < 8.0 kann zusätzlich libxml_disable_entity_loader(true) als harte Absicherung aufgerufen werden. Siehe libxml_disable_entity_loader() für Details (die Funktion ist ab 8.0+ veraltet, da das Laden standardmäßig deaktiviert ist).

XML-Dokumente validieren

libxml kann ein Dokument gegen eine DTD oder ein XSD-Schema validieren. DOMDocument::schemaValidate() ist der direkteste Weg, und Validierungsfehler fließen durch denselben Puffer:

<?php
libxml_use_internal_errors(true);

$doc = new DOMDocument();
if (!$doc->load('example.xml')) {
  echo "Could not load document." . PHP_EOL;
  exit;
}

if ($doc->schemaValidate('example.xsd')) {
  echo "The XML document is valid." . PHP_EOL;
} else {
  echo "Validation failed:" . PHP_EOL;
  foreach (libxml_get_errors() as $error) {
    echo "  line {$error->line}: " . trim($error->message) . PHP_EOL;
  }
  libxml_clear_errors();
}
?>

Für sehr große Dateien empfiehlt sich der streaming-basierte XMLReader, der beim Lesen validiert, ohne das gesamte Dokument in den Speicher zu laden:

<?php
$reader = new XMLReader();
$reader->open('example.xml');
$reader->setSchema('example.xsd'); // attach the XSD before reading

$valid = true;
while ($reader->read()) {
  if (!$reader->isValid()) {
    $valid = false;
    break;
  }
}
$reader->close();

echo $valid ? "Document is valid." : "Document is not valid.";
?>

XML-Dokumente bearbeiten

Zum Ändern eines Dokuments verwendet man in der Regel DOM. Das folgende Beispiel erstellt ein Dokument im Speicher (läuft also ohne externe Datei), hängt einen Knoten an und gibt das Ergebnis aus:

<?php
$doc = new DOMDocument('1.0', 'UTF-8');
$doc->formatOutput = true; // pretty-print the output

// Build a root, then add a child element with text content.
$root = $doc->createElement('catalog');
$doc->appendChild($root);

$book = $doc->createElement('book', 'Learning PHP');
$book->setAttribute('id', '42');
$root->appendChild($book);

echo $doc->saveXML();
// <?xml version="1.0" encoding="UTF-8"?>
// <catalog>
//   <book id="42">Learning PHP</book>
// </catalog>
?>

Beim Bearbeiten einer Datei von der Festplatte: laden, den Zielknoten mit getElementsByTagName() suchen, an diesen Knoten anhängen (nicht an das Dokument, das nur ein Root-Element haben darf), dann mit save() speichern.

Wann wird das verwendet?

  • Konfigurationen oder Feed-Daten lesen (RSS/Atom, SOAP-Antworten, Sitemaps) — mit SimpleXML parsen, mit internen Fehlern absichern.
  • Uploads validieren — Dokumente ablehnen, die schemaValidate() nicht bestehen, bevor man ihnen vertraut.
  • XML für eine API oder einen Export erzeugen — mit DOM aufbauen, damit Attribute und Kodierung korrekt behandelt werden.
  • "Ungültiges XML"-Fehler debuggenlibxml_get_errors() lesen, um die genaue Zeile und Spalte zu sehen.

Fazit

Die libxml-Erweiterung ist das Fundament von PHPs XML-Stack. Das Muster, das sich überall bewährt: libxml_use_internal_errors(true) aufrufen, parsen oder validieren, dann libxml_get_errors() und libxml_clear_errors() auswerten. Danach das richtige Werkzeug wählen — SimpleXML für schnelle Lesevorgänge, DOM zum Bearbeiten, XMLReader für große Dateien — und LIBXML_*-Optionen übergeben, um das Parse-Verhalten zu steuern. Das Laden von Entities für nicht vertrauenswürdige Eingaben deaktiviert lassen, dann ist die XML-Verarbeitung sowohl robust als auch sicher.

Übungen

Übung
Wozu trägt die PHP libxml-Erweiterung bei?
Wozu trägt die PHP libxml-Erweiterung bei?
Was this page helpful?