Parsers XML


Autor: F. Javier García Castellano
Web: http://decsai.ugr.es/~fjgc, Mail: fjgc@decsai.ugr.es
XMLInicioXHTML

(C) GeNeura Team
Web: http://geneura.ugr.es, Mail: tutti@geneura.ugr.es

1. Introducción: Parser con validación y sin validación

Un parser o procesador o analizador sintáctico lee el documento XML y verifica que es XML bien formado , algunos también comprueban que el código XML sea válido.

El parser o procesador de XML es la herramienta principal de cualquier aplicación XML. Mediante el parser no solamente podemos comprobar si nuestros documentos son bien formados o válidos, sino que también podemos incorporarlos a nuestras aplicaciones, de manera que estas puedan manipular y trabajar con documentos XML.

Podemos dividir los parsers XML en dos grupos principales:

En el caso de utilizar un DTD, es preferible utilizar un parser con validación.

2. Parsers XML

Normalmente no nos tendremos que preocupar de buscar un parser concreto para comprobar la validez de nuestros documentos XML, ya que los desarrolladores de las aplicaciones que utilizaremos como navegadores o visualizadores o transformadores de esos documentos en el documento final que el usuario ve, incluirán sus propios parsers. Un ejemplo de esto es el caso del Microsoft Internet Explorer 5 (o superior), que utiliza el parser de MS (incluido en la librería MSXML.DLL); o el caso de Mozilla, que internamente utiliza el parser EXPAT (escrito en C).

A continuación teneis un parser sin validación escrito en JavaScript. Presenta el árbol del documento a comprobar.

Teclea o copia el código XML aquí y pulsa en "Procesar"

3. Modelo de Objeto Documento (DOM)

Para extraer la información que contiene un documento XML, se podría escribir código para analizar el contenido del archivo XML, pues no deja de ser un archivo de texto, tal y como lo podríamos hacer con HTML. Sin embargo, esta solución no es muy aconsejable y desaprovecharía una de las ventajas de XML: el ser una forma estructurada de representar datos.

La mejor forma de recuperar información de archivos XML es utilizar un parser de XML, que sea compatible con el modelo de objeto de documento (DOM) de XML. DOM define un conjunto estándar de comandos que los parsers devuelven para facilitar el acceso al contenido de los documentos XML desde sus programas. Un analizador de XML compatible con DOM toma los datos de un documento XML y los expone mediante un conjunto de objetos que se pueden programar.

DOM para XML es un modelo de objetos estándar (propuesto por el W3C) que muestra el contenido de un documento XML. La Especificación del Modelo de Objeto de documento (DOM) del W3C define actualmente lo que debería mostrar un DOM como propiedades, métodos y eventos.

En http://www.asptutor.com/xml/index5.asp puedes ver una introducción de como se haría en Visual Basic, en http://java.sun.com/webservices/docs/1.1/tutorial/doc/JAXPDOM.html#wp66050como poder hacerlo con JAVA, en http://search.cpan.org/src/ENNO/libxml-enno-1.02/html/XML/DOM.html como hacerlo con Perl, en http://expat.sourceforge.net como hacerlo en C y en C++ usando expat (el parser del Mozilla) y en http://msdn.microsoft.com/msdnmag/issues/01/01/xml/default.aspx como hacerlo en C# .NET

Veamos un ejemplo, supongamos el siguiente trozo de código XML:

 <TABLE>
  <TBODY> 
   <TR> 
       <TD>Shady Grove</TD>
       <TD>Aeolian</TD> 
   </TR> 
   <TR>
       <TD>Over the River, Charlie</TD>        
       <TD>Dorian</TD> 
   </TR> 
  </TBODY>
 </TABLE>

El DOM representaría esta tabla de la siguiente forma:

4. Trabajando con DOM en Perl: XML::DOM

En este apartádo vamos a ver como trabajar con el Modelo de Objeto Documento (DOM) usando Perl, para los que no sepan Perl en http://flanagan.ugr.es/perl hay un tutorial en castellano de Perl y en http://decsai.ugr.es/~fjgc/dbi/modulos.htm como instalar módulos en perl.

