W3docs

Guida di riferimento alla libreria PHP libxml

Guida all'estensione PHP libxml: gestione degli errori, parsing e validazione XML con SimpleXML o DOM, prevenzione degli attacchi XXE.

Questa guida copre l'estensione PHP libxml: cos'è, come i parser XML di PHP segnalano gli errori attraverso di essa e come effettuare il parsing, la validazione e la manipolazione di XML in modo sicuro. Il concetto fondamentale da assimilare è che libxml è il livello condiviso di segnalazione degli errori e configurazione sottostante a SimpleXML, DOM e XMLReader — una volta compreso, ogni estensione XML in PHP diventa più facile da gestire.

Cos'è PHP libxml?

libxml è la libreria C che PHP utilizza per quasi tutta la sua elaborazione XML. L'estensione PHP libxml espone la gestione degli errori e le opzioni del parser di quella libreria al tuo codice. Raramente la chiami direttamente — invece utilizzi un'estensione di livello superiore costruita su di essa:

  • SimpleXML — il modo rapido, simile agli array, per leggere XML.
  • DOM (DOMDocument) — accesso completo in lettura/scrittura all'albero del documento.
  • XMLReader / XMLWriter — parsing in streaming, efficiente in termini di memoria, per file di grandi dimensioni.

Quando uno di questi incontra XML malformato, segnala il problema attraverso libxml. Le funzioni libxml_* consentono di catturare, ispezionare e cancellare quegli errori.

Installare PHP libxml

L'estensione libxml è inclusa e abilitata per impostazione predefinita — non c'è nulla da installare. Puoi verificare che sia attiva in fase di esecuzione:

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

Se una build personalizzata restituisce false, ricompila PHP con --with-libxml (le versioni precedenti di PHP usavano --enable-libxml).

Gestire gli errori libxml

Questa è la parte più importante dell'estensione. Per impostazione predefinita, un documento malformato genera avvisi PHP, il che è scomodo da gestire in produzione. Invece, passa alla modalità errore interno: libxml raccoglie quindi gli errori in un buffer che puoi leggere tu stesso.

<?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.
}
?>

Un LibXMLError espone level (LIBXML_ERR_WARNING, LIBXML_ERR_ERROR, LIBXML_ERR_FATAL), code, message, line, column e file. Funzioni correlate:

Parsing di documenti XML

L'uso più comune di XML in PHP è la lettura di un documento. simplexml_load_string() (e la sua variante per file simplexml_load_file()) restituiscono false in caso di errore, quindi abbinale sempre alla modalità errore interno:

<?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
}
?>

Opzioni del parser (costanti libxml)

La maggior parte delle funzioni XML accetta una maschera di bit $options composta da costanti LIBXML_*. Combinale con l'operatore OR bit a bit (|):

<?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
?>

Opzioni utilizzate frequentemente:

CostanteEffetto
LIBXML_NOBLANKSRimuove i nodi vuoti (solo spazi bianchi).
LIBXML_NOCDATAUnisce le sezioni CDATA come testo normale.
LIBXML_NOERROR / LIBXML_NOWARNINGSopprime errori / avvisi.
LIBXML_COMPACTOttimizzazione per nodi piccoli in documenti di grandi dimensioni.
LIBXML_NOENTSostituisce le entità — pericoloso con input non attendibile (vedi sotto).

Sicurezza: XML non attendibile e XXE

Gli attacchi XML eXternal Entity (XXE) consentono a un documento malevolo di leggere file locali o innescare richieste di rete. Non abilitare mai il caricamento di entità su input che non controlli. Le impostazioni predefinite sicure in PHP moderno (7.0+) disabilitano già il caricamento di entità esterne, quindi la regola è semplice:

  • Non passare LIBXML_NOENT o LIBXML_DTDLOAD durante il parsing di XML non attendibile.
  • Su PHP < 8.0 puoi chiamare anche libxml_disable_entity_loader(true) come protezione aggiuntiva. Consulta libxml_disable_entity_loader() per i dettagli (la funzione è deprecata in 8.0+ perché il caricamento è disabilitato per impostazione predefinita).

Validare documenti XML

libxml può validare un documento rispetto a una DTD o a uno schema XSD. DOMDocument::schemaValidate() è il metodo più diretto, e gli errori di validazione fluiscono attraverso lo stesso buffer:

<?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();
}
?>

Per file molto grandi, preferisci XMLReader in streaming, che valida durante la lettura senza caricare l'intero documento in memoria:

<?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.";
?>

Manipolare documenti XML

Per modificare un documento si utilizza generalmente DOM. L'esempio seguente costruisce un documento in memoria (quindi funziona senza file esterni), aggiunge un nodo e stampa il risultato:

<?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>
?>

Quando si modifica un file dal disco, caricalo, individua il nodo target con getElementsByTagName(), aggiungilo a quel nodo (non al documento, che può contenere un solo elemento radice), quindi salvalo con save().

Quando usarlo?

  • Lettura di dati di configurazione o feed (RSS/Atom, risposte SOAP, sitemap) — effettua il parsing con SimpleXML, proteggi con la modalità errore interno.
  • Validazione di upload — rifiuta i documenti che non superano schemaValidate() prima di considerarli attendibili.
  • Generazione di XML per un'API o un'esportazione — costruiscilo con DOM in modo che attributi e codifica siano gestiti correttamente.
  • Debug di errori "XML non valido" — leggi libxml_get_errors() per vedere la riga e la colonna esatte.

Conclusione

L'estensione libxml è il fondamento dello stack XML di PHP. Il pattern che si rivela utile ovunque è: chiama libxml_use_internal_errors(true), effettua il parsing o la validazione, quindi ispeziona libxml_get_errors() e libxml_clear_errors(). Da lì, scegli lo strumento giusto — SimpleXML per letture rapide, DOM per la modifica, XMLReader per file di grandi dimensioni — e passa le opzioni LIBXML_* per controllare il comportamento del parser. Mantieni disabilitato il caricamento delle entità per input non attendibile e la gestione di XML sarà robusta e sicura.

Pratica

Pratica
A cosa contribuisce l'estensione PHP libxml?
A cosa contribuisce l'estensione PHP libxml?
Was this page helpful?