W3docs

xml_set_end_namespace_decl_handler()

La función xml_set_end_namespace_decl_handler() de PHP registra un callback para el final de declaraciones de espacio de nombres en el analizador XML.

La función xml_set_end_namespace_decl_handler() es una función integrada de PHP que registra un callback definido por el usuario para que se ejecute cada vez que el analizador XML SAX alcanza el final de un elemento que declaró uno o más espacios de nombres XML. Es la contraparte de cierre de xml_set_start_namespace_decl_handler(): el manejador de inicio se activa cuando un prefijo de espacio de nombres entra en ámbito, y este manejador de fin se activa cuando ese prefijo sale del ámbito.

Esta función pertenece a la extensión xml (SAX) orientada a eventos de PHP, que lee un documento de arriba abajo y llama a sus manejadores a medida que encuentra cada construcción, en lugar de construir un árbol en memoria como SimpleXML. Es más útil cuando se desea rastrear qué espacios de nombres están activos durante el análisis, por ejemplo, para mantener una pila de prefijos en ámbito o para limpiar el estado una vez que termina una sección con espacio de nombres.

Cuándo usarlo

Una declaración de espacio de nombres es un atributo como xmlns:ns="http://example.com". Su ámbito es el elemento en el que aparece y todos sus descendientes. Utilice el manejador de fin de espacio de nombres cuando necesite conocer el momento exacto en que ese ámbito se cierra; típicamente para sacar un prefijo de una pila que construyó en el manejador de inicio, imitando la manera en que el propio analizador gestiona el ámbito.

Sintaxis

xml_set_end_namespace_decl_handler(XMLParser $parser, callable|false $handler): bool
ParámetroDescripción
$parserEl analizador XML, creado con xml_parser_create_ns() (recomendado) o xml_parser_create().
$handlerEl callback que se ejecutará en cada evento de fin de espacio de nombres, o false para eliminar un manejador previamente establecido.

Valor de retorno: devuelve true en caso de éxito y false en caso de error (por ejemplo, si $parser no es un analizador válido).

Su manejador recibe dos argumentos:

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

$prefix es el prefijo de espacio de nombres cuyo ámbito está terminando (una cadena vacía "" para una declaración xmlns="..." predeterminada). Tenga en cuenta que, a diferencia del manejador de inicio, el manejador de fin no recibe el URI del espacio de nombres, solo el prefijo.

Ejemplos de uso

Ejemplo: Establecer un manejador de fin de declaración de espacio de nombres

Este ejemplo configura el manejador y lo activa analizando una pequeña cadena XML. El manejador se invoca durante xml_parse(), cuando el analizador cierra el elemento que declaró el espacio de nombres.

Analizando XML con un manejador de fin de declaración de espacio de nombres

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

El prefijo ns se declara en <root>, por lo que su ámbito termina cuando se alcanza </root>. Cuando el manejador se activa, imprime el prefijo que sale del ámbito:

End of namespace prefix: ns

Aviso: la activación del manejador de espacio de nombres de fin es sensible a la versión subyacente de libexpat/PHP: en algunas versiones de PHP el manejador de inicio se ejecuta mientras que el de fin no lo hace. Pruebe siempre contra su entorno de destino y nunca confíe únicamente en el manejador de fin para detectar un espacio de nombres; combínelo con el manejador de inicio (a continuación) para mantener el estado coherente.

Ejemplo: Combinar manejadores de inicio y fin para rastrear el ámbito

En los analizadores reales el manejador de fin rara vez se usa solo. Combinarlo con el manejador de inicio permite mantener una pila de los prefijos actualmente en ámbito. El manejador de inicio agrega cada prefijo al entrar en ámbito; el manejador de fin lo extrae cuando el elemento declarante se cierra:

Rastreando prefijos de espacio de nombres en ámbito con una pila

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

El prefijo x se declara en <a> y y en el <b> interno. A medida que los ámbitos se abren y cierran, la pila rastrea qué prefijos están actualmente activos. Los eventos de fin se producen en orden LIFO (último en entrar, primero en salir): y (el interno) sale del ámbito antes que x:

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

Este patrón de inserción/extracción es el uso canónico del manejador de fin: mantiene su vista de los espacios de nombres en ámbito alineada con la gestión de ámbito del propio analizador.

Problemas comunes

  • Use xml_parser_create_ns(). Los manejadores de espacio de nombres solo reciben eventos cuando el analizador es consciente de espacios de nombres. Un analizador creado con el simple xml_parser_create() no separará los prefijos de los URIs.
  • Sin URI en el callback de fin. Si necesita el URI cuando el ámbito se cierra, capturelo en el manejador de inicio (indexado por prefijo) y búsquelo aquí.
  • Establezca los manejadores antes de analizar. Registre el manejador antes de la primera llamada a xml_parse(); los manejadores establecidos a mitad del análisis perderán los eventos anteriores.
  • Libere el analizador. Llame a xml_parser_free() cuando termine para liberar recursos, especialmente en scripts de larga ejecución.

Conclusión

xml_set_end_namespace_decl_handler() permite que un analizador SAX indique a su código exactamente cuándo un prefijo de espacio de nombres XML sale del ámbito. Combinado con xml_set_start_namespace_decl_handler() y un analizador consciente de espacios de nombres de xml_parser_create_ns(), le proporciona un control preciso y de bajo consumo de memoria sobre el ámbito de los espacios de nombres mientras procesa documentos XML de gran tamaño en modo streaming.

Práctica

Práctica
¿Cuál es la función de xml_set_end_namespace_decl_handler() en PHP?
¿Cuál es la función de xml_set_end_namespace_decl_handler() en PHP?
Was this page helpful?