...Microplagio...

Advertisement

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

 

Para lograrlo debemos hacer una instancia de la clase SimpleXMLElement. El constructor recibe 5 parámetros aunque solo nos interesan 2 (el primero y el tercero). El primero es donde indicamos la dirección URL del archivo XML o la cadena XML en cuestión. El segundo argumento no tiene aplicación práctica para este ejemplo y el tercero es solo para informar al constructor que (en este caso particular) el primer parámetro es una ruta a un archivo y no una cadena XML.

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

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.

1 Comentarios: