viernes, 5 de febrero de 2010

XML y Python - Operaciones básicas I

XML, las tecnologías relacionadas, y los lenguajes de marcado basados en XML son la base para el intercambio de datos entre aplicaciones, multilenguaje y multiplataforma en las aplicaciones modernas.

Python admite completamente el lenguaje XML. La biblioteca estándar Python proporciona el paquete xml, que nos permite utilizar la tecnología XML fundamental de manera muy sencilla. Hay paquetes de terceros, como PyXML que amplían el paquete xml, introduciendo implementaciones de DOM, XPath ó XLST. Hay otro paquete de terceros, llamado 4Suite, que proporciona más analizadores XML para áreas de aplicación específicas, además de XLink y XPointer. Una alternativa Python para el procesamiento XML es Element Tree, cuya funcionalidad, en parte, se incluye en Python 2.5, en el módulo xml.etree.

Para los usuarios que quieran ver en profundidad el tema de Python y XML, sax y DOM, sus diferencias y virtudes, y sus formas de acceso particulares, recomiendo, en primer lugar Google, fuente de toda sabiduría, y en segundo lugar la lectura obligada de Python & XML, de Jones y Drake, editorial O'Reilly.

En este post vamos a ver las operaciones básicas para poder manipular documentos con Python.
Imaginemos, por ejemplo, un fichero que contenga un documento XML (agenda.xml), el cual podría tener la siguiente estructura:
<?xml version="1.0" encoding="iso-8859-1"?>
<agenda_personal>
<codigo_referencia fecha="20100201">
<texto>Texto en el día 01/02/2010.</texto>
</codigo_referencia>
<codigo_referencia fecha="20100215">
<texto>Texto en el día 15/02/2010.</texto>
</codigo_referencia>
</agenda_personal>

La manera más sencilla de obtener un documento XML a partir de un fichero, mostrándolo por la consola es la siguiente:

from xml.dom import minidom

# Cargamos en objeto arbol_dom el documento xml
arbol_dom = minidom.parse('c:\\python\\agenda.xml')

# Mostramos por pantalla el fichero XML, tal cual.
print arbol_dom.toxml()

Documentos bien formados

Para comprobar si un documento XML está bien formado podemos utilizar el módulo xml.sax, cuya función es la de analizar sintácticamente ficheros XML. Si el documento no está bien formado informará con una excepción. En primer lugar cargamos los módulos que necesitaremos para utilizar el analizador sintáctico (parser).

import sys
from xml.sax.handler import ContentHandler
import xml.sax

Creamos un objeto analizador sintáctico (parser) xml.sax, usando para ello la función make_parser(). Es decir, esta función devuelve un objeto parser que utilizaremos para analizar sintácticamente el fichero XML.

xml_analizador = xml.sax.make_parser()

Después de crear el objeto parser, se añade un manejador de contenido (content handler) al objeto usando su función setContentHander(handler). Esto es, un manejador de contenidos genérico se pasa al objeto mediante una llamada a la función xml.sax.handler.ContentHandler().
Se añade un manejador de contenido (content handler) genérico al analizador sintáctico (parser).

xml_analizador.setContentHandler(ContentHandler())

Una vez que el manejador de contenidos se ha añadido al objeto parser el fichero XML puede ser analizado dentro de un bloque try. Si el parser encuentra un error en el documento XML se lanza una excepción; de lo contrario el documento está bien formado (well formed).

nombre_fichero = "c:\\python\\agenda\miagenda.xml"

try:
xml_analizador.parse(nombre_fichero)
print "El fichero XML %s está bien formado." % nombre_fichero

except Exception, err:
print "Error %s:\n\t %s no es un fichero bien formado" % (err, nombre_fichero)

Acceso a datos en árbol DOM

Hay varias formas de acceder a nodos hijos en un árbol DOM. Aquí vamos a ver 3 formas:

1) Mediante referencia directa.
2) Buscando el nodo por nombre de etiqueta.
3) Navegando por el árbol DOM.

Referencia directa

El primer paso es analizar el documento XML utilizando la función minidom.parse (nombre_fichero) para crear el objeto árbol DOM. Los nodos hijos del árbol DOM se pueden acceder directamente utilizando el atributo childNodes, el cual es una lista de nodos hijos de la raíz (root) del árbol.

from xml.dom import minidom

xml_documento = minidom.parse("c:\\python\\agenda.xml")
nodos = xml_documento.childNodes

Puesto que el atributo childNodes es una lista, los nodos se pueden acceder directamente usando childNodes[indice]. Así para acceso a nodos mediante referencia directa haremos:

print "Acceso directo a nodos:"
print nodos[0].toxml()

Nombre de etiqueta

Para buscar nodos por su nombre de etiqueta se utiliza la función getElementByTagName(tag) del nodo objeto. Esta función acepta una cadena con los nombres de etiqueta de nodos hijos y devuelve una lista de todos los nodos hijos con dicha etiqueta. Para buscar el nodo por nombre de etiqueta haremos:

print "Búsqueda de nodo por nombre de etiqueta:"
lista = nodos[0].getElementsByTagName("codigo_referencia")
for nodo in lista:
lista_aux = nodo.getElementsByTagName("texto")
for x in lista_aux:
print x.toxml()

Navegando por el árbol DOM

Por último, se puede acceder a nodos hijos navegando por el árbol DOM. Para ello podemos definir una función recursiva a la que se le pase como parámetro una lista de nodos. Para navegar por el árbol DOM haremos:

print "Búsqueda de nodos navegando por el árbol DOM:"
def VisualizarNodos (lista, nivel):
for nodo in lista:
print (" ")*nivel, nodo.nodeName, nodo.nodeValue
# Llamamos recursivamente a la función.
VisualizarNodos (nodo.childNodes, nivel + 1)

# Llamamos a la función.
VisualizarNodos(xml_documento.childNodes, 0)

6 comentarios:

  1. Buen Tema Muchas Graxias fue de gran Ayuda!!!

    ResponderEliminar
  2. si por ejemplo conozco el valor "iso-8859" y necesito saber en que TAG está?
    cómo podría hacerlo=?

    ResponderEliminar
  3. si quisiera acceder a una propiedad como lo haria, ej:

    <...>
    ..

    ResponderEliminar
  4. tremenda pija tu blog, metele un poco de colores al codigo que se pierde en el texto

    ResponderEliminar
  5. Yo recomiendo https://poeditor.com para traducir los archivos XML. Creo que es una muy rápida y intuitiva herramienta de localización y taducción .

    ResponderEliminar
  6. !!!!!!!!!!!!!!!!!!!!!!!!!DEMASIADO EXCELENTE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

    ResponderEliminar