« Datos XML bonitos y más leíbles en PHP usando PEAR XML_Beautifier El mes de los bugs y nueva versión de PHP »
Feb 09

Dado que ya he hecho un post acerca de como realizar peticiones cURL y otro relacionado con el formateo de XML, sólo me falta lo evidente, un post acerca de como leer y trabajar con los datos XML recibidos. Desde que tenemos la versión 5 del PHP disponemos de la extensión SimpleXML la cual nos proporciona una forma muy rápida y fácil de leer datos XML. Si has programado parsers XML usando librerías como expat encontrarás que esta extensión es una auténtica maravilla, aunque como siempre, a costa de consumir más recursos (básicamente más memoria... pero lo vale).

Con SimpleXML consigues muy fácilmente convertir un archivo XML en un objeto. Para representar la estructura de elementos del documento XML se construye un objeto con atributos q pueden contener directamente valores o arrays de objetos q también tendrán más atributos, más arrays de objetos, etc. (el número de arrays de arrays de objetos depende de los niveles de anidación de los elementos). Se puede trabajar con estos objetos como con cualquier otro en PHP.

Se entiende mucho mejor su uso con un ejemplo sencillo. Imaginemos el siguiente documento XML:

<?xml version='1.0'?>
<mensajes>
  <mensaje>
    <asunto>Hola</asunto>
    <texto>Hola, que tal?</texto>
  </mensaje>
  <mensaje>
    <asunto>Re: Hola</asunto>
    <texto>Bien, gracias.</texto>
  </mensaje>
</mensajes>

Asumiendo que en $data tenemos el XML a leer con un código PHP como:

$xml = simplexml_load_string($data);
foreach ($xml->mensaje as $mensaje)
  echo $mensaje->texto.' ';

Obtendremos el resultado:

Hola, que tal? Bien, gracias.

SimpleXML nos puede devolver errores de todo tipo, documentos malformados, problemas de encodings, etc. Si estás en un entorno donde sólo te interesan los documentos válidos y quieres descartar el resto resulta útil algo como:

function loadXML($data) {
  $xml = @simplexml_load_string($data);
  if (!is_object($xml))
    throw new Exception('Error en la lectura del XML',1001);
  return $xml;
}

Si queremos volver a obtener el documento XML dado un objeto SimpleXML es tan fácil como:

echo $xml->asXML();

En ocasiones tenemos XML con muchos niveles de elementos y se hace especialmente engorroso ir recorriendo con "foreach" todo el documento. En estas situaciones, como en muchas otras, es necesario poder buscar dentro de los XML. Esto lo conseguimos con el soporte XPath que ofrece SimpleXML. Por ejemplo para acceder a todos los elementos "asunto" del ejemplo anterior:

foreach ($xml->xpath('//asunto') as $asunto)
  echo $asunto."\n";

Existen dos consideraciones a tener en cuenta con el uso de SimpleXML:

[1] Si quieres acceder a un elemento que tiene un guión "-" en su nombre debes hacerlo así:

foreach ($xml->{'mensaje-personal'} as $mensaje)
  echo $mensaje->texto.' ';

Si suponemos que en el ejemplo anterior sustituimos "mensaje" por "mensaje-personal".

[2] Es recomendable hacer cast a string siempre que obtenemos datos de los objetos SimpleXML. En ocasiones (unexpected :) en lugar de devolver directamente el valor de un elemento devuelve otro objeto SimpleXML, se soluciona con:

$texto = (string) $data_o->mensaje[0]->texto;

Antes de terminar comento otra característica interesante y es que podemos convertir un objeto SimpleXML en un objeto DOM y viceversa usando las funciones simplexml_import_dom() y dom_import_simplexml(), incluso en las últimas versiones del PHP se le han añadido métodos para poder modificar y crear desde cero documentos XML trabajando directamente con el objeto SimpleXML (al estilo DOM).

  • Facebook
  • Twitter
  • del.icio.us
  • Bitacoras.com
  • Meneame
Entradas relacionadas:
Etiquetas:

