W3docs

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): int

Parámetros

  • $parser — el identificador del analizador XML devuelto por xml_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 en true cuando pases el último fragmento de datos. Mientras sea false, el analizador mantiene su estado para que puedas llamar a xml_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:   note

El 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_handler má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 objeto XMLParser que se recolecta como basura, pero liberarlo explícitamente mantiene ajustada la memoria en scripts de larga ejecución.

Funciones relacionadas

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.

Práctica

Práctica
¿Qué es XML Parser en PHP?
¿Qué es XML Parser en PHP?
Was this page helpful?