xml_set_unparsed_entity_decl_handler()
La función xml_set_unparsed_entity_decl_handler() de PHP define un callback para manejar declaraciones de entidades no analizadas en un parser XML SAX.
La función xml_set_unparsed_entity_decl_handler() define un callback personalizado como manejador de declaraciones de entidades no analizadas en un parser XML. Pertenece a la extensión XML Parser (SAX) de PHP y forma parte de la misma familia que xml_set_element_handler() y xml_set_character_data_handler() — no aplica a SimpleXML ni al DOM.
Una entidad no analizada es una entidad cuyo contenido el procesador XML no debe analizar como XML — típicamente una referencia a datos binarios externos como una imagen, PDF o archivo de audio. Se declara con la palabra clave NDATA seguida de un nombre de notación, por ejemplo:
<!ENTITY logo SYSTEM "logo.png" NDATA png>Cuando el parser encuentra dicha declaración en el DTD del documento, invoca tu manejador para que puedas registrar dónde reside el recurso en lugar de intentar cargarlo como marcado.
Sintaxis
xml_set_unparsed_entity_decl_handler(
XMLParser $parser,
callable $handler
): true| Parámetro | Descripción |
|---|---|
$parser | El parser XML creado con xml_parser_create(). |
$handler | Un callable, o el nombre en string de una función. Pasa una cadena vacía ("") para eliminar el manejador actual. |
Valor de retorno: siempre devuelve true.
Nota PHP 8: desde PHP 8.0 el parser es un objeto
XMLParseren lugar de unresource, pero el código que se escribe es idéntico — sigue tratando el valor que devuelvexml_parser_create()como un handle opaco.
La firma del callback
Tu manejador se invoca con seis argumentos, en este orden:
handler(
XMLParser $parser,
string $entityName, // e.g. "logo"
string $base, // base URI used to resolve the system id (often empty)
string $systemId, // e.g. "logo.png"
string $publicId, // public id, if any
string $notationName // e.g. "png" — declared with xml_set_notation_decl_handler()
): voidEjemplo: capturar declaraciones de entidades no analizadas
Crea un parser SAX con xml_parser_create(), registra el manejador y luego alimenta el XML a xml_parse():
<?php
function handleUnparsedEntity($parser, $name, $base, $systemId, $publicId, $notationName) {
echo "Unparsed entity '$name' -> $systemId (notation: $notationName)\n";
}
$xmlParser = xml_parser_create();
xml_set_unparsed_entity_decl_handler($xmlParser, "handleUnparsedEntity");
$xml = '<?xml version="1.0"?>
<!DOCTYPE catalog [
<!NOTATION png SYSTEM "image/png">
<!ENTITY logo SYSTEM "logo.png" NDATA png>
<!ENTITY manual SYSTEM "manual.pdf" NDATA pdf>
]>
<catalog/>';
xml_parse($xmlParser, $xml, true);
xml_parser_free($xmlParser);Salida esperada:
Unparsed entity 'logo' -> logo.png (notation: png)
Unparsed entity 'manual' -> manual.pdf (notation: pdf)El manejador se ejecuta una vez por cada entidad NDATA del DTD, proporcionando la ruta del archivo ($systemId) y la notación. Una aplicación real almacenaría estas referencias — por ejemplo, para descargar los recursos más tarde — en lugar de mostrarlos por pantalla.
Errores comunes
- El DTD debe contener declaraciones
NDATA. Una entidad interna normal (<!ENTITY name "value">) es texto analizado, por lo que este manejador nunca la ve. Solo las entidades marcadas conNDATA notationson "no analizadas". - Registra los manejadores antes de llamar a
xml_parse(). Como cualquier funciónxml_set_*_handler(), esta no tiene efecto una vez que el análisis ha comenzado. - Libera el parser con
xml_parser_free()cuando hayas terminado para liberar recursos. - No aplica en SimpleXML. Si estás leyendo XML bien formado y no necesitas reaccionar a las declaraciones de entidades del DTD, el parser SimpleXML suele ser la mejor opción.
Funciones relacionadas
xml_parser_create()— crea el parser SAX al que se asocia este manejador.xml_set_notation_decl_handler()— maneja las declaraciones<!NOTATION ...>referenciadas por entidades no analizadas.xml_set_external_entity_ref_handler()— maneja referencias a entidades externas analizadas.xml_set_element_handler()— maneja eventos de inicio/fin de elementos.
Conclusión
xml_set_unparsed_entity_decl_handler() permite que un parser SAX te notifique sobre entidades NDATA — referencias a datos binarios externos — para que puedas capturar sus rutas y notaciones sin intentar analizarlas como XML. Registra el manejador antes de xml_parse(), espera el callback con seis argumentos y recuerda que la función solo aplica a la extensión procedural XML Parser, no a SimpleXML ni al DOM.