Cómo acceder a los datos de XML en PHP

Bien, ahora si dedicaré una entrada completa al manejo de XML en PHP5. Veremos un ejemplo fácil y de paso servirá como explicación al funcionamiento de plugin que muestra la foto astronómica del día.

Lo primero de lo que hay que asegurarnos es de que el XML que vamos a parsear es válido. Esto significa que debe estar bien formado (un sólo elemento raíz, etiquetas abiertas y cerradas correctamente, anidaciones válidas, etc) y debe obedecer a un DTD. Después de segurarnos de esto, lo que sigue es trabajar sobre PHP5.

¿Por qué PHP5? por dos razones, una, nos da una orientación a objetos más eficiente que a versión 4 y, dos, nos provee de la extensión SimpleXMLElement que es con la trabajaremos el XML. ¿A caso PHP4 no tiene extensiones que hagan lo mismo? No lo sé, ni me interesa. PHP5 es mejor.

Bien, empecemos. Supongamos que tenemos un archivo XML llamado library.xml con el siguiente contenido:

<?xml version="1.0" ?>
<library>
	<book isbn="0345342968">
		<title>Fahrenheit 451</title>
		<author>R. Bradbury</author>
		<publisher>Del Rey</publisher>
	</book>
	<book isbn="0048231398">
		<title>The Silmarillion</title>
		<author>J.R.R. Tolkien</author>
		<publisher>G. Allen & Unwin</publisher>
	</book>
	<book isbn="0451524934">
		<title>1984</title>
		<author>G. Orwell</author>
		<publisher>Signet</publisher>
	</book>
	<book isbn="031219126X">
		<title>Frankenstein</title>
		<author>M. Shelley</author>
		<publisher>Bedford</publisher>
	</book>
	<book isbn="0312863551">
		<title>The Moon Is a Harsh Mistress</title>
		<author>R. A. Heinlein</author>
		<publisher>Orb</publisher>
	</book>
</library>

Y supongamos que lo que queremos hacer es una tabla con todos los libros y sus respectivos datos:

Title Author Publisher ISBN
Fahrenheit 451 R. Bradbury Del Rey 0345342968
The Silmarillion J.R.R. Tolkien G. Allen & Unwin 0048231398
1984 G. Orwell Signet 0451524934
Frankenstein M. Shelley Bedford 031219126X
The Moon Is a Harsh Mistress R. A. Heinlein Orb 0312863551

Debemos hacer una instancia de la clase SimpleXMLElement. Hay varias formas de hacerlo. Las dos primeras envuelven el uso de programación estructurada o usan funciones que solo regresan objetos SimpleXML.

// Carga una cadena XML desde un archivo...
$xmlstr = file_get_contents( 'library.xml' );
$library = simplexml_load_string( $xmlstr );

// Carga un archivo XML
$library = simplexml_load_file( 'library.xml' );

Las dos formas al final hacen lo mismo. Sin embargo en un escenario real definitivamente nos vamos por la segunda. Hay otras dos formas que implican el uso de algo más orientado a objetos:

// Carga una cadena XML desde un archivo...
$xmlstr = file_get_contents( 'library.xml' );
$library = new SimpleXMLElement( $xmlstr );

// Carga un archivo XML
$library = new SimpleXMLElement('library.xml', null, true);

Ahora sí, de las cuatro formas, recomiendo la última. El segundo argumento no tiene aplicación práctica para este ejemplo y el tercero es solo para informar al constructor que el primer parámetro es una ruta a un archivo y no una cadena XML.

Aquí viene lo interesante, el acceso a los hijos y atributos. He aquí por qué SimpleXMLElement hace magia; convierte a todos los nodos del árbol XML en atributos de clase y los atributos del XML mismo los convierte en variables a las que podemos acceder como arreglos asociativos.

Si hasta aquí todo va claro, entonces ya tenemos las bases para manipular de forma sencilla el archivo de la biblioteca para mostrar los libros en una tabla. Y nos debería quedar algo así:

echo '<table>';
echo '<tr>';
echo '<th>Title</th><th>Author</th>
       <th>Publisher</th><th>ISBN</th>';
