Crear XML con PHP (II)

Facebooktwittergoogle_pluslinkedinmailFacebooktwittergoogle_pluslinkedinmail

En el artículo anterior vimos la importancia de poder crear ficheros XML con PHP, y también vimos la forma en que no debemos hacerlo. En este artículo vamos a aprender a hacerlo empleando las prestaciones de OOP que PHP pone a nuestra disposición, logrando un código más robusto, fiable, mantenible y elegante.

LA EXTENSIÓN XMLWriter

La extensión XMLWriter proporciona los medios necesarios para generar documentos XML, tanto mediante OOP cómo por programación procedimental, aunque aquí vamos a centrarnos en su uso mediante OOP.

Para funcionar necesita que PHP tenga habilitada la librería libxml. Esta ya se encuentra habilitada por defecto desde la versión 5.1.2, por lo que no debemos preocuparnos por ello. No es necesario ningún otro requisito para su uso.

Vamos a ver un primer ejemplo de uso, basado en el ejemplo del artículo anterior. Lo vamos a hacer muy simple para familiarizarnos con XMLWriter. El código se llama escribir_xml.php y genera un fichero XML como el que veíamos en el ejemplo anterior:

A continuación entraremos en detalles pero, antes, un apunte importante. Si bien un archivo XML puede estár en la codificación que desees (aunque, por supuesto, la más empleada es UTF-8), los datos que le pasemos deberán ir SIEMPRE, en UTF-8. Si no, pueden quedar incorrectamente grabados. Para que todo tu trabajo siga esta codificación, revisa este mini post que, seguro, encontrarás muy interesante.

Empecemos a ver que hemos hecho. El XML lo vamos a procesar como un objeto, así que empezamos, como siempre que de programación orientada a objetos se trata, creando un objeto de la clase adecuada, del modo que vemos en la siguiente línea:

$objetoXML = new XMLWriter();

A continuación tenemos que decidir qué vamos a hacer con el XML que generemos: una opción es crearlo en memoria, para posteriormete grabarlo en disco, mostrarlo en pantalla, devolverlo por ajax a otro script o lo que sea, la otra alternativa, que es la que hemos elegido en este ejemplo, es grabarlo, directamente, en un archivo en disco, así:

$objetoXML->openURI("obras.xml");

El método XMLWriter::openURI() recibe, cómo argumento, el nombre del archivo en el que se grabará el contenido XML. Si el archivo ya existe en el disco, este método “machaca” el que hay para ser sustituido por el que vamos a crear.

Si lo que quisiéramos fuera crear el archivo en memoria para manejarlo posteriormente cómo hemos sugerido, emplearíamos la siguiente línea:

$objetoXML->openMemory();

A continuación vamos a establecer la indentación de los nodos XML:

$objetoXML->setIndent(true);
$objetoXML->setIndentString("\t");

El método XMLWriter::setIndent() recibe un valor booleano para establecer si los distintos niveles de nodos XML deben quedar indentados o no.

Si vamos a emplear indentación, el método XMLWriter::setIndentString() recibe, cómo argumento, la cadena a emplear cómo indentación por cada nuevo nivel de nodos. En este ejemplo empleamos el carácter \t, que corresponde a una tabulación. Si no especificamos este método, se toma cómo cadena de indentación un espacio en blanco.

Por fín, inicializamos el XML:

$objetoXML->startDocument('1.0', 'utf-8');

El método XMLWriter::startDocument() recibe dos argumentos: el primero es la versión de XML empleada y el segundo es la codificiación en la que se deben entender grabados los datos cuando se vaya a leer el archivo.

Para crear cada nodo de elemento XML hay dos formas de hacerlo. Si el nodo sólo va a tener su propio contenido pero no va a tener atributos, ni otros elementos anidados, la manera más simple es mediante el método XMLWriter::writeElement(). Este método recibe dos argumentos: el primero es el nombre del elemento y el segundo su valor. Por ejemplo, si, pensando en la matriz de datos que estamos empleando, sólo quisieramos en cada elmento obra poner el nombre de la obra cómo contenido, pero sin incluir los atirbutos ni los elementos anidados que hay, lo podríamos poner así:

$objetoXML->writeElement('obra', 'Construcción de aparcamiento público');

Sin embargo, este es el menos habitual de los casos. Lo normal es que un elemento vaya a incluir atributos, además de su propio contenido e, incluso, otros elementos anidados. Así pues, tenemos que separar el inicio del elemento, su contenido, y la finalización del mismo. La línea que hemos creado hace un momento quedaría, pues, dividida en tres, así:

$objetoXML->startElement('obra');
$objetoXML->text('Construcción de aparcamiento público');$objetoXML->endElement();

De hecho, en nuestro código de ejemplo, vemos que el elemento raíz del XML, que agrupará todas las obras que hay en la matriz, y que hemos llamado obras se inicializa, precisamente, de este modo, lo que permite anidar los demás elementos dentro:

$objetoXML->startElement("obras");

A continuación, creamos un bucle que recorre la matriz creando cada elemento. Observa que podemos crear la estructura de anidamiento XML que necesitemos, pero siempre deberemos acabar carrando cada elemento que hayamos abierto.

Para los atributos hay, cómo para los elementos, dos formas de crearlos. Podemos hacerlo en una sóla línea, así:

$objetoXML->writeAttribute("inicio", $obra["fecha_de_inicio"]);

Aunque también podríamos haberlo hecho en tres líneas, así:

$objetoXML->startAttribute("inicio");
$objetoXML->text($obra["fecha_de_inicio"]);
$objetoXML->endAttribute();

Al final del documento, y tras cerrar el elemento que corresponde al nodo raíz (que es el primero que se abrió y, por tanto, el último que se cierra) debemos cerrar también el documento, así:

$objetoXML->endDocument();

En nuestro ejemplo ya hemos terminado, porque el XML se ha grabado directamente a un fichero, tal cómo le dijimos que hiciera con el método XMLWriter::openURI(). Si lo hubiéramos creado en memoria, empleando para ello el método XMLWriter::openMemory() deberíamos hacer algo con el contenido XML. La opción más habitual es convertirlo a una cadena con el método XMLWriter::outputMemory(), así:

$cadenaXML = trim($objetoXML->outputMemory());

Cómo vés, este método no recibe argumentos. También es conveniente “recortar” los extremos de la cadena de salida, cómo hemos hecho en la línea de ejemplo.

 

ATENCIÓN. El método XMLWriter::text() renderiza el contenido de un elemento o atributo “en línea” con el inicio y el final del elemento o atributo correpondiente. Si necesitas, por cuestiones de visualización, que la salida del contenido esté en una línea aparte deberás forzar los saltos de línea y las tabulaciones necesarias para dicho contenido, cómo puedes ver en el script de ejemplo en la siguiente línea:

$objetoXML->text("\n\t\t".$obra["obra"]."\n");

La extensión XMLWriter incluye otros métodos, que podemos emplear para agregar, por ejemplo, comentarios al XML, espacios de nombres, etc. Lo que hemos visto en este artículo cubrirá nuestras necesidades en el 80% de los casos. En el siguiente post veremos más funcionalidades de esta extensión.

     

2 comentarios:

  1. Pingback: Crear XML con PHP (I) » eldesvandejose.com

  2. Pingback: Crear XML con PHP (III) » eldesvandejose.com

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *