12 Diciembre 2007

Cómo modificar documentos XML con PHP

Por Abel

Bien, después de haberme atrasado casi un mes y en vista de que es un tema difícil de encontrar en la red, voy a hacer un microtutorial sobre cómo modificar un documento XML usando PHP5. Ya vimos cómo hacer un parsing a un documento XML usando la extensión que provee PHP5 llamada SimpleXMLElement. Ahora veremos primero cómo modificar elementos de nuestro XML, estamos hablando de agregar o eliminar elementos.

Cómo agregar elementos, hijos y atributos

Hasta PHP 5.1.3 la extensión SimpleXMLElement no tenía forma de agregar elementos a un documento XML. Sólo era posible modificar los valores de elementos o atributos pero para agregar nuevos era necesario exportar el objeto SimpleXMLElement a DOM, hacer los cambios y exportar de nuevo a SimpleXMLElement, lo cual era una tarea complicada. Pero la versión 5.1.3 introdujo dos nuevos métodos que nos dan el poder de modificar el documento XML. Me refiero a los métodos:

SimpleXMLElement::addChild()
SimpleXMLElement::addAttribute()

El nombre lo dice todo, con el primero agregamos un elemento hijo al elemento en el que nos encontramos y con el segundo agregamos un atributo. addChild() acepta tres parámetros, el primero indica el nombre del nuevo elemento, el segundo es opcional e indica el valor del elemento, y el tercero también es opcional e indica el namespace al cual pertenece el elemento. addAttribute() recibe dos, el nombre del atributo y su valor.

Pongamos un ejemplo para ilustrar su uso. Recordemos el ejemplo de la vez pasada donde usamos un archivo XML cuyo contenido son libros con sus respectivos datos y pasemos a crear el objeto SimpleXMLElement.

$library = new SimpleXMLElement('library.xml', null, true);

Ahora supongamos que queremos agregar un nuevo libro llamado The finished mistery cuyo autor es J. F. Rutherford, el ISBN es 0812550706 y la editorial es Watchtower Society.

$book = $library->addChild('book');
$book->addAttribute('isbn', '0812550706');
$book->addChild('title', "The finished mistery");
$book->addChild('author', 'J. F. Rutherford');
$book->addChild('publisher', 'Watchtower Society');

Con eso es suficiente para modificar el contenido XML. En la primera línea estamos agregando un nuevo hijo llamado book al elemento raíz que es library, como SimpleXMLElement siempre nos regresa un objeto del mismo tipo, entonces a la variable $book también podemos aplicarle el metodo addChild() para crearle hijos, (que vendrían siendo los nietos de $library). Es como una especie de recursividad, donde podemos ir creando elementos en varios niveles, paras obtener hijos, nietos, bisnietos etc.

Ahora bien, hasta este punto no podemos ver cómo ha quedado nuestro documento XML. Lo siguiente será mostrarlo en el navegador. Para ello, debemos enviar una cabecera para indicar al navegador que el contenido a mostrar no es simple texto ni HTML, sino XML y después hacer la impresión del mismo.

header('Content-type: text/xml');
echo $library->asXML();

¿Para que sirve el método asXML()? regresa el contenido XML del objeto como una cadena, pero solo si lo llamamos sin argumentos. La otra opción, que sin duda es la qué podria darnos mas usabilidad es llamarlo con un parametro que contendría una ruta a un archivo, el cual se escribirá con el contenido XML del objeto. El método asXML($string) regresará un valor de tipo boolean dependiendo del resultado de la operación.

¿Cómo escribir entonces un archivo XML? Supongamos que, una vez agregado el nuevo libro a nuestro archivo de libros queremos guardar los cambios. Lo único que habría que hacer es:

$library->asXML('library.xml');

Y listo, si escribimos el nombre de un archivo que no existe, se crea automaticamente y si ya existe se sobrescribe.

¿Cómo eliminar ahora elementos y atributos de un documento XML?

SimpleXMLElement, no provee ningun metodo para hacerlo, sin embargo sí hay una forma de eliminar hijos. Supongamos que quiero eliminar el libro que acabo de agregar. Como es el elemento book número 6, solo hay que destruir el objeto que pertenece a ese hijo:

$library->book[5] = null;

El cinco es porque los elementos empiezan a contarse desde cero. Sin embargo, hay un inconveniente; esto solo eliminara a los hijos del elemento book y a sus respectivos atributos, pero los atributos que haya al nivel de book permaneceran ahi. Por lo que el atributo isbn seguirá existiendo. Si lo igualamos a null, solo conseguiremos vaciar su valor pero dejando intacto al atributo.

Para remover efectivamente hijos y atributos, debemos exportar el objeto SimpleXMLElement a DOM, donde las funcionalidades de PHP5 para manipular los datos se hacen más poderosas. Hablaré de ello después…

Espero que este microtutorial sea de utilidad para quien necesite manipular datos XML con PHP 5.


Technorati tags: , , , ,


Entradas posiblemente relacionadas:


Este artículo fue escrito el 12 de Diciembre 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.

Actualmente hay 13 comentarios para “Cómo modificar documentos XML con PHP”

