W3docs

xml_get_error_code()

La funzione PHP xml_get_error_code(): sintassi, valore restituito e come convertire il codice Expat in un messaggio leggibile con xml_error_string().

La funzione xml_get_error_code() è una funzione built-in di PHP che recupera il codice di errore di un parser XML. Quando si analizza XML con l'estensione XML Parser (Expat) di PHP, le funzioni di parsing restituiscono false nel momento in cui qualcosa va storto — ma false da solo non dice cosa è andato storto. xml_get_error_code() restituisce un codice numerico che descrive l'errore più recente, che è poi possibile tradurre in un messaggio leggibile con xml_error_string().

Questa pagina illustra la sintassi della funzione, cosa restituisce, come convertire il codice in un messaggio e l'insidia che mette in difficoltà la maggior parte delle persone: il codice restituito è un codice di errore Expat, non la costante XML_OPTION_* che ci si potrebbe aspettare.

Sintassi

xml_get_error_code(XMLParser $parser): int

$parser è il parser creato da xml_parser_create() (o xml_parser_create_ns()). In PHP 8.0+ si tratta di un oggetto XMLParser; in PHP 7.x e precedenti era una resource. Il codice in questo capitolo funziona su entrambi.

Valore restituito

La funzione restituisce un codice di errore di tipo integer:

  • 0 (la costante XML_ERROR_NONE) significa nessun errore — il parsing è riuscito.
  • Qualsiasi valore diverso da zero identifica il tipo di errore. Passarlo a xml_error_string() per ottenere una descrizione leggibile e a xml_get_current_line_number() per individuare dove si è verificato.

Controllare sempre il valore restituito dalla funzione di parsing (xml_parse() / xml_parse_into_struct()); chiamare xml_get_error_code() solo dopo che restituisce false.

Un esempio completo ed eseguibile

L'esempio seguente analizza una stringa XML volutamente errata (il tag di chiusura non corrisponde a quello di apertura), poi riporta il codice di errore, il relativo messaggio e il numero di riga. Poiché l'XML è incorporato come stringa, è possibile copiarlo ed eseguirlo così com'è — senza bisogno di alcun file.

<?php
$broken = "<note><to>Ann</from></note>";   // </from> should be </to>

$parser = xml_parser_create();
if (!xml_parse_into_struct($parser, $broken, $values)) {
    $code = xml_get_error_code($parser);
    echo "Error code:  $code\n";
    echo "Message:     " . xml_error_string($code) . "\n";
    echo "On line:     " . xml_get_current_line_number($parser) . "\n";
}
xml_parser_free($parser);

Output:

Error code:  76
Message:     Mismatched tag
On line:     1

xml_parse_into_struct() restituisce false, quindi si chiama xml_get_error_code() e si passa il risultato direttamente a xml_error_string() per ottenere il messaggio "Mismatched tag".

L'insidia: il codice è un codice Expat

È allettante confrontare il risultato con costanti come XML_ERROR_TAG_MISMATCH in uno switch:

switch ($code) {
    case XML_ERROR_TAG_MISMATCH:  // value 7
        // ...
}

Ma questo ramo non corrisponde mai. Il parser Expat restituisce 76 per un tag non corrispondente, mentre XML_ERROR_TAG_MISMATCH è la costante 7 — si tratta di schemi di numerazione diversi, quindi il confronto fallisce silenziosamente. L'approccio affidabile è convertire sempre il codice in testo con xml_error_string() invece di confrontare numeri grezzi:

<?php
$samples = [
    'good'      => "<note><to>Ann</to></note>",
    'mismatch'  => "<note><to>Ann</from></note>",
    'truncated' => "<note><to>Ann",
];

foreach ($samples as $label => $xml) {
    $parser = xml_parser_create();
    $ok = xml_parse_into_struct($parser, $xml, $values);
    $code = xml_get_error_code($parser);
    printf("%-9s -> code %d (%s)\n", $label, $code, xml_error_string($code) ?: 'OK');
    xml_parser_free($parser);
}

Output:

good      -> code 0 (No error)
mismatch  -> code 76 (Mismatched tag)
truncated -> code 5 (Invalid document end)

Un codice 0 (XML_ERROR_NONE) conferma che il documento è stato analizzato correttamente, che è esattamente il risultato prodotto dal campione good ben formato.

Mostrare l'errore all'utente

In un'applicazione reale — ad esempio, un gestore per un file XML caricato — di solito si registra il dettaglio tecnico e si mostra il messaggio comprensibile:

$parser = xml_parser_create();
$xml    = file_get_contents($_FILES['xml_file']['tmp_name']);

if (!xml_parse_into_struct($parser, $xml, $values)) {
    $code = xml_get_error_code($parser);
    $line = xml_get_current_line_number($parser);

    // For the logs / developers:
    error_log("XML parse failed on line $line: " . xml_error_string($code));

    // For the user:
    $userMessage = "We couldn't read that file — please check it is valid XML.";
}
xml_parser_free($parser);

Quando usarla (e quando no)

xml_get_error_code() appartiene all'estensione XML Parser basata su Expat — la stessa famiglia di xml_parser_create() e xml_parse_into_struct(). Si utilizza quando si esegue il parsing basato su eventi/stream con tale estensione e si ha bisogno di reagire a un errore.

Se si analizza XML con SimpleXML o DOM, questa funzione non si applica — quelle usano l'API degli errori di libxml. In tal caso si utilizza libxml_get_last_error() (dopo aver chiamato libxml_use_internal_errors(true)) per esaminare cosa è andato storto. Vedere la panoramica di SimpleXML per quel flusso di lavoro.

Conclusione

xml_get_error_code() recupera il codice di errore numerico Expat per l'ultimo errore su un'istanza del parser XML. Il pattern affidabile è: controllare il valore restituito dalla funzione di parsing, e se è false, chiamare xml_get_error_code() e passare il risultato a xml_error_string() per un messaggio leggibile — non confrontare il codice grezzo con le costanti XML_ERROR_*, poiché la numerazione Expat non corrisponde a esse. Abbinarla a xml_get_current_line_number() per indicare agli utenti (e ai log) il punto esatto in cui il documento ha smesso di funzionare.

Pratica

Pratica
Qual è il modo corretto per recuperare il codice di errore di un documento XML in PHP?
Qual è il modo corretto per recuperare il codice di errore di un documento XML in PHP?
Was this page helpful?