W3docs

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ámetroDescripción
$parserEl analizador creado por xml_parser_create().
$start_handlerSe llama en cada etiqueta de apertura. Recibe ($parser, $name, $attributes).
$end_handlerSe 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$name es el nombre de la etiqueta y $attributes es 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 como BOOK). Compara los nombres sin distinguir mayúsculas de minúsculas, o desactiva la conversión con xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, false). Consulta xml_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:   LIBRARY

Observa 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: 3

Cuá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.

Práctica

Práctica
¿Para qué se usa la función xml_set_element_handler() en PHP?
¿Para qué se usa la función xml_set_element_handler() en PHP?
Was this page helpful?