W3docs

xml_set_end_namespace_decl_handler()

A função xml_set_end_namespace_decl_handler() do PHP registra um callback para o fim de declarações de namespace no parser XML SAX.

A função xml_set_end_namespace_decl_handler() é uma função nativa do PHP que registra um callback definido pelo usuário para ser executado sempre que o parser XML SAX atingir o fim de um elemento que declarou um ou mais namespaces XML. Ela é a contraparte de fechamento de xml_set_start_namespace_decl_handler(): o handler de início é disparado quando um prefixo de namespace entra em escopo, e este handler de fim é disparado quando esse prefixo sai do escopo.

Esta função pertence à extensão xml (SAX) orientada a eventos do PHP, que lê um documento de cima para baixo e chama os seus handlers conforme encontra cada construção, em vez de construir uma árvore na memória como o SimpleXML. É mais útil quando você deseja rastrear quais namespaces estão ativos durante a análise — por exemplo, para manter uma pilha de prefixos em escopo ou para limpar o estado assim que uma seção com namespace termina.

Quando usar

Uma declaração de namespace é um atributo como xmlns:ns="http://example.com". Seu escopo é o elemento em que aparece e todos os seus descendentes. Use o handler de fim de namespace quando você precisar saber o momento exato em que esse escopo se fecha — geralmente para retirar um prefixo da pilha criada no handler de início, espelhando como o próprio parser gerencia o escopo.

Sintaxe

xml_set_end_namespace_decl_handler(XMLParser $parser, callable|false $handler): bool
ParâmetroDescrição
$parserO parser XML, criado com xml_parser_create_ns() (recomendado) ou xml_parser_create().
$handlerO callback a ser executado em cada evento de fim de namespace, ou false para remover um handler previamente definido.

Valor de retorno: retorna true em caso de sucesso e false em caso de falha (por exemplo, se $parser não for um parser válido).

Seu handler recebe dois argumentos:

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

$prefix é o prefixo de namespace cujo escopo está terminando (uma string vazia "" para uma declaração padrão xmlns="..."). Observe que, diferente do handler de início, o handler de fim não recebe o URI do namespace — apenas o prefixo.

Exemplos de uso

Exemplo: Definindo um handler de fim de declaração de namespace

Este exemplo configura o handler e o aciona ao analisar uma pequena string XML. O handler é invocado durante xml_parse(), quando o parser fecha o elemento que declarou o namespace.

Analisando XML com um handler de fim de declaração de 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);

O prefixo ns é declarado em <root>, portanto seu escopo termina quando </root> é alcançado. Quando o handler é disparado, ele imprime o prefixo que saiu do escopo:

End of namespace prefix: ns

Atenção: o disparo do handler de namespace de fim é sensível à versão do libexpat/PHP — em algumas versões do PHP o handler de início é executado enquanto o de fim não. Sempre teste com o seu ambiente de execução alvo e nunca dependa somente do handler de fim para detectar um namespace; use-o em conjunto com o handler de início (abaixo) para manter seu estado consistente.

Exemplo: Combinando handlers de início e fim para rastrear escopo

Em parsers reais, o handler de fim raramente é usado sozinho. Combiná-lo com o handler de início permite manter uma pilha dos prefixos atualmente em escopo. O handler de início empilha cada prefixo quando ele entra em escopo; o handler de fim o remove quando o elemento declarante é fechado:

Rastreando prefixos de namespace em escopo com uma pilha

$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);

O prefixo x é declarado em <a> e y no <b> interno. À medida que os escopos abrem e fecham, a pilha rastreia quais prefixos estão ativos. Os eventos de fim são disparados em ordem LIFO — y (o interno) sai do escopo antes de x:

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

Este padrão de início/remoção da pilha é o uso canônico do handler de fim: mantém sua visão dos namespaces em escopo alinhada com o gerenciamento de escopo do próprio parser.

Erros comuns

  • Use xml_parser_create_ns(). Os handlers de namespace só recebem eventos quando o parser é ciente de namespaces. Um parser criado com o simples xml_parser_create() não separará prefixos de URIs.
  • Sem URI no callback de fim. Se você precisar do URI quando o escopo fechar, capture-o no handler de início (indexado pelo prefixo) e consulte-o aqui.
  • Defina os handlers antes de analisar. Registre o handler antes da primeira chamada a xml_parse(); handlers definidos no meio da análise perderão os eventos anteriores.
  • Libere o parser. Chame xml_parser_free() ao terminar para liberar recursos, especialmente em scripts de longa execução.

Conclusão

xml_set_end_namespace_decl_handler() permite que um parser SAX informe ao seu código exatamente quando um prefixo de namespace XML sai do escopo. Combinado com xml_set_start_namespace_decl_handler() e um parser ciente de namespaces criado com xml_parser_create_ns(), oferece controle preciso e de baixo consumo de memória sobre o escopo de namespaces ao percorrer grandes documentos XML.

Prática

Prática
Qual é a função de xml_set_end_namespace_decl_handler() no PHP?
Qual é a função de xml_set_end_namespace_decl_handler() no PHP?
Was this page helpful?