martes, 3 de abril de 2012

Leyendo XML en PHP con SimpleXML

Bueno, he leído en hartas partes, que una buena manera de guardar las cosas que hacemos, sobre todo cuando  requieren tantos pasos, es anotarlo y que mejor que hacerlo en un blog, así puedo buscarlo en mi blog y otras personas también pueden acceder a ellas, bien pues manos a la obra.

Leer los datos de un XML


Para cargar un archivo xml, solo basta con poner en el php:

$xml=simplexml_load_file(URL);

Para crearlo a partir de una cadena en formato de xml:

$xml=new SimpleXMLElement(STRING);

Bien, con eso tenemos un objeto SimpleXML, pero ahora hay que ver que datos se han obtenidos,
inicialmente usaba echo, pero print_r es mejor para mostrar un objeto, así que para observar los datos, recomiendo usar:

print_r($xml);

ahora si escribimos
$nodo=$xml->nombrenodo;
solo nos mostrara el primer nodo y si hay mas de un nodo con el mismo nombre, no lo mostrará, de modo que para mostrar otro nodo, tenemos varias opciones:

a) si conocemos el indice del nodo:
$nodo=$xml->nombrenodo[INDICE];
b) si conocemos el valor de un atributo o nodo, podemos obtenerlo con un xpath.
$array=$xml->xpath('nombrenodo[@nombreatributo="valoratributo"]');
OJO esto devolverá una array compuesta con todos los nodos que cumplan con la condición, si es solo uno podemos ocupar:
$array=$xml->xpath('nombrenodo[@nombreatributo="valoratributo"]');
$nodo=$array[0];
Ok, ya hemos cargado el xml, tambien hemos obtenido algunos nodos y ahora solo nos faltaría sacar los datos, para hacer esto solo hay que hacer esto:
$dato=(string) $nodo['nombreatributo'];
¿por qué (string)?

Es que si no lo conviertes a string (o a int o a boolean o al que necesites), seguirá siendo un SimpleXML y aunque con echo veas su valor, al no ser una string te dara problemas mas adelante.

¿Pero como obtengo los datos del interior de un nodo, como por ejemplo dato?

Es aun mas fácil:
$dato=(string) $nodo;
Por ultimo y para facilitar las cosas, recordemos que los SimpleXML son objetos iterables , es decir, que podemos recorrerlos con un ciclo, como el siguiente ejemplo:

foreach ($xml->node as $node){
echo $node;
}
y lo mismo con los xpath (recuerda que son arrays)

 foreach ($xml->xpath(//node) as $node){
 echo $node;
}
con eso es mas fácil, mostrar un listado o hacer algo con todos los datos.



Modificar los datos de un XML

No todo es leer datos, uno también quiere poder modificarlos, así que partamos con obtener un nodo y luego modificar sus valores:

Tenemos el siguiente xml:
< root >
< child atributo="value" >
dato
< /child >
< /root >
y queremos que el value cambie a value2, así que capturemos el nodo

$xml=$xml=new SimpleXMLElement(LA STRING QUE ESCRIBÍ ARRIBA);
$child=$xml->child; #como es uno solo no hay problema
y luego modificamos su valor:
$child['atributo']='value2';
¿fácil no?

Ahora a un valor interno, en nuestro ejemplo, cambiar dato a dato2
echo $child;
$child[0]='dato2';
echo $child;
Si queremos agregar un hijo:
$child->addChild("subchild",htmlspecialchars(utf8_encode(VALUE)));
Le puse htmlspecialchars(utf8_encode( VALUE )) por que así no me preocupo si va con tilde o con ñ.

Si queremos agregar un atributo:
$child->addAttribute("atributename",VALUE);
Si quisiera agregarle otro nodo a un nodo o un atributo hijo:
$subchild=$child->addChild("subchild",htmlspecialchars(utf8_encode(VALUE)));
$subchild->addChild("subsubchild",htmlspecialchars(utf8_encode(VALUE)));

Guardar los datos de un XML

Esta es la parte facil, solo hay que ocupar
$xml->asXML(URL);

ahora si quieres que el mismo php se vuelva un archivo xml, primero hay que agregarle header

header ("Content-Type:text/xml");
echo $xml->asXML();
Listo espero que ha alguien mas le sirva, por que yo voy a ocupar esta entrada como punto de referencia cada vez que lo necesite.


PD: alguien me puede decir como colorear el texto en mi blog?