El formato XML se ha introducido en todos los campos (incluidos la traducción) por varios motivos, pero podemos destacar unos pocos:
En esta unidad veremos algunos ejemplos sencillos y el lector podrá crearse sus propias aplicaciones modificando los ejemplos que exponemos. También se puede encontrar mucha más información sobre Python y XML en los siguientes enlaces:
Utilizaremos diversas técnicas para leer y obtener información de archivos XML:
En toda esta unidad utilizaremos como archivo XML uno que representa una base de datos de CDs de música. Se puede encontrar adjunto en esta página (y en todo el resto de páginas de la unidad donde haga falta). Aprovechad para abrirlo con un editor de textos. Este archivo lo presentamos en tres versiones:
Para cada programa que presente será interesante observar si la estrategia que hemos utilizado funciona correctamente para las tres versiones de este archivo.
De esta unidad dispones de los siguientes archivos:
Los archivos XML se pueden tratar con funciones estándar de cadena, como en el programa-10-1.py.
import codecs
entrada=codecs.open("catalog.xml","r",encoding="utf-8")
sortida=codecs.open("catalog.txt","w",encoding="utf-8")
artist=""
title=""
year=""
for linia in entrada:
linia=linia.rstrip().lstrip()
if linia.startswith("</cd>"):
if not artist=="" and not title=="" and not year=="":
cadena=artist+"\t"+title+"\t"+year
print(cadena)
sortida.write(cadena+"\n")
if linia.startswith("<title>") and linia.endswith("</title>"):
title=linia[7:-8]
elif linia.startswith("<artist>") and linia.endswith("</artist>"):
artist=linia[8:-9]
elif linia.startswith("<year>") and linia.endswith("</year>"):
year=linia[6:-7]
Si nos fijamos, en este código veremos que sólo se utilizan funciones de cadena estándar como startswith () y endswith (), por ejemplo. Si lo ejecutamos, veremos que funciona correctamente y que a la salida nos da la información de artista, título y año.
Bob Dylan Empire Burlesque 1985
Bonnie Tyler Hide your heart 1988
Dolly Parton Greatest Hits 1982
Gary Moore Still got the blues 1990
Esta estrategia puede ser válida, pero se basa demasiado en la disposición física de las marcas y la información en el documento. Prueba ahora si este programa funciona bien para catalog-mod.txt y catalog-mod2.txt.
Para evitar el problema de la dependencia de la disposición de la información, podemos hacer uso de expresiones regulares, como en el siguiente programa (programa-10-2.py)
import codecs
import re
entrada=codecs.open("catalog.xml","r",encoding="utf-8")
sortida=codecs.open("catalog.txt","w",encoding="utf-8")
artist=""
title=""
year=""
for linia in entrada:
linia=linia.rstrip().lstrip()
if linia.startswith("</cd>"):
if not artist=="" and not title=="" and not year=="":
cadena=artist+"\t"+title+"\t"+year
print(cadena)
sortida.write(cadena+"\n")
else:
m_title = re.search('<title>(.+?)</title>', linia)
if m_title:
title = m_title.group(1)
m_artist = re.search('<artist>(.+?)</artist>', linia)
if m_artist:
artist = m_artist.group(1)
m_year = re.search('<year>(.+?)</year>', linia)
if m_year:
year = m_year.group(1)
Intenta ejecutar el programa con los archivos catalog modificados. ¿Los puede tratar todos?
xml2dict nos permite tratar archivos XML de una manera muy fácil, ya que convierte los archivos XML en una estructura de datos de tipo diccionario. En el programa-10-3.py podemos observar cómo utilizar esta librería.
import xmltodict
xml=open('catalog.xml')
xmldict = xmltodict.parse(xml.read())
for cd in xmldict["catalog"]["cd"]:
print(cd["artist"],cd["title"],cd["year"])
Prueba con todas las modificaciones del archivo catalog y observa si es capaz de procesar correctamente todos los archivos.
Disponemos de una serie de librerías que nos facilitan mucho la lectura de archivos XML. Una de ellas es xml.etree.ElementTree. Para observar cómo funciona, ejecutaremos el programa-10-4.py y observaremos la salida:
import xml.etree.ElementTree as etree
for event, elem in etree.iterparse("catalog.xml",events=("start", "end")):
print(event,elem,elem.tag,elem.attrib)
La librería es capaz de detectar cuando hay un evento (y hemos seleccionado el principio (start) y el final (end)), el elemento afectado, la etiqueta del elemento y el atributo del elemento. En este programa de prueba simplemente escribimos esta información:
start <Element 'catalog' at 0x7f456b5c3728> catalog {}
start <Element 'cd' at 0x7f4569d999f8> cd {'id': '1'}
start <Element 'title' at 0x7f4569d3c2c8> title {}
end <Element 'title' at 0x7f4569d3c2c8> title {}
start <Element 'artist' at 0x7f4569d3c318> artist {}
end <Element 'artist' at 0x7f4569d3c318> artist {}
Con esta información, podemos hacer un programa que lea el archivo (programa-10.5.py):
import xml.etree.ElementTree as etree
import codecs
artist=""
title=""
year=""
sortida=codecs.open("catalog.txt","w",encoding="utf-8")
for event, elem in etree.iterparse("catalog.xml",events=("start", "end")):
if event=="end" and elem.tag=="cd":
cadena=artist+"\t"+title+"\t"+year
print(cadena)
sortida.write(cadena+"\n")
artist=""
title=""
year=""
if event=="end" and elem.tag=="title":
title="".join(elem.itertext()).lstrip().rstrip()
if event=="end" and elem.tag=="artist":
artist="".join(elem.itertext()).lstrip().rstrip()
if event=="end" and elem.tag=="year":
year="".join(elem.itertext()).lstrip().rstrip()
Comprueba que este programa funciona también bien con el catalog modificado.