Procesando XML con Perl
Breve referencia básica y rápida al procesamiento de archivos XML con Perl.

Enlaces básicos (inglés):
  • XML::Parser
  • XML::Parser::Expat
  • En el ejemplo se ilustra una forma simple de recorrer un archivo XML y mostrar su contenido. Hay muchas más opciones de hacerlo y formas de procesar la información, pero sólo apliqué la que me es necesaria.

    Para el correcto funcionamiento es necesario tener instaladas 2 librerias básicas (la una por requerimiento de la otra):

    Para descargarlas pulsa sobre ellas. Descomprime, configure, make.. lo de siempre. Si tienes dudas, traen un README :)


    Código fuente Explicado

    Rutina Principal (Main)

    		
    
    		#!/usr/bin/perl
    		use XML::Parser;
    
    		$file="programacion.xml";  #Archivo XML
    
    		###################################################
    		#
    		#Programa Principal
    		#
    		###################################################
    
    		my $parser = new XML::Parser(Style=>'Tree');
    		$parser->setHandlers(Start => \&start_handler,
    				  End   => \&end_handler,
    				  Char  => \&char_handler);
    
    		$parser->parsefile($file);
    
    		

    Tras establecer el nombre del archivo a parsear, creamos el Parser y establecemos las rutinas que procesaran los distintos eventos (handlers). Éstas habrán de definirse ulteriormente y se verá su funcionamiento en breve.

    Con esto ya se analiza el archivo, el resto (o la chicha) se ve en las subrutinas.

    • Start: define la funcion a ejecutar cuando un nuevo Nodo se encuentra
    • End: define la funcion a ejecutar cuando se encuentra el final de un Nodo
    • Char: define la funcion a ejecutar cuando se encuentra un Nodo de Texto (Texto entre nodo de apertura y de cierre)


    SubRutinas

    		
    
    				###################################################
    				#
    				# Subrutinas
    				#
    				###################################################
    
    				sub start_handler{
    				 my ($p, $el, %atts) = @_;
    				 print "\n-> Inicio Nodo $el";
    				 while(($c,$v)=each(%atts)){
    				   print "\n\t-> Atributos ".$c." = ".$v;
    				 }
    				}
    
    				sub end_handler{
    				 my ($p, $el) = @_;
    				 print "\nFin de elemento $el";
    				}
    
    				sub char_handler{
    					my ($p, $el) = @_;
    					chomp($el);
    					$el=~ s/\t//;
    					if(length($el)>0){
    						print "\nText-node::".$el." ".length($el);
    					}
    				}
    
    		

    Explicacion de las subrutinas:

    start_handler: Se ejecuta cuando se detecta el inicio de un Nodo.
    El nombre del Nodo se encuentra en la variable $el.
    Los posibles atributos del nodo se encuentran almacenados en el hashtable %atts
    end_handler: Se ejecuta cuando se detecta el final de un Nodo, su nombre almacenado en la variable $el.
    char_handler: Se ejecuta cuando se detecta un Nodo de texto (texto entre nodos de apertura y cierre)
    En el ejemplo le quito el último carácter y tabulaciones porque me detecta nodos de texto fantasmas dados ciertos caracteres especiales.



    Código fuente Completo

    		
    
    		#!/usr/bin/perl
    		use XML::Parser;
    
    		$file="programacion.xml";  #Archivo XML
    
    		###################################################
    		#
    		#Programa Principal
    		#
    		###################################################
    
    		my $parser = new XML::Parser(Style=>'Tree');
    		$parser->setHandlers(Start => \&start_handler,
    				  End   => \&end_handler,
    				  Char  => \&char_handler);
    
    		$parser->parsefile($file);
    
    
    		###################################################
    		#
    		# Subrutinas
    		#
    		###################################################
    
    		sub start_handler{
    		 my ($p, $el, %atts) = @_;
    		 print "\n-> Inicio Nodo $el";
    		 while(($c,$v)=each(%atts)){
    		   print "\n\t-> Atributos ".$c." = ".$v;
    		 }
    		}
    
    		sub end_handler{
    		 my ($p, $el) = @_;
    		 print "\nFin de elemento $el";
    		}
    
    		sub char_handler{
    			my ($p, $el) = @_;
    			chomp($el);
    			$el=~ s/\t//;
    			if(length($el)>0){
    				print "\nText-node::".$el." ".length($el);
    			}
    		}
    		



    Fuente del XML

    		
    			<xml version="1.0" encoding="UTF-8"?>
    			<programaciones>
    				<cliente nombre="a">
    					<clave nombre="clave-a" periodo="30" e-mail="rcc@la-ira.com" dia="10" dia_semana=""/>
    					<clave nombre="clave-b" periodo="7" e-mail="rcc@la-ira.com" dia="" dia_semana="02"/>
    				</cliente>
    			</programaciones>