Existen muchas técnicas para leer y escribir XML con PHP. Este artículo proporciona tres métodos para leer XML: usar una biblioteca DOM, usar un analizador SAX y usar expresiones regulares. También se cubre la escritura de XML utilizando plantillas de texto DOM y PHP.
Leer y escribir lenguaje de marcado extensible (XML) en PHP puede parecer un poco aterrador. De hecho, XML y todas sus tecnologías relacionadas pueden dar miedo, pero leer y escribir XML en PHP no tiene por qué ser una tarea aterradora. Primero, necesita aprender un poco sobre XML: qué es y qué puede hacer con él. Luego, necesita aprender a leer y escribir XML en PHP, y hay muchas formas de hacerlo.
Este artículo proporciona una breve introducción a XML y luego explica cómo leer y escribir XML con PHP.
¿Qué es XML?
XML es un formato de almacenamiento de datos. No define qué datos se guardan ni define el formato de los datos. XML simplemente define etiquetas y los atributos de esas etiquetas. El marcado XML bien formado se ve así:
<nombre>Jack Herrington</nombre>
Esta etiqueta <nombre> contiene algo de texto: Jack Herrington.
El marcado XML sin texto se ve así:
<encender/>
Hay más de una forma de escribir algo en XML. Por ejemplo, esta etiqueta genera el mismo resultado que la etiqueta anterior:
<encender></encender>
También puede agregar atributos a etiquetas XML. Por ejemplo, esta etiqueta <nombre> contiene el primer y el último atributo:
<nombre primero="Jack" último="Herrington" />
Los caracteres especiales también se pueden codificar en XML. Por ejemplo, el símbolo & se puede codificar así:
&
Un archivo XML que contiene etiquetas y atributos está bien formado si tiene el formato del ejemplo, lo que significa que las etiquetas son simétricas y los caracteres están codificados correctamente. El Listado 1 es un ejemplo de XML bien formado.
Listado 1. Ejemplo de lista de libros XML
<libros>
<libro>
<autor>Jack Herrington</autor>
<título>Hacks de PHP</título>
<editor>O'Reilly</editor>
</libro>
<libro>
<autor>Jack Herrington</autor>
<título>Trucos de podcasting</título>
<editor>O'Reilly</editor>
</libro>
</libros>
|
El XML del Listado 1 contiene una lista de libros. La etiqueta principal <books> contiene un conjunto de etiquetas <book>, cada una de las cuales contiene etiquetas <author>, <title> y <publisher>.
Un documento XML es correcto cuando su estructura de marcado y su contenido son verificados por un archivo de esquema externo. Los archivos de esquema se pueden especificar en diferentes formatos. Para este artículo, todo lo que se necesita es XML bien formado.
Si cree que XML se parece mucho al lenguaje de marcado de hipertexto (HTML), tiene razón. Tanto XML como HTML son lenguajes basados en marcado y tienen muchas similitudes. Sin embargo, es importante señalar que, si bien un documento XML puede ser HTML bien formado, no todos los documentos HTML son XML bien formados. La etiqueta de nueva línea (br) es un buen ejemplo de la diferencia entre XML y HTML. Esta etiqueta de nueva línea es HTML bien formado, pero no XML bien formado:
<p>Este es un párrafo<br>
Con un salto de línea</p>
Esta etiqueta de nueva línea es XML y HTML bien formado:
<p>Este es un párrafo<br />
Con un salto de línea</p>
Si desea escribir HTML como XML bien formado, siga el estándar del lenguaje de marcado de hipertexto extensible (XHTML) del comité W3C (consulte Recursos ). Todos los navegadores modernos pueden representar XHTML. Además, puede utilizar herramientas XML para leer XHTML y encontrar los datos en el documento, lo cual es mucho más fácil que analizar HTML.
Leer XML usando la biblioteca DOM
La forma más sencilla de leer archivos XML bien formados es utilizar la biblioteca del Modelo de objetos de documento (DOM) compilada en algunas instalaciones de PHP. La biblioteca DOM lee el documento XML completo en la memoria y lo representa como un árbol de nodos, como se muestra en la Figura 1.
Figura 1. Árbol XML DOM para libro XML
El nodo de libros en la parte superior del árbol tiene dos etiquetas de libros secundarios. En cada libro existen varios nodos: autor, editorial y título. Los nodos de autor, editor y título tienen nodos secundarios de texto que contienen texto.
El código que lee el archivo XML del libro y muestra el contenido usando el DOM se muestra en el Listado 2.
Listado 2. Lectura de un libro XML usando DOM
<?php
$doc = nuevo DOMDocumento();
$doc->cargar( 'libros.xml' );
$libros = $doc->getElementsByTagName( "libro" );
foreach($libros como $libro)
{
$autores = $libro->getElementsByTagName( "autor" );
$autor = $autores->item(0)->nodeValue;
$editores = $libro->getElementsByTagName( "editor" );
$editor = $editores->item(0)->nodeValue;
$títulos = $libro->getElementsByTagName( "título" );
$título = $títulos->item(0)->nodeValue;
echo "$título - $autor - $editorn";
}
?>
|
El script primero crea un nuevo objeto DOMdocument y carga el libro XML en este objeto usando el método de carga. Luego, el script utiliza el método getElementsByName para obtener una lista de todos los elementos bajo el nombre especificado.
En el bucle del nodo del libro, el script utiliza el método getElementsByName para obtener el valor de nodo de las etiquetas de autor, editor y título. nodeValue es el texto en el nodo. Luego, el script muestra estos valores.
Puede ejecutar scripts PHP en la línea de comando de esta manera:
%phpe1.php
Hacks de PHP - Jack Herrington - O'Reilly
Trucos de podcasting - Jack Herrington - O'Reilly
%
Como puede ver, cada bloque de libro genera una línea. Éste es un buen comienzo. ¿Pero qué pasa si no tienes acceso a la biblioteca XML DOM?
Leer XML con el analizador SAX
Otra forma de leer XML es utilizar un analizador XML Simple API (SAX). La mayoría de las instalaciones de PHP incluyen un analizador SAX. El analizador SAX se ejecuta en un modelo de devolución de llamada. Cada vez que se abre o cierra una etiqueta, o cada vez que el analizador ve texto, se vuelve a llamar a la función definida por el usuario con información sobre el nodo o el texto.
La ventaja del analizador SAX es que es verdaderamente liviano. El analizador no mantiene el contenido en la memoria durante largos períodos de tiempo, por lo que puede usarse para archivos muy grandes. La desventaja es que escribir devoluciones de llamada del analizador SAX es muy engorroso. El Listado 3 muestra el código que utiliza SAX para leer un archivo XML de un libro y mostrar el contenido.
Listado 3. Lectura de un libro XML con el analizador SAX
<?php
$g_libros = matriz();
$g_elem = nulo;
función startElement ($ analizador, $ nombre, $ atributos)
{
global $g_libros, $g_elem;
if ( $nombre == 'LIBRO' ) $g_books []= matriz();
$g_elem = $nombre;
}
función endElement ($ analizador, $ nombre)
{
global$g_elem;
$g_elem = nulo;
}
función textData ($ analizador, $ texto)
{
global $g_libros, $g_elem;
if ( $g_elem == 'AUTOR' ||
$g_elem == 'EDITORIAL' ||
$g_elem == 'TÍTULO' )
{
$g_libros[ recuento( $g_libros ) - 1 ][ $g_elem ] = $texto;
}
}
$parser = xml_parser_create();
xml_set_element_handler( $parser, "startElement", "endElement");
xml_set_character_data_handler ($parser, "textData");
$f = fopen( 'libros.xml', 'r' );
mientras( $datos = fread( $f, 4096 ) )
{
xml_parse( $analizador, $datos );
}
xml_parser_free ($ analizador);
foreach($g_books como $libro)
{
echo $libro['TÍTULO']." - ".$libro['AUTOR']." - ";
echo $libro['PUBLICADOR']."n";
}
?>
|
El script primero configura la matriz g_books, que contiene todos los libros y la información del libro en la memoria, y la variable g_elem contiene el nombre de la etiqueta que el script está procesando actualmente. Luego, el script define la función de devolución de llamada. En este ejemplo, las funciones de devolución de llamada son startElement, endElement y textData. Al abrir y cerrar la marca, llame a las funciones startElement y endElement respectivamente. TextData se llama en el texto entre las etiquetas de apertura y cierre.
En este ejemplo, la etiqueta startElement busca la etiqueta del libro para iniciar un nuevo elemento en la matriz del libro. Luego, la función textData mira el elemento actual para ver si es una etiqueta de editor, título o autor. Si es así, la función coloca el texto actual en el libro actual.
Para permitir que el análisis continúe, el script crea un analizador utilizando la función xml_parser_create. Luego, configure el identificador de devolución de llamada. Luego, el script lee el archivo y envía fragmentos del mismo al analizador. Una vez leído el archivo, la función xml_parser_free elimina el analizador. El final del script genera el contenido de la matriz g_books.
Como puede ver, esto es mucho más difícil que escribir la misma funcionalidad en el DOM. ¿Qué pasa si no hay una biblioteca DOM ni una biblioteca SAX? ¿Hay alguna alternativa?
Analizar XML con expresiones regulares
Estoy seguro de que algunos ingenieros me criticarán por siquiera mencionar este método, pero es posible analizar XML con expresiones regulares. El Listado 4 muestra un ejemplo del uso de la función preg_ para leer un archivo de libro.
Listado 4. Lectura de XML con expresiones regulares
<?php
$xml = "";
$f = fopen( 'libros.xml', 'r' );
while( $datos = fread( $f, 4096 ) ) { $xml .= $datos }
cerrar ($f);
preg_match_all( "/<libro>(.*?)</libro>/s",
$xml, $bloques de libros);
foreach( $bloquesdelibros[1] como $bloque )
{
preg_match_all( "/<autor>(.*?)</autor>/",
$bloque, $autor);
preg_match_all( "/<título>(.*?)</título>/",
$bloque, $título);
preg_match_all( "/<publisher>(.*?)</publisher>/",
$bloque, $editor);
echo( $título[1][0]." - ".$autor[1][0]." - ".
$editor[1][0]."n" );
}
?>
|
Observe lo corto que es este código. Inicialmente, lee el archivo en una cadena grande. Luego use una función de expresión regular para leer cada elemento del libro. Finalmente, use un bucle foreach para recorrer cada bloque de libro y extraer el autor, el título y el editor.
Entonces, ¿dónde están los defectos? El problema con el uso de código de expresión regular para leer XML es que no verifica primero que el XML esté bien formado. Esto significa que no hay forma de saber si el XML está bien formado antes de leerlo. Además, es posible que algunos archivos XML bien formados no coincidan con la expresión regular, por lo que deberán modificarse más adelante.
Nunca recomiendo usar expresiones regulares para leer XML, pero a veces es la mejor manera de lograr compatibilidad porque las funciones de expresiones regulares siempre están disponibles. No utilice expresiones regulares para leer XML directamente del usuario porque no tiene control sobre el formato o la estructura de dicho XML. Siempre debes usar una biblioteca DOM o un analizador SAX para leer XML del usuario. Escribir XML usando DOM
Leer XML es sólo una parte de la ecuación. ¿Cómo escribir XML? La mejor manera de escribir XML es utilizar DOM. El Listado 5 muestra cómo el DOM construye el archivo XML del libro.
Listado 5. Escribir un libro XML usando DOM
<?php
$libros = matriz();
$libros [] = matriz(
'título' => 'Trucos PHP',
'autor' => 'Jack Herrington',
'editor' => "O'Reilly"
);
$libros [] = matriz(
'title' => 'Trucos de podcasting',
'autor' => 'Jack Herrington',
'editor' => "O'Reilly"
);
$doc = nuevo DOMDocumento();
$doc->formatoSalida = verdadero;
$r = $doc->createElement( "libros" );
$doc->appendChild( $r );
foreach($libros como $libro)
{
$b = $doc->createElement( "libro" );
$autor = $doc->createElement( "autor" );
$autor->appendChild(
$doc->createTextNode( $libro['autor'] )
);
$b->appendChild( $autor );
$título = $doc->createElement( "título" );
$título->appendChild(
$doc->createTextNode( $libro['título'] )
);
$b->appendChild( $título);
$editor = $doc->createElement( "editor" );
$editor->appendChild(
$doc->createTextNode( $libro['editor'] )
);
$b->appendChild( $editor);
$r->appendChild( $b );
}
eco $doc->saveXML();
?>
|
En la parte superior del script, la matriz de libros está cargada con algunos libros de muestra. Estos datos pueden provenir del usuario o de la base de datos.
Una vez cargados los libros de muestra, el script crea un nuevo DOMDocument y le agrega el nodo de libros raíz. Luego, el script crea nodos para el autor, título y editorial de cada libro, y agrega nodos de texto a cada nodo. El paso final para cada nodo de libro es volver a agregarlo a los libros del nodo raíz.
Al final del script, utilice el método saveXML para enviar el XML a la consola. (También puede utilizar el método guardar para crear un archivo XML). El resultado del script se muestra en el Listado 6.
Listado 6. Salida del script de compilación DOM
%phpe4.php
<?xml versión="1.0"?>
<libros>
<libro>
<autor>Jack Herrington</autor>
<título>Hacks de PHP</título>
<editor>O'Reilly</editor>
</libro>
<libro>
<autor>Jack Herrington</autor>
<título>Trucos de podcasting</título>
<editor>O'Reilly</editor>
</libro>
</libros>
%
|
El valor real de usar DOM es que el XML que crea siempre está bien formado. Pero, ¿qué pasa si no puedes crear XML usando DOM?
Escribir XML en PHP
Si el DOM no está disponible, se puede escribir XML utilizando las plantillas de texto de PHP. El Listado 7 muestra cómo PHP construye el archivo XML del libro.
Listado 7. Escribir un libro XML en PHP
<?php
$libros = matriz();
$libros [] = matriz(
'título' => 'Trucos PHP',
'autor' => 'Jack Herrington',
'editor' => "O'Reilly"
);
$libros [] = matriz(
'title' => 'Trucos de podcasting',
'autor' => 'Jack Herrington',
'editor' => "O'Reilly"
);
?>
<libros>
<?php
foreach($libros como $libro)
{
?>
<libro>
<título><?php echo( $libro['título'] ?></título>);
<autor><?php echo( $libro['autor'] ?>);
</autor>
<editor><?php echo( $libro['editor'] ?>);
</editor>
</libro>
<?php
}
?>
</libros>
|
La parte superior del script es similar a un script DOM. La parte inferior del script abre la etiqueta de libros y luego recorre cada libro, creando la etiqueta de libro y todas las etiquetas internas de título, autor y editor.
El problema con este enfoque es codificar las entidades. Para garantizar que las entidades estén codificadas correctamente, se debe llamar a la función htmlentities en cada elemento, como se muestra en el Listado 8.
Listado 8. Codificación de entidades usando la función htmlentities
<libros>
<?php
foreach($libros como $libro)
{
$título = htmlentities( $libro['título'], ENT_QUOTES);
$autor = htmlentities( $libro['autor'], ENT_QUOTES);
$editor = htmlentities( $libro['editor'], ENT_QUOTES);
?>
<libro>
<título><?php echo( $título ?></título>);
<autor><?php echo( $autor ?> </autor>);
<editor><?php echo( $editor ?>);
</editor>
</libro>
<?php
}
?>
</libros>
|
Aquí es donde escribir XML en PHP básico se vuelve molesto. Cree que ha creado un XML perfecto, pero tan pronto como intenta utilizar los datos, descubre que algunos elementos están codificados incorrectamente.
Conclusión
Siempre hay mucha exageración y confusión en torno a XML. Sin embargo, no es tan difícil como crees, especialmente en un lenguaje tan bueno como PHP. Una vez que comprenda e implemente XML correctamente, encontrará muchas herramientas poderosas a su disposición. XPath y XSLT son dos de esas herramientas que vale la pena estudiar.