W3docs

xml_set_character_data_handler()

La función xml_set_character_data_handler() de PHP registra una función definida por el usuario como manejador de datos de carácter en un analizador XML.

La función xml_set_character_data_handler() registra un callback definido por el usuario que el analizador XML invoca cada vez que encuentra datos de carácter — el contenido de texto que se encuentra entre las etiquetas XML. Pertenece a la extensión xml heredada, que envuelve el analizador Expat orientado a eventos, por lo que forma parte de la API de análisis basada en flujos ("estilo SAX") de PHP en lugar de los enfoques basados en árbol DOMDocument o SimpleXML.

Se recurre a esta función cuando se desea capturar o transformar el texto dentro de los elementos mientras el documento se procesa en flujo continuo — por ejemplo, recopilando el título de cada <item> en un feed RSS, o realizando una transformación sobre el texto extraído sin necesidad de construir el documento completo en memoria. Casi siempre se usa junto con xml_set_element_handler(), que indica a qué elemento pertenece el texto.

Aviso: La extensión xml es heredada. Para código nuevo, se recomienda usar SimpleXML o DOMDocument. Utilice este manejador cuando esté manteniendo analizadores existentes basados en Expat o cuando realmente necesite procesamiento en flujo orientado a eventos para documentos muy grandes.

Sintaxis

xml_set_character_data_handler(XMLParser $parser, callable $handler): bool
  • $parser — el analizador creado por xml_parser_create().
  • $handler — el callback que se invoca para los datos de carácter. Se puede pasar el nombre de una función como string, una clausura o un array para un callback de método. Pasar una cadena vacía "" elimina un manejador previamente registrado.

La función devuelve true en caso de éxito.

La firma del manejador

Su manejador recibe dos argumentos — el analizador y el fragmento de texto:

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

Documentación más antigua a veces muestra un tercer parámetro $length, pero la extensión xml basada en Expat no lo pasa. En PHP 8+, declarar un tercer parámetro requerido lanza un ArgumentCountError, por lo que debe mantener su manejador con dos parámetros (o hacer que los adicionales sean opcionales).

Ejemplos de uso

Ejemplo 1: Un manejador de datos de carácter mínimo

Cree un analizador, adjunte un manejador y aliméntelo con una cadena XML. El manejador simplemente imprime el texto recortado que recibe:

function handle_character_data($parser, $data) {
    echo trim($data);
}

$xml_parser = xml_parser_create();
xml_set_character_data_handler($xml_parser, "handle_character_data");

$xml_data = '<root><item>Hello World</item></root>';
xml_parse($xml_parser, $xml_data, true);

xml_parser_free($xml_parser);
// Output: Hello World

xml_parser_create() construye el analizador, xml_set_character_data_handler() conecta el callback, xml_parse() procesa los datos en flujo (el true final indica que es el último fragmento), y xml_parser_free() libera el analizador.

El problema del fragmentado

El analizador puede llamar a su manejador múltiples veces por un mismo elemento, y también se activa para los espacios en blanco entre elementos. No le entrega una cadena ordenada por elemento. Observe lo que ocurre con dos elementos y algo de sangría:

function show($parser, $data) {
    echo '[' . $data . "]\n";
}

$p = xml_parser_create();
xml_set_character_data_handler($p, "show");

$xml = '<root><item>Hello World</item>  <item>Goodbye</item></root>';
xml_parse($p, $xml, true);
xml_parser_free($p);

// Output:
// [Hello World]
// [  ]
// [Goodbye]

El espacio de dos caracteres entre </item> y el siguiente <item> genera su propia llamada. El texto largo también puede llegar dividido en varias llamadas. Por ello, se debe acumular los datos en un búfer y actuar sobre ellos solo cuando se sepa que el elemento ha terminado.

Ejemplo 2: Acumulando texto con un manejador de elementos

El patrón fiable es: reiniciar un búfer cuando comienza un elemento, añadir cada fragmento de datos de carácter, y leer el búfer cuando el elemento termina. Por eso xml_set_element_handler() casi siempre se usa junto con esta función.

$buffer = '';

function start_element($parser, $name, $attrs) {
    global $buffer;
    $buffer = '';            // start collecting fresh text
}

function character_data($parser, $data) {
    global $buffer;
    $buffer .= $data;        // chunks may arrive in pieces — append
}

function end_element($parser, $name) {
    global $buffer;
    $text = trim($buffer);
    if ($text !== '') {
        echo "$name: $text\n";
    }
}

$parser = xml_parser_create();
xml_set_element_handler($parser, "start_element", "end_element");
xml_set_character_data_handler($parser, "character_data");

$xml = '<books><title>PHP Basics</title><title>Advanced XML</title></books>';
xml_parse($parser, $xml, true);
xml_parser_free($parser);

// Output:
// TITLE: PHP Basics
// TITLE: Advanced XML

Los nombres de los elementos llegan en mayúsculas de forma predeterminada porque el analizador normaliza el caso. Para mantener el formato original, deshabilite el plegado de mayúsculas con xml_parser_set_option():

xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);

Errores comunes

  • Asumir una sola llamada por elemento. Como se muestra arriba, los datos de carácter pueden entregarse en varios fragmentos; acumule siempre en un búfer.
  • Llamadas con solo espacios en blanco. La sangría y los saltos de línea entre etiquetas activan el manejador con espacios en blanco. Filtrelos con trim() antes de actuar.
  • Un tercer parámetro en el manejador. El manejador Expat solo pasa $parser y $data; un parámetro $length requerido provoca un ArgumentCountError.
  • Registrar el manejador después del análisis. Adjunte todos los manejadores antes de llamar a xml_parse(), o los eventos ya habrán pasado.

Conclusión

xml_set_character_data_handler() registra un callback para el texto entre etiquetas XML en la extensión xml heredada de PHP basada en Expat. Su manejador recibe dos argumentos — el analizador y el fragmento de datos — y puede activarse varias veces por elemento, incluidos los espacios en blanco, por lo que el enfoque fiable es acumular el texto en un búfer y procesarlo cuando el elemento termine mediante xml_set_element_handler(). Para proyectos nuevos, se prefiere las APIs modernas SimpleXML o DOMDocument; recurra a esta función cuando mantenga analizadores existentes o procese documentos muy grandes en flujo continuo.

Práctica

Práctica
¿Qué hace la función 'xml_set_character_data_handler()' en PHP?
¿Qué hace la función 'xml_set_character_data_handler()' en PHP?
Was this page helpful?