Para manejar el DOM bajo Perl vamos a utilizar el módulo XML::DOM que lo podeis encontrar en http://search.cpan.org/search?dist=libxml-enno. El módulo XML::DOM se basa en el módulo XML::Parser y éste a su vez en la librería del expat (parser de libre distribución del Mozilla). Para consultar los métodos y objetos del módulo XML::DOM podeis mirar en http://theoryx5.uwinnipeg.ca/CPAN/data/libxml-enno/XML/DOM.html.

Para comprender mejor como se trabaja con el DOM en Perl, vamos a a usar el siguiente documento XML de ejemplo:

<?xml version="1.0" standalone="yes"?>
<noticias>
        <!--Noticia 1 -->
	<noticia tipo="economia">
	  <titulo url="http://www.elpais.es/articulo.html?anchor=elpepieco&amp;xref=20010215elpepieco_14&amp;type=Tes&amp;d_date=20010215">
		Microsoft, investigado por invertir en un rival
	  </titulo>
          <fecha>15 de febrero de 2001</fecha>
	  <contenido>
               El gigante de la informatica Microsoft, pendiente
		de una apelacion para evitar ser dividido en dos por
		vulnerar la competencia, está siendo investigado otra vez por las autoridades
		antimonopolio, que sospechan de por que el mayor fabricante de programas invirtio
		135 millones de dolares (24.165 millones de pesetas) en su rival Corel.
	  </contenido>
	 </noticia>

	<!--Noticia 2 -->
	<noticia tipo="internet">
	  <titulo url="http://www.abc.es/Internet/noticia.asp?id=13298&amp;dia=18022001">
		 Clinicas reales y virtuales para tratar adictos a Internet
	  </titulo>
          <fecha>18 de febrero de 2001</fecha>
	  <contenido>
                   La aparicion de una nueva patologia, la "dependencia" a internet, esta confirmada por la creacion
                   de numerosas clinicas en Estados Unidos, reales o virtuales, para tratar de remediar las
                   enfermedades de la red....
	  </contenido>
	 </noticia>

</noticias>

En el ejemplo anterior se tiene un documento XML que está pensado para trabajar con noticias que aparecen en Internet. Lo que vamos a hacer es, usando Perl y el módulo XML::DOM, un programa que procese el documento xml y muestre el titulo de las noticias

#!/usr/bin/perl

#Indicamos al perl que use el modil XML::DOM
use XML::DOM;

#Creamos un parser XML
$parser = new XML::DOM::Parser;

#Hacemos el parser XML al fichero ejmploDOM.xml y obtenemos el DOM
$doc = $parser->parsefile ("ejemploDOM.xml");

# Cogemos el titulo todas las noticias del documento XML
$noticias = $doc->getElementsByTagName ("titulo");

#Cogemos el número de noticias
$n = $noticias->getLength;

#Escribimos el título de cada noticia
for (my $i = 0; $i < $n; $i++)
{
   #Cogemos el tiltulo de la noticia i
   my $noticia = $noticias->item ($i);

   #Imprimimos el nombre de la etiqueta
   print $noticia->getTagName;
   print ": ";

   #Cogemos el hijo (texto) de la etiqueta que estamos procesando
   my $noticia_contenido = $noticia->getFirstChild;

   #Imprimimos el contenido del hijo
   print $noticia_contenido->getData;
   print "\n";
}

# Escribimos la salida del parser (el documento XML) en un fichero
$doc->printToFile ("salida.xml");

# Escribimos el documento XMl en pantalla
#print $doc->toString;

# Limpiamos la memoria ocupada por el documento XML
$doc->dispose;

Ahora vamos a hacer un segundo ejemplo donde mostraremos las noticias, y la url correspondiente


#!/usr/bin/perl

#Usamos el módulo XML::DOM de Perl
use XML::DOM;

#Creamos un parser XML
$parser = new XML::DOM::Parser;

#Hacemos el parser XML al fichero ejmploDOM.xml
$doc = $parser->parsefile ("ejemploDOM.xml");

# Cogemos los nodos del DOM cuyas etiquetas sean titulo
$noticias = $doc->getElementsByTagName ("titulo");

#Cogemos el número de noticias
$n = $noticias->getLength;

