
Estoy creando un flujo de trabajo semiautomatizado para el control de gastos e ingresos. Así que lo primero fue establecer las tecnologías ha utilizar.
El presupuesto que establecí es de cero dólares ($0). Y la idea es tener un núcleo tecnológico desde el nacimiento de la empresa. Y pues si te lo preguntas, tener un núcleo tecnológico en tu empresa no significa pagar licencias o instalar software pirata. Significa que tu equipo sea capaz de generar soluciones con los recursos a tu alcance.
Nos decidimos por Python, ya que podemos tener el prototipo de una aplicación básica en poco tiempo. Y con jupyter notebooks, es prácticamente como tener una hoja de cálculo en Excel.
El código este tutorial simple, lo puedes encontrar en nuestro repositorio de github:
Para poder realizar este ejercicio vamos a necesitar importar las siguientes librerías, por comodidad de este tutorial usaremos un notebook.
#librerias a utilizar
#libreria parse XML
import xml.etree.ElementTree as ET
#expresiones regulares
import re
#pandas para dataframes
import pandas as pd
#acceder a path de directorios locales
import os
La librería xml.etree.ElementTree en específico nos ofrece métodos muy sencillos para poder extraer los datos de los nodos de un XML, e incluso soporta búsquedas xpath.
Empecemos por descargar uno de los archivos XML de la página del SRI, en mi caso una de las facturas recibidas por compras:

Una vez que tienes tu archivo de ejemplo, investiguemos un poco la estructura del XML. Puedes abrir el archivo en un editor de texto de tu preferencia.

De este apartado nos interesa verificar las etiquetas o nodos existentes en el archivo. Entonces toda la etiqueta <?xml encierra el contenido que deseo obtener. Si continuo hacia abajo el siguiente nivel es <autorizacion>.
Si estas viendo el archivo en este momento, ya habras notado la similitud con un HTML (no es lo mismo), las etiquetas tienen tanto una apertura como un cierre, <apertura> </cierre>.
Dicho esto, podemos notar que la etiqueta <autorizacion> tiene una apertura y le siguen las etiquetas de:
<estado>AUTORIZADO</estado>
<numeroAutorizacion>2502202221179004027500120</numeroAutorizacion>
<fechaAutorizacion>2021-03-24T10:34:45-05:00</fechaAutorizacion>
<ambiente>PRODUCCIÓN</ambiente>
<comprobante>
Hacemos un nuevo stop, al llegar a la etiqueta <comprobante> que también aparece como una apertura, el cierre de la misma esta en parte inferior y nos hace entender que esta etiqueta contiene todos los datos resaltados en amarillos. Estos son los datos que requiero para los informes, para estructurarlos y para la aplicación que tenemos en mente.
Para este momento ya tengo el notebook con las librerías a utilizar, y abierto el archivo de ejemplo:
Obtengo el listado de ejemplo usando la librería os, para obtener todos los archivos del directorio actual. Como el objeto que me devuelve este método es una lista, puedo seleccionar uno de ellos usando notación de corchetes[].

El siguiente paso como puedes ver en la imagen es obtener el XML del archivo, esto lo realizas pasándole a la función ET.parse() la factura, seguidamente de la función .getroot() que devuelve la raíz o por decirlo de alguna manera la etiqueta que abarca a todas las demás etiquetas que estamos investigando.
Si usas type para ver de que clase de objeto se trata obtienes el siguiente resultado:
type(root)
output: xml.etree.ElementTree.Element
Para acceder al contenido debo iterar sobre la variable root, con un ciclo for, los métodos que vamos utilizar .tag, .attrib y .text que viene de la librería ET.
.tag: devuelve el nombre de la etiquetas por ejemplo autorización, estado etc.
.attrib: devuelve los valores que contiene una etiqueta lo veremos mejor en el ejemplo
.text: devuelve el contenido en tipo str que contiene una etiqueta
#verificar las etiquetas child de root
for i in root:
print(i.tag,":", i.attrib)
output:
estado : {}
numeroAutorizacion : {}
fechaAutorizacion : {}
ambiente : {}
comprobante : {}
mensajes : {}
Ten en mente que el objeto root es un diccionario, y los keys de este diccionario son los valores que estás obteniendo con la iteración. En este caso nos interesa el comprobante : {} al tratar de obtener los atributos o contenido nos devuelve un diccionario vació. Esto significa que dentro de estas etiquetas ya no existen sub-niveles o mas árboles de datos del XML. Pero esto no es verdad porque ya vimos que dentro de comprobante está toda la información de la factura. Para tener más claro el panorama envés de .attrib usamos .text y el resultado es el siguiente:

Si te fijaste, en el inicio de la investigación del archivo notaste que toda la información resaltada en amarillo esta encerrada en un <
Por último generamos dos funciones para organizar el trabajo que hemos levantado. La primera función se va encargar de obtener el texto de comprobante, y devolver los datos al diccionario, y la otra nos va ayudar a la ingesta de las facturas que tenemos listadas.


Nos resta crear un bucle que acumule los valores que me van a devolver las funciones y generar un DataFrame con los datos de los diccionarios que obtengo de mis dos facturas ejemplo.
#usando las funciones para obtener datos
#facturas seleccionadas
data_df=[]
for i in range(len(facturas)):
textos=parser(facturas[i])
data_df.append(obtener_dato(textos))
Con el resultado de data_df tenemos los datos para generar un dataframe. Así de sencillo obtuvimos los datos del archivo XML usando Python. La lógica aplicada para obtener datos de la etiqueta factura se puede replicar para investigar adicional a los datos que obtenemos, por ejemplo los detalles de cada ítem comprado, con su costo unitario, o el valor de impuesto que esta dentro de la etiqueta impuestos.

Si deseas estar pendiente de mis publicaciones, tutoriales o próximos lanzamientos de cursos de análisis de datos, te invito cordialmente a suscribirte.