Un poco de scripting ODF con Python en el GDLDevHouse

Me entero que la banda de HackerGarage organiza un GDLDevHouse (una especie de SuperHappyDevHouse) y me lanzo al evento, sufriendo un poco con las rutas llegué una hora y media tarde, pero llegué🙂

Yo jugué con scripting ODF en Python. Aquí un resumen de lo que aprendí:

Estructura de un ODF

Un archivo Open Document Format (ODF) es básicamente un archivo zipeado que contiene varios ficheros XML dentro de si. Lo que significa que lo primero que hacemos es descomprimir el archivo ODF, ya sea un ODP, ODT, OTS o cualquier otro. Yo usé el formato ODP.

#!/usr/bin/env python

import zipfile, os
folder = os.getcwd()
plantilla = zipfile.ZipFile(folder + '/template.odp')

Pensemos que el script y el archivo ODP viven en el mismo directorio. Después de ejecutar estas líneas “ya” los datos del fichero template.odp estarán cargados en la variable plantilla. Ahora haremos un ejercicio de instrospección, es decir, echaremos un vistazo al interior de algunos objetos. Esto lo hacemos con el comando dir():

>>> dir(plantilla)
['NameToInfo', '_GetContents', '_RealGetContents', '__del__',
...
 'infolist', 'start_dir', 'testzip', 'write', 'writestr']
>>> lista_de_archivos = plantilla.infolist()
>>> len(lista_de_archivos)
19
>>> dir(lista_de_archivos[-1])
['CRC', 'FileHeader', '__class__',
...
 'orig_filename', 'reserved', 'volume']

Al mirar dentro de plantilla podemos ver algunos de sus métodos y atributos [1]. Usamos la función infolist() que nos devuelve una lista de archivos que guardamos en la variable lista_de_archivos [5]. Esta lista tiene 19 items [6-7]. Hacemos una nueva instrospección; ahora al último de los 19 items [8].

Cada uno de esos items tiene varios atributos: data_time, filename, file_size, compress_size y orig_filename, que es con el cual vamos a trabajar:

>>> for item in lista_de_archivos: print item.orig_filename
...
mimetype
...
content.xml
styles.xml
meta.xml
Thumbnails/thumbnail.png
settings.xml
META-INF/manifest.xml

Recorremos lista_de_archivos. Los archivos más interesantes de este listado son:

  • content.xml: Quizás el más interesante de todos, muy similar a un archivo HTML.
  • META-INF/manifest.xml: Simplemente un archivo XML con un listado de todos los archivos guardados.
  • mimetype: Un archivo que contiene la línea mimetype del archivo.
  • meta.xml: Contiene información del autor, fecha de creación, etc.
  • styles.xml: Contiene la información de los estilos aplicados al texto.

Extrayendo estos archivos

Para extraer el archivo content.xml hacemos lo siguiente:

for archivo in lista_de_archivos:
  if archivo.orig_filename == 'content.xml':
    contenido = plantilla.read(archivo.orig_filename)

Podemos ver que en la variable contenido tenemos almacenado lo que hay en content.xml. Si no queremos recorrer la lista podemos hacer algo así: contenido = plantilla.read('content.xml').

Usando un XML parser

Ya tenemos el contenido XML en una variable, podemos parsearlo o con Document Object Model (DOM) o con Simple API for XML (SAX). Yo escogí hacerlo con DOM y usar la libreria xml.dom.minidom para tal efecto:

import xml.dom.minidom

def parse_and_replace(plantilla, dctn):
  contenido = plantilla.read('content.xml')
  doc = xml.dom.minidom.parseString(contenido)
  text_element = doc.getElementByTagName('text:span')
  for word in text_element:
    for w in word.childNodes:
      if w.nodeType == TEXT_NODE:
        if w.data == 'KEYWORD_ONE':
          w.data = dctn['KEYWORD_ONE']
        if w.data == 'KEYWORD_TWO':
          w.data = dctn['KEYWORD_TWO']

Lo que hicimos fue crear una función que sustituyé ciertas KEYWORDS por datos agrupados en un diccionario [9-12]. Cargar a contenido los datos, parsear la cadena y guardarla en una variable doc. Guardar en una lista aquellos tags del tipo text:span. Recorrer tal lista [6-7] y realizar las sustituciones.

El chiste era cargar estos datos de una base de datos, pero como no dió tiempo, al menos de un archivo de texto. Otra cosa que faltó fue generar el bunch de documentos a partir de estos datos. Realmente no alcancé a terminar mi programilla, quizás para el siguiente #DevHouse o en uno de mis ratos libres (que son casi nulos).

En cierta forma esto es un avance a la elaboración de constancias electrónicas del FLISoL que aún no han sido enviadas😀

Referencias

Todo lo anterior es una cuasi-traducción del tutorial Extract and Parse ODF Files with Python tomado de LINUX Journal.

El break y el momento de las minicharlas

Ya en el break la banda estaba afuera comiendo pizza y platicando sobre las aventuras escolares, el país, el sistema educativo y otras cosas. Después seguimos trabajando un rato hasta el momento de las minicharlas, entre lo más interesante de estas minicharlas un cuate de Oracle nos platicó un poco sobre un GameEngine que él ha programado a lo largo de dos años, además de mostrarnos un demo de como se iría expandiendo una población de zombies. Igualmente interesante la charla de unos amigos que quieren aventarse al mundo del cómic, también mostraron algunos demos y platicaron sobre sus ideas.

Sobre la recta final se armó el relajo y fue cuando empezaron las pláticas de anécdotas, videojuegos y cosas por el estilo. En fin, tuve la oportunidad de conocer gente interesante y con propuestas muy buenas. Ahora sólo hay que esperar el siguiente #GDLDevHouse😀

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s