Por defecto PHP, desde la versión 5.1.2, incorpora la extensión SimpleXML y la trae habilitada (en versiones anteriores es necesario usar –enable-simplexml para activar esta extensión en el momento de compilar). Dicha extensión incluye una serie de herramientas que nos permiten trabajar fácilmente con XML.
No es extraño que si tenemos que comunicarnos con un api externa esta nos devuelva una respuesta en XML, que es un formato universal que puede ser trabajado con casi cualquier lenguaje (otra posibilidad muy habitual es JSON). SimpleXML nos permite recoger esta respuesta, convertirla en un objeto y trabajar con el mismo sin mucha complicación.
En caso de querer recoger una respuesta de otra página, el método a usar sería simplexml_load_string():
$objetoxml = simplexml_load_string($respuestaApi);
Con esto ya tenemos un objeto fácil de recoger. Vamos a imaginar que el objeto que recibimos es tal que así:
<response> <requestid>A16</requestid> <requests>3</requests> <status>error</status> <error> <code>106</code> <message>Request expired</message> </error> </response>
Una notificación de un error conectando con un servicio externo (de hecho, es una copia de un mensaje de error del api de Calameo). Ahora imaginemos que queremos recoger este mensaje de error y mostrárselo por pantalla al usuario. ¿Qué hacemos? Pues muy facilito:
//primero convertimos el xml a objeto $objetoxml = simplexml_load_string($respuestaApi); //luego comprobamos que sea un mensaje de error: if (isset($objetoxml->error)) { //e imprimimos echo 'Error:'.$objetoxml->error->code.': '.$objetoxml->error->message; }
Trabajar con el objeto SimpleXML es cosa fácil: Cuando quieres acceder a un elemento basta ir moviéndose como si accedieras a las propiedades o métodos de un objeto. Es decir abuelo->padre->hijo. ¿Que hay varios elementos con la misma etiqueta? Sin problema, las etiquestas se convierten en objetos iterables y accesibles, por lo que puedes recorrerlos recurriendo a los mecanismos básicos de iteración (bucle foreach, por ejemplo).
¿Y para acceder a los atributos? En el ejemplo del xml no hay, pero imaginemos que en lugar del anterior la cosa fuera así:
<response> <requestid>A16</requestid> <requests>3</requests> <status>error</status> <errors> <error> <message code="106">Request expired</message> </error> <error> <message code="401">File not found</message> </error> </error> </response>
Ok, ahora tendrías que acceder a los atributos, y de paso podríamos ver un ejemplo de iteración. A los atributos se accede como si fuesen elementos de un array, usando como índice su nombre:
//primero convertimos el xml a objeto $objetoxml = simplexml_load_string($respuestaApi); //luego comprobamos que sea un mensaje de error: if (isset($objetoxml->errors)) { foreach(objetoxml->errors->error as $error) { echo 'Error:'.$error['code'].': '.$error->message; } }
Un par de notas más:
- Para usar el texto de un elemento en una comparación o pasarlo a una función como string hay que forzar la conversión a cadena de texto haciendo un cast con (string)
- Para acceder a un elemento cuyo nombre viole las convenciones para nombres de objeto de PHP hay que recurrir a encapsular el nombre del elemento dentro de un par de llaves y comillas simples.
- En este caso hemos hablado de recoger una respuesta de un servicio externo, pero SimpleXML nos permite también recoger un xml desde un archivo con simplexml_load_file().
Y si necesitáis convertir el elemento en un array (en su momento me tocó) ya tratamos ese punto con anterioridad.