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 PHP. Ya vimos cómo hacer un parsing a un documento XML usando la extensión que provee PHP 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:
// Class SimpleXMLElement 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.
Este es el archivo XML que usaremos de nuevo:
Fahrenheit 451 R. Bradbury Del Rey The Silmarillion J.R.R. Tolkien G. Allen & Unwin 1984 G. Orwell Signet Frankenstein M. Shelley Bedford The Moon Is a Harsh Mistress R. A. Heinlein Orb
Ahora lo cargamos y convertimos a objeto con la clase 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.
Esto es lo que debemos hacer:
// Primero creamos un elementoy lo agregamos al elemento raíz $book = $library->addChild('book'); // Le asignamos el atributo [isbn] al elemento $book->addAttribute('isbn', '0812550706'); // Creamos los elementos que van dentro de : , y $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 utilidad es llamarlo con un parametro string
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('new-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 PHP 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.