xml_set_element_handler()
La función xml_set_element_handler() en PHP define funciones de usuario como manejadores para las etiquetas de apertura y cierre de un elemento XML.
xml_set_element_handler() registra dos callbacks en un analizador XML: uno que se activa cada vez que el analizador encuentra una etiqueta de apertura (<book>) y otro que se activa en cada etiqueta de cierre (</book>). Pertenece al analizador Expat de PHP basado en eventos — la familia xml_parser_* — no a SimpleXML ni al DOM. Mientras SimpleXML carga el documento completo en un árbol en memoria, Expat recorre el documento en flujo continuo y llama a tus manejadores a medida que avanza, lo que lo hace muy adecuado para archivos grandes que no deseas cargar todos a la vez.
Esta página cubre la firma de la función, los argumentos exactos que reciben tus manejadores, un ejemplo completo ejecutable y los errores más comunes (conversión de mayúsculas en nombres de etiquetas y la forma de callback mediante métodos de objeto).
Sintaxis
xml_set_element_handler(
XMLParser $parser,
callable $start_handler,
callable $end_handler
): bool| Parámetro | Descripción |
|---|---|
$parser | El analizador creado por xml_parser_create(). |
$start_handler | Se llama en cada etiqueta de apertura. Recibe ($parser, $name, $attributes). |
$end_handler | Se llama en cada etiqueta de cierre. Recibe ($parser, $name). |
La función devuelve true en caso de éxito y false en caso de fallo. Un callback puede proporcionarse como una cadena con el nombre de la función ("startTag"), una clausura o un par objeto-método ([$object, 'method']).
Qué reciben los manejadores
- Manejador de inicio —
$namees el nombre de la etiqueta y$attributeses un array asociativo con los atributos de esa etiqueta (['ID' => 'b1']). - Manejador de fin — solo
$name, ya que las etiquetas de cierre no llevan atributos.
Por defecto, Expat convierte los nombres de etiquetas y atributos a mayúsculas (
<book>llega comoBOOK). Compara los nombres sin distinguir mayúsculas de minúsculas, o desactiva la conversión conxml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false). Consultaxml_parser_set_option().
Ejemplos de uso
Ejemplo: Imprimir el árbol de elementos
Este script completo analiza una cadena XML y utiliza los manejadores de inicio/fin para imprimir un esquema indentado del documento, incluyendo los atributos de cada etiqueta.
<?php
$xml = '<?xml version="1.0"?>
<library>
<book id="b1">PHP Basics</book>
<book id="b2">Advanced XML</book>
</library>';
$depth = 0;
function startTag($parser, $name, $attrs) {
global $depth;
echo str_repeat(" ", $depth) . "START: $name";
foreach ($attrs as $key => $value) {
echo " ($key=\"$value\")";
}
echo "\n";
$depth++;
}
function endTag($parser, $name) {
global $depth;
$depth--;
echo str_repeat(" ", $depth) . "END: $name\n";
}
$parser = xml_parser_create();
xml_set_element_handler($parser, "startTag", "endTag");
if (!xml_parse($parser, $xml, true)) {
die(sprintf(
"XML error: %s at line %d",
xml_error_string(xml_get_error_code($parser)),
xml_get_current_line_number($parser)
));
}
xml_parser_free($parser);Salida:
START: LIBRARY
START: BOOK (ID="b1")
END: BOOK
START: BOOK (ID="b2")
END: BOOK
END: LIBRARYObserva que library llega como LIBRARY y id como ID: esa es la conversión a mayúsculas mencionada anteriormente. El tercer argumento de xml_parse() se establece en true para indicarle al analizador que este es el fragmento final (y único) de datos. Siempre libera el analizador con xml_parser_free() cuando hayas terminado.
Ejemplo: Usar un método de objeto como manejador
Los manejadores no tienen que ser funciones independientes. Pasar [$object, 'method'] te permite mantener el estado del análisis en un objeto en lugar de en variables globales — útil cuando varios manejadores necesitan compartir datos.
<?php
$xml = '<note><to>Tove</to><from>Jani</from></note>';
class TagCounter {
public int $open = 0;
public function onStart($parser, $name, $attrs) { $this->open++; }
public function onEnd($parser, $name) {}
}
$counter = new TagCounter();
$parser = xml_parser_create();
xml_set_element_handler($parser, [$counter, 'onStart'], [$counter, 'onEnd']);
xml_parse($parser, $xml, true);
xml_parser_free($parser);
echo "Opening tags seen: {$counter->open}\n";Salida:
Opening tags seen: 3Cuándo usarlo
Recurre a los manejadores de Expat cuando necesites un recorrido en flujo continuo y con poco uso de memoria sobre XML — feeds grandes, archivos de registro o sitemaps — o cuando solo te interesen algunas etiquetas y no quieras construir un árbol completo. Para leer el texto dentro de un elemento (el PHP Basics en <book>PHP Basics</book>), combina esto con xml_set_character_data_handler(). Si prefieres consultar un documento pequeño con acceso similar a XPath, SimpleXML es más sencillo. Para una visión general de cada enfoque, consulta PHP XML Parsers.
Conclusión
xml_set_element_handler() conecta callbacks de etiquetas de inicio y fin al analizador Expat de PHP basado en eventos, permitiéndote reaccionar a la estructura de un documento a medida que se procesa en flujo. Recuerda los tres puntos esenciales: crea el analizador primero, ten en cuenta los nombres de etiquetas en mayúsculas y libera el analizador cuando hayas terminado.