xml_parse()
La función xml_parse() es una función integrada de PHP que analiza datos XML de forma eficiente mediante un analizador de estilo SAX.
¿Qué es xml_parse()?
La función xml_parse() es una función integrada de PHP que analiza datos XML. Pertenece a la extensión XML Parser de PHP e implementa un analizador de flujo de estilo SAX (Simple API for XML). A diferencia de los analizadores basados en árboles, procesa el XML de forma secuencial, activando funciones de devolución de llamada cuando encuentra elementos, atributos y datos de caracteres. Esto lo hace muy eficiente para analizar archivos XML grandes sin cargar el documento completo en memoria.
La función xml_parse() es útil cuando necesitas analizar datos XML en PHP, por ejemplo, para extraer datos de un archivo XML, transformar datos XML a otro formato o procesar flujos XML en tiempo real.
Sintaxis
La sintaxis de la función xml_parse() es la siguiente:
xml_parse($parser, $data, $is_final = false): intParámetros
$parser— el identificador del analizador XML devuelto porxml_parser_create(). Es el objeto que mantiene el estado del análisis.$data— un fragmento (o todo) del texto XML que se pasa al analizador.$is_final— establécelo entruecuando pases el último fragmento de datos. Mientras seafalse, el analizador mantiene su estado para que puedas llamar axml_parse()de nuevo con el siguiente fragmento.
Valor de retorno
xml_parse() devuelve 1 (verdadero) en caso de éxito y 0 (falso) en caso de error. No devuelve los datos analizados — el contenido analizado se entrega a las funciones de devolución de llamada que registraste. Cuando devuelve 0, inspecciona el error con xml_get_error_code() y xml_error_string().
Ejemplos de uso
Veamos algunos ejemplos prácticos del uso de xml_parse() en PHP.
Ejemplo 1: Análisis de XML con controladores de eventos
xml_parse() es un analizador SAX: no construye un documento, sino que dispara eventos. Para obtener alguna salida debes registrar funciones controladoras. El ejemplo siguiente utiliza una cadena XML en línea para que se ejecute tal cual, sin ningún archivo externo:
<?php
$xml = <<<XML
<?xml version="1.0"?>
<note>
<to>Tove</to>
<from>Jani</from>
</note>
XML;
$parser = xml_parser_create();
// Keep element names in their original case instead of upper-casing them.
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0);
xml_set_element_handler(
$parser,
fn($p, $name, $attrs) => print("Start: $name\n"),
fn($p, $name) => print("End: $name\n")
);
xml_set_character_data_handler($parser, function ($p, $data) {
$data = trim($data);
if ($data !== "") {
echo "Text: $data\n";
}
});
if (!xml_parse($parser, $xml, true)) {
$code = xml_get_error_code($parser);
echo "Error: " . xml_error_string($code)
. " at line " . xml_get_current_line_number($parser);
}
xml_parser_free($parser);Esto imprime:
Start: note
Start: to
Text: Tove
End: to
Start: from
Text: Jani
End: from
End: noteEl analizador recorre el documento de arriba a abajo y llama a los controladores de inicio de elemento, datos de caracteres y fin de elemento en el orden del documento. Los registramos con xml_set_element_handler() y xml_set_character_data_handler(), pasamos todo en una sola llamada ($is_final = true) y liberamos el analizador con xml_parser_free().
Ejemplo 2: Análisis de un archivo o flujo de datos en fragmentos
La verdadera fortaleza de xml_parse() es el análisis incremental: alimentar el documento de a poco para que incluso un archivo de varios gigabytes no tenga que caber en memoria. Pasa $is_final = false para cada fragmento excepto el último:
<?php
$parser = xml_parser_create();
xml_set_element_handler(
$parser,
fn($p, $name, $attrs) => print("<$name>\n"),
fn($p, $name) => print("</$name>\n")
);
$handle = fopen("data.xml", "r"); // or php://stdin for a stream
while (($chunk = fread($handle, 4096)) !== false) {
$isFinal = feof($handle);
if (!xml_parse($parser, $chunk, $isFinal)) {
$code = xml_get_error_code($parser);
echo "XML error: " . xml_error_string($code)
. " at line " . xml_get_current_line_number($parser);
break;
}
if ($isFinal) {
break;
}
}
fclose($handle);
xml_parser_free($parser);Como el analizador mantiene su estado entre llamadas, un elemento puede comenzar en un fragmento y terminar en otro — xml_parse() une los eventos correctamente. Esto es lo que hace que la función sea adecuada para archivos XML grandes donde un enfoque basado en árbol como SimpleXML agotaría la memoria.
Ejemplo 3 (referencia): análisis de un archivo de una sola vez
Si tu XML es lo suficientemente pequeño como para caber en memoria, puedes leerlo con file_get_contents() y pasar toda la cadena a xml_parse() en una sola llamada. Los controladores también pueden ser funciones con nombre (nombres como cadenas) en lugar de closures:
$xml_parser = xml_parser_create();
xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, 0);
// Define handler functions
function startElement($parser, $name, $attrs) {
echo "Start element: $name\n";
}
function endElement($parser, $name) {
echo "End element: $name\n";
}
function characterData($parser, $data) {
echo "Data: $data\n";
}
// Set handlers
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "characterData");
$xml_data = file_get_contents("data.xml");
if (!xml_parse($xml_parser, $xml_data, true)) {
$error_message = xml_error_string(xml_get_error_code($xml_parser));
$error_line = xml_get_current_line_number($xml_parser);
echo "XML Parsing Error: $error_message at line $error_line";
}
xml_parser_free($xml_parser);Este código crea un analizador XML usando xml_parser_create() y establece una opción para desactivar el plegado de mayúsculas. Luego define tres funciones de devolución de llamada: startElement() para las etiquetas de apertura, endElement() para las etiquetas de cierre y characterData() para el contenido de texto. Estos controladores se registran usando xml_set_element_handler() y xml_set_character_data_handler().
El script lee "data.xml" y lo pasa a xml_parse(). A medida que el analizador recorre el XML, llama automáticamente a los controladores registrados. Si ocurre un error durante el análisis, el código recupera el código y el mensaje de error usando xml_get_error_code() y xml_error_string(), y muestra un error descriptivo. Finalmente, libera la memoria del analizador con xml_parser_free().
Errores comunes
- Sin controladores, sin salida.
xml_parse()solo dispara las devoluciones de llamada que registraste. Sin controladores configurados, analiza correctamente pero no hace nada visible. - Los datos de caracteres llegan en fragmentos. Un único nodo de texto puede activar
xml_set_character_data_handlermás de una vez (por ejemplo, alrededor de referencias a entidades), por lo que debes acumular el texto en un búfer en lugar de asumir que lo recibes todo de una vez. - Los espacios en blanco cuentan como datos de caracteres. La sangría entre etiquetas activa el controlador de datos de caracteres. Usa
trim()(como en el Ejemplo 1) si solo te interesan los textos reales. - Libera siempre el analizador. Llama a
xml_parser_free()cuando termines; en PHP 8+ el identificador es un objetoXMLParserque se recolecta como basura, pero liberarlo explícitamente mantiene ajustada la memoria en scripts de larga ejecución.
Funciones relacionadas
xml_parser_create()— crea el identificador del analizador que pasas axml_parse().xml_set_element_handler()— registra devoluciones de llamada para etiquetas de inicio/fin.xml_set_character_data_handler()— registra la devolución de llamada para el contenido de texto.xml_parse_into_struct()— analiza XML en un array plano en lugar de disparar eventos.- SimpleXML — una alternativa de mayor nivel, basada en árbol, para documentos pequeños.
Conclusión
La función xml_parse() de PHP es el motor de la extensión XML Parser de estilo SAX. En lugar de devolver un documento, recorre el XML en flujo y dispara los controladores que registras, devolviendo 1 en caso de éxito y 0 en caso de error. Su parámetro $is_final te permite analizar datos en fragmentos, lo que explica que se mantenga eficiente en memoria incluso con archivos enormes. Combínala con xml_parser_create(), las funciones de configuración de controladores y xml_parser_free(), y tendrás una forma rápida y de bajo consumo de memoria para procesar XML en PHP.