Oct 302012
 
Artículo Perl

( Read this post in english )

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”:

<?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:

#!/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:

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:

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:

print XMLout($clientes);
print "\n";

Indice de artículos sobre programación en lenguaje Perl

 Publicado por en 7:10 pm

  2 Respuestas a “Cómo leer y escribir ficheros XML en Perl con XML::Simple”

  1. 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.

 Deja un comentario

(requerido)

(requerido)