#Escribimos el título de cada noticia
for ($i = 0; $i < $n; $i++)
{
 	#Cogemos el tiltulo de la noticia i
	$noticia = $noticias->item ($i);


	#Imprimimos el nombre de la etiqueta
	print $noticia->getTagName;
	print ": ";


	#Cogemos el hijo (texto) de la etiqueta que estamos procesando
	my $noticia_contenido = $noticia->getFirstChild;


	#Imprimimos el contenido del hijo
	print $noticia_contenido->getData;


	#Cogemos el valor del atributo url
	$mi_url= $noticia->getAttributeNode("url");


	#Imprimimos el contenido de dicho atributo
	print " (href=";
	print $mi_url->getValue;
	print " )\n";
}

# Limpiamos la memoria ocupada por el documento XML
$doc->dispose;

Ahora vamos a hacer un tercer ejemplo donde recorremos el DOM

#!/usr/bin/perl

#Usamos el módulo XML::DOM de Perl
use XML::DOM;

#Creamos un parser XML
my $parser = new XML::DOM::Parser;

#Hacemos el parser XML al fichero ejmploDOM.xml
my $doc = $parser->parsefile ("ejemploDOM.xml");

#Cogemos el nodo raiz
my $raiz = $doc->getFirstChild;

#Como el nodo raiz está en lo alto de la jerarquía, ponemos profundidad =0
my $profundidad=0;

#Mostramos el árbol xml
muestra_arbol($raiz,$profundidad);

# Limpiamos la memoria ocupada por el documento XML
$doc->dispose;
#------------------------------------------------------------------------
sub muestra_arbol()
{
 	#Cogemos los dos parámetros el nodo del árbol y la profundidad
	my ($nodo, $profundidad)=@_;


	#Miramos el tipo de nodo, si es de texto (hoja del DOM) decimos que hay datos
	if ($nodo->getNodeType==TEXT_NODE) {
		for (my $i=0; $i < $profundidad; $i++) {print " "};
		print $nodo->getData;
		print "\n";
	}

        #Miramos el tipo de nodo, si es un comentario
	elsif ($nodo->getNodeType==COMMENT_NODE) {
		for (my $i=0; $i < $profundidad; $i++) {print " "};
		print "COMENTARIO\n";
	}
        #No es nodo hoja, lo mostramos y recorremos sus hijos
	else
	{
         	 #Nos vamos a la derecha dependiendo de la profundidad
		 for (my $i=0; $i < $profundidad; $i++) {print" "};

		 #Mostramos la etiqueta del nodo
		 print $nodo->getTagName;
		 print "\n";


		#Cojemos los nodos hijos y el número que hay
		my $hijos=$nodo->getChildNodes;
		my $n=$hijos->getLength;

		#Para cada nodo hijo, mostramos su etiqueta y mostramos su subarbol
		for (my $i;$i < $n; $i++)
		{
                   #Cogemos el hijo i
                   my $hijo=$hijos->item($i);

                   #Exploramos el subarbol del hijo i
                   muestra_arbol($hijo,profundidad+1);
		}


	}
}
#------------------------------------------------------------------------



Resumiendo, como podemos ver, con XML es mucho más fácil (dentro de lo que cabe) procesar la información que lo era antes con HTML, ya que para procesar una página HTML (no XHTML) teníamos que trabajar con ella como si fuera texto plano.

5. Ejercicios

Ejercicio: Probar alguno de los códigos que se han escrito anteriormente en el parser XML on-line que teneis aquí. Probad como no funciona bien si el código XML está no está bien formado (Si es que no lo habeis probado anteriormente)

Ejercicio: Dibuja cual sería el DOM de uno de los documentos XML realizado en ejercicios anteriores (Escoge, por ejemplo, el ejercicio del hotel). Este ejercicio os ayudará a comprender cómo trabajan las aplicaciones sobre XML, y como manipulareis el árbol generado por un documento XML desde vuestra aplicación

Ejercicio:Coge el documento XML del ejercicio anterior y muestra el contenido de algún elemento del mismo, que se repita varias veces (si has cogido el ejemplo del hotel, que escriba los nombres de los hoteles>

Ejercicio:Coge el documento XML del ejercicio anterior y muestra el contenido de algún elemento del mismo, generando una página HTML. Basta que la página se vea por pantalla y luego podeis verla con el mozilla. (para guardar la salida por pantalla del ejemplo se haría de la siguiente forma: ejercicio.pl > pagina.html). Si sigues con el ejemplo de los hoteles que escriba una página html con los nombres de los hoteles.