28 Comentarios sobre “Leyendo XML desde PHP con SimpleXML”

  1. parandroide dice:

    estoy haciendo un guestbook que guarda los registros en un archivo xml, mismo que es manipulado (leído y escrito) por un script php. Cuando es leido, devuelve el contenido en html para ser desplegado tal cual en la página a través de una petición XMLHttpRequest. Todo funciona bien, guarda y devuelve y despliega los mensajes perfectamente. El xml es como el siguiente:

    nick/nombre–1
    web/mail–1
    mensaje–1

    nick/nombre–2
    web/mail–2
    mensaje–2

    nick/nombre–3
    web/mail–3
    mensaje–3

    No soy muy avanzado en php ni en xml, y mi problema (ojalá me puedan ayudar) es que no sé cómo hacer que los mensajes nuevos aparezcan primero, ya que en el xml los nuevos registros van quedando hasta abajo, antes de , o que php al momento de leerlos que los muestre en el orden contrario en el que se encuentran, esto es, primero los nuevos (los de abajo). Estoy usando las funciones simplexml de php5 para leer y ecribir el xml. No sé, tal vez es algo muy simple y yo me estoy rompiendo la cabeza de más, pero bueno, para saberlo vine aquí. Saludos.

  2. Oriol dice:

    no acabo de entender como lo tienes montado pero… así a bote pronto:
    - si escribes tu los datos en el XML usando simplexml puedes insertar los nuevos al principio.
    - otra opción es leer los nick del último al primero ya sea desde javascript o desde PHP antes de enviarlo (si es q no lo envías directo). Desde PHP puedes usar algo como array_reverse() o con un simple “for” desde el fin al principio en lugar de “foreach”.

  3. eduard dice:

    hola
    tengo creado un formulario que se llama agenda, con nombre, direccion, telefono, Email y obervaciones,genero un archivo en php que los guarda. me gustaria saber como se puede generar un xml porque en relidad estoy confundido que hace un xml

    FORMULARIO:

    Encuesta Nº 1

    Nombre:

    Direccion

    Comuna

    Telefono

    Tel. Celular

    Email

    Empresa

    Direccion Empresa

    Tel. Empresa

    Cargo

    Observaciones:

     

    ARCHIVO QUE LO GUARDA:

    TE QUEDARIA MUY AGRADEIDO YA QUE CON ESTO QUEDARIA MAS CLARO GRACIAS

  4. Oriol dice:

    Si la duda es que es un XML: http://es.wikipedia.org/wiki/XML
    XML es un metalenguaje extensible de etiquetas desarrollado por el W3C que se propone como un estándar para el intercambio de información estructurada entre diferentes plataformas.
    Un ejemplo de uso del XML en la situación que entiendo que tienes sería:
    Un script PHP que genera un formulario HTML y a la vez es el encargado de recoger los datos por GET/POST y guardarlos (es el action del form)… pero la pregunta es ¿donde quieres guardar los datos?. Lo que podrías hacer es que el script PHP generase un XML con los datos recibidos:
    <encuesta>
    <nombre></nombre>
    <!-- ... -->
    </encuesta>

    Y después leerlos con SimpleXML como explico en el post :)

  5. [...] Desde que tenemos la versión 5 del PHP disponemos de la extensión SimpleXML la cual nos proporciona una forma muy rápida y fácil de leer datos XML. Si has programado parsers XML usando librerías como expat encontrarás que esta extensión es una auténtica maravilla, aunque como siempre, a costa de consumir más recursos (básicamente más memoria… pero lo vale).» noticia original [...]

  6. albert dice:

    alguien que sepa de un hosting php5 gratis para probar mi buscador de videos youtube que lo eh echo con simplexml , pues los host que dicen ser php5 qu eh encontrado no me agarran simplexml … ya ehh probado mi buscador en localhost y funcina bien solo deseo uno host de prueba para probar el buscar ya despues me voy a pagar un host solo quiero de prueba no importa con anuncios si alguien sabe , si puede me manda al correo albert_g608@hotmail.com

  7. Edwin dice:

    hola

    Estoy haciendo un repositorio de objetos de aprendizaje, los objetos de aprendizaje son empaquetados en un zip bajo el estandar SCORM, estos objetos de aprendizaje contienen metadatos con la descripcion del objeto. lo que quiero hacer es leer los metadatos del archivo xml del objeto mediante php y almacenar los metadatos en una base de datos de sql, para poder catalogar los objetos realizar busquedas etc

  8. Oriol dice:

    Aunque no he trabajado con SCORM desde PHP por lo que sé no deberías tener problemas con el uso de SimpleXML para leer los datos de los archivos XML contenidos en un paquete. Si es que ya lo has probado ¿Dónde está el problema?

  9. Ferran dice:

    Buenas tardes, tengo que recuperar unos datos sobre libros que estan en xml y me he estado mirando sax, simplexml etc… de momento con lo que mas he conseguido algo ha sido con simplexml, el problema es que mis etiquetas tienen atributos, o sea: en lugar de

    algo

    queda asi

    algo

    y no hay manera de que me muestre las etiquetas si tienen atributos…

    muchas gracias y muy bueno el tutorial :)

  10. Oriol dice:

    perdón por el retraso :)

    con el filtro de WordPress no puedo ver bien tu código y no sé exactamente donde está el problema.

    En todo caso con SimpleXML puedes acceder a los elementos tengan o no atributos de la misma forma y puedes acceder a los atributos de un elemento en concreto como si fuera un array. Otra opción es usar una expresión XPath para directamente obtener los elementos con un atributo (o valor de atributo) determinado.

  11. Etej dice:

    Hola!
    Estoy intentando leer un xml desde un formulario con SimpleXML pero me tira warnings…
    Detallo como esta en codigo y el ejemplo para ver si me pueden ayudar:
    En el formulario en el item xml ingreso el siguiente ejemplo:

    facundo

    005491144345601
    005491145104302
    Contenido del mensaje de texto

    En el codigo:
    $xml = $_REQUEST['data'];
    $xmlElement = simplexml_load_string($xml);

    Como resultado me tira lo siguiente:

    Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 1: parser error : String not started expecting ‘ or " in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: <?xml version=\’1.0\’ encoding=\’UTF-8\’?> in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 1: parser error : Malformed declaration expecting version in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: <?xml version=\’1.0\’ encoding=\’UTF-8\’?> in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 1: parser error : Blank needed here in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: <?xml version=\’1.0\’ encoding=\’UTF-8\’?> in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 1: parser error : parsing XML declaration: ‘?>’ expected in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: <?xml version=\’1.0\’ encoding=\’UTF-8\’?> in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 2: parser error : AttValue: " or ‘ expected in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: <service type=\’sms\’> in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 2: parser error : attributes construct error in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: <service type=\’sms\’> in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 2: parser error : Couldn’t find end of Start Tag service line 2 in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: <service type=\’sms\’> in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: Entity: line 2: parser error : Extra content at the end of the document in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: <service type=\’sms\’> in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Warning: simplexml_load_string() [function.simplexml-load-string]: ^ in /home/p4r4com/public_html/analia/push/sms.service.php on line 78

    Donde justamente la linea 78 es: $xmlElement = simplexml_load_string($xml);
    Me faltara llamar al constructor? El xml lo veo bien formado, sinceramente necesito solucionar el tema urgente! Si alguno me puede orientar se lo agradecere!

  12. Etej dice:

    Perdon… pero veo que no sale correctamente mi xml… como puedo escribirlo para que lo vean correctamente? Muchas gracias

  13. Oriol dice:

    Hola Etej,

    Para escribir XML en los comentarios y que aparezca correctamente es un poco coñazo. Lo has de poner todo entre tags <code> y sustituir los < por &lt; y los > por &gt; en tu XML. En los posts tengo un plugin que me lo hace mucho más fácil pero no sirve para los comentarios.

  14. Vianey dice:

    Hola que tal?
    Necesito de sus grandísimas ayudas…

    Lo que pasa es que estoy haciendo un programa en php5 que lea un archivo xml, y me inserte, consulte, elimine y modifique nodos xml.

    Por ejemplo:
    Tengo este archivo:

    Ana
    111
    aaa

    Luis
    222
    bbb

    Juan
    333
    ccc

    Hasta el momento, despues de tanto investigar puedo hacer correctamente sólo insertar y consultar nodos.

    Y sólo de esto he encontrado información.

    Lo malo está en que no puedo modificar ni eliminar, porque no se cómo hacerle, no he encontrado información sobre esto.

    Quisiera eliminar todo un cliente, por ejemplo, eliminar a Luis, y que me quedara así

    Ana
    111
    aaa

    Juan
    333
    ccc

    O bién modificar todos los datos de Luis y cambiarle hasta el nombre, por decir que en lugar de los datos de luis quedaran otros como: nombre = Carlos, telefono = 444 y domicilio = ddd, y quedara así:

    Ana
    111
    aaa

    Carlos
    444
    ddd

    Juan
    333
    ccc

    Espero y me ayuden porfavor, es urgentísimo.

    Ayudenme, no importa si tengo que usar Dom ó SimpleXML, Como sea, pero ayudenme, porfavor.

    Gracias de antemano.

  15. Ser dice:

    Hola que tal,
    Estoy atorado con XML y PHP, tengo un un xml que tomo de un sitio web que alberga videos, y necesito leerlo con PHP, lo hago de la siguiente manera:

    $data = file_get_contents($url,FALSE,NULL); //
    $fileData = new SimpleXMLElement($data);

    el XML que me genera es el siguiete:

    Query Result
    http://
    Result of query

    HelpSample.mov

    Fri, 07 Mar 2008 19:28:38
    616043
    Ser
    0XCzIG2UEp5kcbiEJW0yIWom13

    etc…

    etc…

    puedo leer perfectamente la info dentro de ,, pero no los que estan en ó en pocas palabras no se como leer las etiquetas con “:” alguien sabe como hacerlo se que debe de ser una tonteria pero no tengo experiencia con XML y php.

    Gracias!

  16. tru3n0 dice:

    Hola, tengo una duda, sabrías como borrar un nodo con simplexml? no utilizo ningún tipo de identificador para los nodos, podría hacerse una lectura de todo el xml y borrarse el nodo actual por ejemplo?

    Un saludo y gracias de antemano

  17. tiam dice:

    Saludos, mi duda es la siguiente, realizo una consulta a una base de datos, los resultados que tengo quiero almacenarlos en un archivo xml. si pudieran darme una mano con esto.

    gracias

  18. CArlos Albertto dice:

    Necesito saber como podría recuperar parametros con el sigueinte ejemplo:

    Requiero recuperar

    espero puedan ayudarme.

    5/30/08 8:37 AM Local Time

    87
    73
    6:35 AM
    7:43 PM

    38
    Scattered T-Storms

    10
    N/A
    3
    N

    Sct T-Storms
    60
    79

    11
    T-Showers

    10
    N/A
    349
    N

    T-Showers
    60
    92

  19. albert dice:

    hola , quisiera saber como puede leer un nodo XML de un feed con “:” (2 puntos) usando SimpleXML o algo alternativo, el feed es:

    xxyy xxyy //con esto no tengo problema
    222222//este es el problema
    vvvvvv

    si lo pongo directamente me da un error de sintaxis:

    $xml = simplexml_load_file($url);
    foreach($xml->item->grupo:userid as $uid){
    //trabajo con la variable $uid
    }

    también probé:

    —-1—-
    $userid=”grupo:userid”;
    $xml->item->$userid

    —-2—-
    $xml->item->{’grupo:userid’}

    y pues ninguno no me ah dado resultado, espero me puedan ayudar, gracias por la respuesta

  20. NeySmall dice:

    Hola:

    Estoy usando php5

    Me gustaría saber cómo hacerle para leer imprimir en pantalla sólo el último registro xml.

    Por ejemplo si tengo este archivo:

    ———–

    Jabón
    12.89
    12457689

    cereal
    22.50
    59484000

    sopa
    3.49
    23994338

    refresco 600 ml.
    6.50
    88763902

    sabritas
    5.00
    98346751

    ———–

    para imprimir sólo el último registro que sería:

    Sabritas
    5.00
    98346751

    ¿Cómo le haría?

    Actualmente tengo este código en php usando SimpleXML:

    ——–

    cliente as $cliente )
    {
    echo “” , $cliente->nombre , “”;
    echo “” , $cliente->telefono , “”;
    echo “” , $cliente->pais , “”;
    echo “” , $cliente->estado , “”;
    echo “” , $cliente->ciudad , “”;
    echo “” , $cliente->domicilio , “”;
    echo “” , $cliente->colonia , “”;
    echo “” , $cliente->codigopostal , “”;
    }

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

    ——–

    pero con esto se muestran todos los registros, y yo quiero mostrar sólo el último.

    ¿Cómo le haría? ayudenme.
    Ya sea con DOMXML o con SimpleXML, con cualquiera de los 2 está bien.

    Gracias de antemano.

    Saludos.

  21. NeySmall dice:

    Perdón puse otro archivo php que no era.

    Este es el correcto:

    _____________

    foreach (Tienda as $Tienda )
    {
    echo “” , $Tienda->descripcion , “”;
    echo “” , $Tienda->precio , “”;
    echo “” , $Tienda->codigo , “”;
    }

    $item = $apod->channel->item[1];
    $descripcion = $apod->channel->item[1]->description;
    ?>
    ____________

  22. heel linux dice:

    saludos, tengo un problema voy a trabajar con XML y php, lo que necesito saber es de que manera puedo enviar y recibir XML vía http. Los ejemplos que he encontrado han sido leer un archivo en el mismo servidor.

    Mi problema en concreto es que me envian un XML vía HTTP, yo tengo que obtener de ese XML los datos que necesito para hacer una consulta a un AS/400 (esto se puede hacer con php?) convertila en XML y regresarla vía HTTP.

    Gracias. HEEL, Mehico Tenochtitlan.

  23. Diego dice:

    Tengo problemas para que simplexml me tome valores de una variable.
    Basicamente quiero que el usuario seleccione filas (con checkbox) de una tabla larga (rellenada por xml), y al hacer submit aparezca la misma tabla pero solo con los seleccionados.
    A continuacion les pongo el script que recibe el formulario:

    tipo[0]->categoria[$seleccion];
    $nombre = $categoria->categorianombre;
    $precio = $categoria->categoriaprecio;
    //$seleccion por si solo aprarece bien con un valor numerico, pero las busquedas dentro del xml relacionadas con $seleccion no aparecen
    echo “***”;
    echo “$seleccion – $nombre – $precio”;
    echo “***”;
    $i ;
    }

    }

    ?>

    El problema me aparece en “$categoria = $xml->tipo[0]->categoria[$seleccion];” No me toma $seleccion.
    La pagina esta muy buena.
    Saludos

  24. Diego dice:

    Pude solucionar el problema anterior.
    No me tomaba el array que contenia numeros como numeros. Lo tomaba como cadena.
    Lo solucione usando “(integer)”.
    $seleccion = (integer) $casilla[$i];
    Saludos

  25. Angel dice:

    Este el un ejemplo del xml que tengo que procesar. Son los ficheros que tengo que procesar.

    este es un ejemplo del xml que tengo que convertir

    Los datos a sacar son:

    el contenido de “to” a una variable $de
    el contenido de “from” a una variable $a
    el contenido de “datetime” a una variable $datetime
    y el contenido de body ya lo he sacado.

    ¿Alguien me puede ayudar?
    Gracias

  26. Pablo dice:

    Necesito saber como modificar el contenido d eun nodo, o de lo contrario como borrar el nodo completo… muchas gracias.

  27. Hey @albert , el que yo uso es 000webhost.com Te dan 1.5GB, mysql, php. No es nada malo, te lo recomiendo

  28. Juan Martin Hernandez dice:

    Mi problema es el siguiente: tengo un archivo excel, lo guardo como xml. Yo ahora quiero guardar todas las filas del excel y sus respectivos campos en un array… alguien tiene alguna idea ??

    gracias

Escribe un comentario

preload preload preload