W3docs

xml_set_end_namespace_decl_handler()

La funzione xml_set_end_namespace_decl_handler() registra un callback per la fine delle dichiarazioni di namespace XML nel parser SAX di PHP.

La funzione xml_set_end_namespace_decl_handler() è una funzione integrata di PHP che registra un callback definito dall'utente da eseguire ogni volta che il parser SAX XML raggiunge la fine di un elemento che ha dichiarato uno o più namespace XML. È la controparte di chiusura di xml_set_start_namespace_decl_handler(): l'handler di apertura si attiva quando un prefisso di namespace entra in scope, mentre questo handler di chiusura si attiva quando quel prefisso esce dallo scope.

Questa funzione appartiene all'estensione xml (SAX) event-driven di PHP, che legge un documento dall'inizio alla fine e chiama gli handler man mano che incontra ogni costrutto, anziché costruire un albero in memoria come SimpleXML. È utile soprattutto quando si vuole tenere traccia dei namespace attualmente attivi durante il parsing — ad esempio, per mantenere uno stack dei prefissi in scope o per pulire lo stato al termine di una sezione con namespace.

Quando usarla

Una dichiarazione di namespace è un attributo come xmlns:ns="http://example.com". Il suo scope è l'elemento su cui appare e tutti i suoi discendenti. Usare l'handler di fine namespace quando è necessario conoscere il momento esatto in cui quello scope si chiude — tipicamente per rimuovere un prefisso dallo stack costruito nell'handler di apertura, replicando come il parser stesso gestisce lo scope.

Sintassi

xml_set_end_namespace_decl_handler(XMLParser $parser, callable|false $handler): bool
ParametroDescrizione
$parserIl parser XML, creato con xml_parser_create_ns() (raccomandato) o xml_parser_create().
$handlerIl callback da eseguire ad ogni evento di fine namespace, oppure false per rimuovere un handler precedentemente impostato.

Valore restituito: restituisce true in caso di successo e false in caso di errore (ad esempio, se $parser non è un parser valido).

L'handler riceve due argomenti:

function handler(XMLParser $parser, string $prefix): void

$prefix è il prefisso del namespace il cui scope sta terminando (una string vuota "" per una dichiarazione xmlns="..." predefinita). Si noti che, a differenza dell'handler di apertura, l'handler di chiusura non riceve l'URI del namespace — solo il prefisso.

Esempi d'uso

Esempio: Impostare un handler per la fine della dichiarazione di namespace

Questo esempio configura l'handler e lo attiva analizzando una piccola string XML. L'handler viene invocato durante xml_parse(), quando il parser chiude l'elemento che ha dichiarato il namespace.

Analisi di XML con un handler per la fine della dichiarazione di namespace

function handle_end_namespace_decl($parser, $prefix) {
    echo "End of namespace prefix: $prefix\n";
}

$xml_parser = xml_parser_create_ns();
xml_set_end_namespace_decl_handler($xml_parser, "handle_end_namespace_decl");

$xml_data = '<?xml version="1.0"?><root xmlns:ns="http://example.com"><ns:child/></root>';
xml_parse($xml_parser, $xml_data, true);
xml_parser_free($xml_parser);

Il prefisso ns è dichiarato su <root>, quindi il suo scope termina quando viene raggiunto </root>. Quando l'handler si attiva, stampa il prefisso che esce dallo scope:

End of namespace prefix: ns

Attenzione: l'attivazione dell'handler di fine namespace dipende dall'implementazione di libexpat/PHP — su alcune versioni di PHP l'handler di apertura funziona mentre quello di chiusura non si attiva. Verificare sempre sul proprio runtime di destinazione e non affidarsi mai al solo handler di chiusura per rilevare un namespace; abbinarlo all'handler di apertura (vedi sotto) in modo che lo stato rimanga coerente.

Esempio: Abbinare gli handler di apertura e chiusura per tracciare lo scope

Nei parser reali l'handler di chiusura è raramente usato da solo. Abbinarlo all'handler di apertura consente di mantenere uno stack dei prefissi attualmente in scope. L'handler di apertura aggiunge ogni prefisso quando entra in scope; l'handler di chiusura lo rimuove quando l'elemento dichiarante si chiude:

Tracciamento dei prefissi di namespace in scope con uno stack

$activePrefixes = [];

function on_start_ns($parser, $prefix, $uri) {
    global $activePrefixes;
    $activePrefixes[] = $prefix;
    echo "Enter '$prefix' -> $uri | active: " . implode(', ', $activePrefixes) . "\n";
}

function on_end_ns($parser, $prefix) {
    global $activePrefixes;
    array_pop($activePrefixes);
    echo "Leave '$prefix' | active: " . implode(', ', $activePrefixes) . "\n";
}

$parser = xml_parser_create_ns();
xml_set_start_namespace_decl_handler($parser, "on_start_ns");
xml_set_end_namespace_decl_handler($parser, "on_end_ns");

$xml = '<?xml version="1.0"?>'
     . '<a xmlns:x="urn:x"><b xmlns:y="urn:y"><c/></b></a>';

xml_parse($parser, $xml, true);
xml_parser_free($parser);

Il prefisso x è dichiarato su <a> e y sul <b> interno. Man mano che gli scope si aprono e si chiudono, lo stack tiene traccia dei prefissi attualmente attivi. Gli eventi di chiusura si attivano in ordine last-in, first-out — y (quello interno) esce dallo scope prima di x:

Enter 'x' -> urn:x | active: x
Enter 'y' -> urn:y | active: x, y
Leave 'y' | active: x
Leave 'x' | active: 

Questo schema push/pop è l'utilizzo canonico dell'handler di chiusura: mantiene la visione dei namespace in scope allineata con la gestione dello scope del parser.

Errori comuni

  • Usare xml_parser_create_ns(). Gli handler di namespace ricevono eventi solo quando il parser è namespace-aware. Un parser creato con il semplice xml_parser_create() non separa i prefissi dagli URI.
  • Nessun URI nel callback di chiusura. Se si ha bisogno dell'URI quando lo scope si chiude, acquisirlo nell'handler di apertura (indicizzato per prefisso) e cercarlo qui.
  • Impostare gli handler prima del parsing. Registrare l'handler prima della prima chiamata a xml_parse(); gli handler impostati a metà parsing perderanno gli eventi precedenti.
  • Liberare il parser. Chiamare xml_parser_free() al termine per rilasciare le risorse, specialmente in script a lunga esecuzione.

Conclusione

xml_set_end_namespace_decl_handler() consente a un parser SAX di notificare al proprio codice esattamente quando un prefisso di namespace XML esce dallo scope. Combinato con xml_set_start_namespace_decl_handler() e un parser namespace-aware creato con xml_parser_create_ns(), offre un controllo preciso e a basso consumo di memoria sullo scope dei namespace durante lo streaming di grandi documenti XML.

Esercitazione

Pratica
Qual è la funzione di xml_set_end_namespace_decl_handler() in PHP?
Qual è la funzione di xml_set_end_namespace_decl_handler() in PHP?
Was this page helpful?