Cómo acceder a los datos de XML en PHP
Por Abel
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.
Technorati tags: php, simplexmlelement, xml
Entradas posiblemente relacionadas:
- Clase para manejar base de datos MySQL en PHP (7)
- Método de Gauss en PHP (6)
- Cómo modificar documentos XML con PHP (13)
- Manejo de errores en PHP (4)
Este artículo fue escrito el 18 de Noviembre de 2007 y se encuentra en la(s) categoría(s) de Microtutoriales, PHP. Puedes seguir las respuestas a esta entrada a traves del Feed RSS. También puedes dejar un comentario, o hacer un trackback desde tu propio blog.


momox:
Noviembre 19th, 2007
Programadorx:
Diciembre 10th, 2007
Abel:
Diciembre 10th, 2007
Programadorx:
Diciembre 10th, 2007
Programadorx:
Diciembre 11th, 2007
Abel:
Diciembre 11th, 2007
Programadorx:
Diciembre 11th, 2007
Guillermo Maneiro:
Marzo 1st, 2008
Alexis:
Junio 27th, 2008