Deja el tuyo.

  1. 1

    Programadorx:
    Diciembre 13th, 2007

    Hola que tal, muchas gracias por el tutorial, pero tengo una interrogante aun, como puedo hacer para, en ves de agregar algo, solo modificarlo un elemento existente, ya sea, un elemento o un nodo, por ejemplo

    Fahrenheit 451
    R. Bradbury
    Del Rey

    como puedo hacer para modificar solamente el valor de isbn, modificarlo y guardar el cambio.
    espero me puedas rsponder
    Gracias de antemano

  2. 2

    Programadorx:
    Diciembre 18th, 2007

    como se puede modificar solamente??

  3. 3

    Abel:
    Diciembre 23rd, 2007

    Disculpa la espera, estuve investigando eso, necesitas usar DomDocument y DomXpath, ambos son clases de PHP5. Solo permíteme un poco más para intentar dominar el tema.

    Un saludo.

  4. 4

    Programadorx:
    Diciembre 27th, 2007

    Bueno, esperare ya que es un tema el cual no logro comprender, te agradezco mucho tu ayuda, Gracias

    Un Cordial Saludo

  5. 5

    Programadorx:
    Enero 2nd, 2008

    Buenas tardes y feliz a;o nuevo, me gustaria saber si has encontrado algo sobre el tema de mi interrogante.

    Gracias

  6. 6

    Abel:
    Enero 2nd, 2008

    Hola! Muchas gracias.

    Fijate que sí tengo un poco de documentación. Pero suficiente como para redactar un manual propio no lo creo… Sin embargo, puedo mostrarte un ejemplo pequeño de cómo modificar un elemento existente.

    Como ya te habia dicho, necesitas crear una instancia de DOMDocument y pasar el objeto a DomXpath para trabajar por medio de queries… El ejemplo lo tomaré directamente de la guía de certificación de Zend.

    $xml = <<<XML
    <xml>
    <text>some text here</text>
    </xml>
    XML;
    $dom = new DOMDocument();
    $dom->loadXML($xml);
    $xpath = new DomXpath($dom);
    $node = $xpath->query("//text/text()")->item(0);
    $node->data = strtoupper($node->data);
    echo $dom->saveXML();
    

    Lo que hace ese script es tomar el elemento que contiene la cadena ‘text’ y poner en mayúscula su contenido. El resultado sería esto:

    <?xml version="1.0"?>
    <xml>
    <text>SOME TEXT HERE</text>
    </xml>
    

    He probado cosas más complejas y sigo teniendo algunos problemillas,por eso no me he animado a escribir al respecto, además de algunos pendientes importantes que tengo en el trabajo. Espero que eso te dé por lo menos una idea de cómo continuar.

    Un saludo.

  7. 7

    Programadorx:
    Enero 9th, 2008

    Vaya, Exelente ejemplo, creo que ya puedo seguir solo, gracias por tu tiempo y tu comprension, tienes un exelente web, muchas gracias.

    Saludos

  8. 8

    Abel:
    Enero 9th, 2008

    Que bueno que te sirvió… y gracias por todos los comentarios!

  9. 9

    GokuH:
    Febrero 7th, 2008

    Buenas amigo, muxas gracias por tu tutorial, muy weno!, me sirvio de muxa ayuda!
    io te dejo aki una forma k encontre para actualizar con el mismo simpleXML, dejo aki el codigo de ejemplo:

    $admin = new SimpleXMLElement($xmlfile, null, true); // Carga un archivo XML
    $users = $admin->xpath(’//usuario[username="' . $nombreusuario . '"]‘);
    if ($users){
    $users[0]->avatar = $dire;
    $admin->asXML($xmlfile);
    }
    eso modifica avatar dentro de mi xml, :D

  10. 10

    Vianey:
    Febrero 14th, 2008

    Hola Que tal,

    pero quisiera un ejemplo para modificar un nodo hijo XML desde php.
    Modificar un dato existente dentro del nodo raiz.

    GRACIAS DE ANTEMANO

  11. 11

    cotorrito_punto_com:
    Abril 24th, 2008

    Hola, tengo el siguiente Script para intentar agregar un nuevo nodo pero algo no me resulta:

    La linea de $listaCDs=new SimpleXMLElement($userXML,null, true); me esta generando un error, solo que mi apache2triad en lugar de mostrarmelo me saca la agina en blanco. Espero y me puedan ayudar..

  12. 12

    cotorrito_punto_com:
    Abril 24th, 2008

    Perdon mi codigo era:

    $relativepath=”../cds/”.$_SESSION['user'];
    $userXML=$relativepath.”.xml”;
    $elCD=$_POST['album'];
    $elCantante=$_POST['artista'];
    $elTrackList=$_POST['tracklist'];
    $listaCDs=new SimpleXMLElement($userXML,null, true);

  13. 13

    linda:
    Abril 29th, 2008

    tengo este archivo xml (

    Hola Caracola
    KaoS
    Olla Kaitos a Luisete

    Nuevo articulo en desarrolloweb
    Raul
    Jeje hola, aqui estamos

    XML;
    ?>)

    luego de este codigo–
    ( noticias[0]->addChild(’noticia’);
    $noticia->addChild(’titulo’, ‘muerte en inundaciones’);
    $noticia->addChild(’autor’, ‘lobo’);
    $noticia->addChild(’cuerpo’, ‘12 muertes por lluvias’);

    //header(’Content-type: text/xml’);
    echo $xml->asXML();

    ?> )

    me da este error–(Ha ocurrido un error al procesar el documento “” a XML )

    alguien podria decirme ke debo hacer para arreglar eso ????
    gracias

Deja un comentario

  • Ventana al cosmos

  • Apollo 17: Anaglifo de asientos VIP

  • Publicidad