echo '</tr>';
foreach( $library->book as $book ) {
	echo '<tr>';
	echo '<td>' . $book->title . '</td>';
	echo '<td>' . $book->author . '</td>';
	echo '<td>' . $book->publisher . '</td>';
	echo '<td>' . $book['isbn'] . '</td>';
	echo '</tr>';
}
echo '</table>';

El problema ahora sería, ¿qué pasa si no conocemos todos los nombres de los elementos ni los atributos? SimpleXMLElement tiene la solución. Los métodos SimpleXMLElement::children() y SimpleXMLElement::attributes() así como el método recien introducido en PHP5.1.3 SimpleXMLElement::getName() nos ayudarán en gran medida.

Como bien se sobreentiende, el método children() regresa los nodos hijos de elemento actual. El método attributes() regresa los atributos del elemento actual y el método getName() el nombre del elemento actual. Todos se pueden aplicar recurrentemente dependiendo del nivel de anidación de los elementos. Es decir, si estamos en el elemento $x, y llamamos a $x->children() obtendremos a los hijos de $x, y si a uno de esos hijos le aplicamos el children() obtendremos los nietos de $x, y así sucesivamente.

De modo que, para concluir, el plugin que hice solo lee el feed, saco el nodo hijo <item> del elemento raíz que es <channel> llamándolo así:

$item = $apod->channel->item[0];

La posición cero indica que es el primer item del documento, es decir, el elemento con el cual se ha actualizado el feed. Y con ese elemento trabajo para obtener los demás datos. Por ejemplo, si la descripción es un elemento hijo de cada item, la obtengo así:

$descripcion = $apod->channel->item[0]->description;

Hasta aquí llega el microtutorial de hoy que ha servido para ver cómo parsear una cadena de XML para leerla nada más. La próxima semana escribiré cómo modificar documentos XML.

Fuente de inspiración: El manual para certificación de Zend PHP.

Tags: , , ,

Siéntete libre de dejar tu comentario.

Comentarios

Que pedo Plagiooos, nos Enlazamos? en el buen sentido de la palabra claro esta!

sobrex!

hola, como estas, muchas gracias por exelente tutorial, pero quisiera poder tambien escribir, me gustaria que nos explicaras como poder hacerlo, Gracias antemano

Gracias por tu comentario… lo estaba posponiendo pero lo haré pronto… a ver si puedo hoy o mañana.

ok, muchas gracias, estare al tanto.

Que tal, al parecer tu eres el unico que tiene la respuesta a mi interogante sobre como modificar un elemento de xml con php, por que he buscado por todas partes y no encuentro como, espero que puedas resolver mi problema pronto.

Gracias

Hola, mira, no tengo el manual de certificación de Zend (de donde me baso para hacer los ejemplos y donde he aprendido tales cosas) en mi laptop ahora, la tengo en mi PC de escritorio , y no puedo usarla ahora por unos pequeños problemas. Me percaté de eso hoy cuando quise escribir dicho artículo.

Te pido una disculpa, y prometo que intentaré conseguir el manual lo antes posible.

Hola, Bueno, no hay problema, estaré al tanto de todos modos, es que he estado como loco buscando la explicación pero no la encuentre, así que te esperare.

Gracias

Excelente tu post!!! me sirvio de mucho, este y el de modificar documentos XML con PHP. La verdad muchas gracias!

Muchas gracias, este artículo es claro, útil, y concreto.

amigos e probado ese odigo y tiene un par de fallas una el XML el cual no puede tener & si no el siguiente codigo ( & ), es decir le paso a continuación la construcción del xml: el archivo lo llame library.xml
// ——————

Fahrenheit 451
R. Bradbury
Del Rey

The Silmarillion
J.R.R. Tolkien
G. Allen & Unwin

1984
G. Orwell
Signet

Frankenstein
M. Shelley
Bedford

The Moon Is a Harsh Mistress
R. A. Heinlein
Orb

// ————–

a continuación el codigo php

<?php

// Carga un archivo XML
$library = new SimpleXMLElement(’library.xml’, null, true);

echo ”;
echo ”;
echo ‘TitleAuthor
PublisherISBN’;
echo ”;

foreach( $library->book as $book ) {
echo ”;
echo ” . $book->title . ”;
echo ” . $book->author . ”;
echo ” . $book->publisher . ”;
echo ” . $book['isbn'] . ”;
echo ”;
}
echo ”;

?>

Deja el tuyo

(requerido)

(requerido)