14. Procesamiento de documentos XML
![]() |
Consideramos el siguiente documento XML:
<tribu>
<enseignant>
<personne sexe="M">
<nom>dupont</nom>
<prenom>jean</prenom>
<age>28</age>
ceci est un commentaire
</personne>
<section>27</section>
</enseignant>
<etudiant>
<personne sexe="F">
<nom>martin</nom>
<prenom>charline</prenom>
<age>22</age>
</personne>
<formation>dess IAIE</formation>
</etudiant>
</tribu>
Analizamos este documento para generar la siguiente salida de consola:
tribu
enseignant
(personne,(sexe,M) )
nom
[dupont]
/nom
prenom
[jean]
/prenom
age
[28]
/age
/personne
section
[27]
/section
/enseignant
etudiant
(personne,(sexe,F) )
nom
[martin]
/nom
prenom
[charline]
/prenom
age
[22]
/age
/personne
formation
[dess IAIE]
/formation
/etudiant
/tribu
Debemos saber cómo reconocer:
- una etiqueta de inicio como <formación>;
- una etiqueta de cierre como </enseñante>;
- una etiqueta de inicio con atributos como <persona sexo="F">;
- el cuerpo de una etiqueta como martin en <nombre>martin</nombre>.
El programa de análisis de un código XML se denomina analizador XML. Dos módulos nos proporcionan las funcionalidades para analizar un código XML: xml.sax y xml.sax.handler.
El módulo [xml.sax] nos proporciona un analizador XML mediante la instrucción:
Este analizador analiza el texto XML de forma secuencial. Llama a métodos del usuario en determinados eventos:
- el método startElement al inicio de una etiqueta;
- el método endElement al final de una etiqueta;
- el método characters en el cuerpo de una etiqueta.
Debemos indicar al analizador la clase que implementa estos métodos:
Pasamos al método setContentHandler del analizador una instancia de la clase que implementa los métodos startElement, endElement y characters. La clase utilizada es una clase derivada de la clase xml.sax.handler.ContentHandler. Los métodos anteriores se invocan con los siguientes parámetros:
- name es el nombre de la etiqueta de inicio. attributes es el diccionario de atributos de la etiqueta. Así, para la etiqueta <personne sexe="M"> tendremos name="personne" y attributes={'sexe':'M'}
- name es el nombre de la etiqueta de cierre. Así, para la etiqueta </estudiante> tendremos name='estudiante'.
- data es el cuerpo de la etiqueta. Por lo tanto, si la etiqueta es
obtendremos data='\r\n dupont\r\n '. Por lo general, se eliminarán los espacios que preceden y siguen a los datos.
Una vez explicado esto, podemos pasar al script de análisis de un documento XML:
# -*- coding=utf-8 -*-
import xml.sax, xml.sax.handler,re
# clase de gestión XML
class XmlHandler(xml.sax.handler.ContentHandler):
# función que se invoca al encontrar una etiqueta de inicio
def startElement(self,name,attributs):
global depth
# una secuencia de espacios (sangría)
print " " * depth,
# atributos
precisions=""
for (attrib,valeur) in attributs.items():
precisions+="(%s,%s) " % (attrib,valeur)
# se muestra el nombre de la etiqueta y los posibles atributos
if precisions :
print "(%s,%s)" % (name,precisions)
else :
print name
# un nivel más en el árbol
depth+=1
# ¿Es una etiqueta de datos?
global balisesDonnees,baliseDeDonnees
if balisesDonnees.has_key(name.lower()):
baliseDeDonnees=1
# la función que se invoca al encontrar una etiqueta de cierre
def endElement(self,name):
# fin de etiqueta
# nivel de sangría
global depth
depth-=1
# una secuencia de espacios (sangría)
print " " * depth,
# el nombre de la etiqueta
print "/%s" % (name)
# la función de visualización de datos
def characters(self,data):
# datos
global baliseDeDonnees
# ¿Es la etiqueta actual una etiqueta de datos?
if not baliseDeDonnees :
return
# nivel de sangría
global depth
# una secuencia de espacios (sangría)
print " " * depth,
# se muestran los datos
match=re.match(r"^\s*(.*)\s*$",data)
if match:
print "[%s]" % (match.groups()[0])
# fin de la etiqueta de datos
baliseDeDonnees=False
# ------------------------------------------- main
# el programa
# datos
file="data.xml" # el archivo xml
depth=0 # nivel de sangría = profundidad en el árbol
balisesDonnees={"nom":1,"prenom":1,"age":1,"section":1,"formation":1}
baliseDeDonnees=True # si es verdadero, indica que se trata de una etiqueta de datos
# se crea un objeto de análisis de texto xml
xml_parser=xml.sax.make_parser()
# el gestor de etiquetas
xml_parser.setContentHandler(XmlHandler())
# explotación del archivo xml
xml_parser.parse(file)
Notas:
- el script utiliza la biblioteca de funciones de los módulos xml.sax, xml.sax.handler (línea 3);
- línea 62: el archivo XML analizado;
- línea 68: el analizador XML;
- línea 70: el gestor de eventos emitidos por el analizador será una instancia de la clase XmlHandler;
- línea 72: se inicia el análisis del documento XML;
- línea 6: la clase que implementa los métodos startElement, endElement, characters. Deriva de la clase xml.sax.handler.ContentHandler, que implementa los métodos utilizados por el analizador;
- línea 9: el método startElement;
- línea 30: el método endElement;
- línea 41: el método characters.
Los resultados son los que se presentan al principio de este párrafo.
