
Existen numerosos módulos disponibles en CPAN que implementan distintas aproximaciones para el proceso de ficheros en formato XML.
El módulo XML::Simple que comentamos en este artículo puede ser el más adecuado para los casos más sencillos, en los que necesitamos leer o generar un fichero de pequeño tamaño que no hace uso de características avanzadas del formato XML.
Ejemplo de fichero en formato XML
El formato XML permite representar en un fichero de texto una estructura jerárquica de elementos, en donde cada elemento consta de una serie de atributos (parejas (nombre,valor)), y una serie de subelementos.
En el siguiente ejemplo vemos un documento XML que contiene un elemento raiz «documento» con dos subelementos «cliente»:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?xml version="1.0"?> <documento version="3.5" timestamp="2002-05-13 15:33:45"> <cliente identificador="62520"> <nombre>Juan</nombre> <apellido>Fernandez</apellido> <direccion> <calle>Avda. Ilustración 17</calle> <poblacion>Guadalajara</poblacion> <provincia>Guadalajara</provincia> <cp>82649</cp> </direccion> <email>juan.fernandez@expensive-mail.org</email> <edad>42</edad> </cliente> <cliente identificador="62521"> <nombre>Elena</nombre> <apellido>Rovira</apellido> <direccion> <calle>Pez Volador 2</calle> <poblacion>Móstoles</poblacion> <provincia>Madrid</provincia> <cp>28001</cp> </direccion> <email>elerovw@cyb.org</email> <edad>37</edad> </cliente> </documento> |
A su vez, los subelementos cliente contienen subelementos «nombre»,»apellido»,»direccion»,etc
También vemos que el elemento «documento» tiene atributos «version» y «timestamp», y los elementos «cliente» tienen un atributo «identificador».
Leer un documento XML con XML::Simple
El módulo CPAN XML::Simple permite leer el documento entero en memoria, en forma de una estructura de datos.
Ejemplo:
1 2 3 4 5 6 7 8 9 10 11 12 |
#!/usr/bin/perl use strict; use warnings; use XML::Simple; # Lee el fichero XML con XMLin, usando la opción 'forcearray' # para que todos los elementos contengan arrayrefs my $datos = XMLin('./clientes.xml', forcearray=>1); |
Con este código, a la variable «$datos» se le asigna una referencia a una hashtable de pares (clave,valor).
Cada clave identifica:
- un atributo si el valor es un literal simple
- un array de subelementos si el valor es una referencia a array.
Cada subelemento puede ser:
- un valor simple
- una hashref de subelementos del siguiente nivel.
A continuación vemos cómo podemos recorrer esta estructura de datos:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
imprime_elemento("CLIENTES",$datos,""); sub imprime_elemento { my $nombre = shift; my $elemento = shift; my $indentacion = shift; print $indentacion . "Elemento: " . $nombre . "\n"; $indentacion .= " "; foreach my $clave (keys %$elemento) { if (ref $elemento->{$clave} eq "ARRAY") { foreach my $subelemento (@{$elemento->{$clave}}) { if (ref $subelemento eq "HASH") { imprime_elemento($clave, $subelemento,$indentacion); } else { print $indentacion . "Elemento: " . $clave . ", Valor: " . $subelemento . "\n"; } } } else { print $indentacion . "Atributo: " . $clave . ". Valor: " . $elemento->{$clave} . "\n"; } } } |
La subrutina imprime_elemento es recursiva, se llama a sí misma para cada subelemento del elemento que está siendo procesado. Con este código aplicado al fichero xml de más arriba, se obtiene el resultado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Elemento: DATOS Atributo: timestamp. Valor: 2002-05-13 15:33:45 Atributo: version. Valor: 3.5 Elemento: cliente Elemento: email, Valor: juan.fernandez@expensive-mail.org Atributo: identificador. Valor: 62520 Elemento: apellido, Valor: Fernandez Elemento: edad, Valor: 42 Elemento: direccion Elemento: provincia, Valor: Guadalajara Elemento: calle, Valor: Avda. Ilustración 17 Elemento: cp, Valor: 82649 Elemento: poblacion, Valor: Guadalajara Elemento: nombre, Valor: Juan Elemento: cliente Elemento: email, Valor: elerovw@cyb.org Atributo: identificador. Valor: 62521 Elemento: apellido, Valor: Rovira Elemento: edad, Valor: 37 Elemento: direccion Elemento: provincia, Valor: Madrid Elemento: calle, Valor: Pez Volador 2 Elemento: cp, Valor: 28001 Elemento: poblacion, Valor: Móstoles Elemento: nombre, Valor: Elena |
Escribir un documento XML con XML::Simple
El módulo XML::Simple implementa también el método XMLout, que recibe como argumento una hashref con una estructura de datos como la que produce XMLin, y la convierte a formato XML:
1 2 3 4 |
print XMLout($clientes); print "\n"; |
—
Indice de artículos sobre programación en lenguaje Perl
—
Hay un problema, al generar la salida, devuelve desordenados los resultados, ser: Nombre en el xml está arriba de todo y en el output está debajo.
Saludos!
Efectivamente, XML::Simple no tiene en cuenta el orden de los elementos. En muchos casos esto no supone un problema. Si lo fuera, podemos utilizar el módulo XML::Parser::PerlSAX, que procesa el documento XML como un stream, y por lo tanto permite tener en cuenta el orden en el que se presentan los elementos en el mismo. Los detalles de uso de este módulo para el proceso de ficheros XML los explicamos en el articulo «Cómo leer y escribir documentos XML en Perl con XML::Parser::PerlSAX» en este mismo blog.