Saltar al contenido

🧾 Cómo extraer datos de facturas XML del SRI y analizarlos en Power BI

ChatGPT Image 14 abr 2025 21 42 33

🗓️ Actualizado en mayo de 2026.

TL;DR: las facturas electrónicas del SRI vienen en XML con el comprobante envuelto en una sección CDATA. Con un script de Python (pandas + lxml) puedes recorrer una carpeta de XML, extraer emisor, fechas y detalle de productos, y construir una tabla lista para Power BI. Aquí tienes el script completo, cómo cargarlo desde el conector de Python y una alternativa 100% en Power Query (lenguaje M) que sí refresca en el servicio.


🧾 Cómo extraer datos de facturas XML del SRI y analizarlos en Power BI

Power BI: Power Query Limpiar y extraer Datos con Lenguaje MUdemy
Power Query

Power BI: Power Query Limpiar y extraer Datos con Lenguaje M

★ 4.6(1100 estudiantes)
$54.99

En el mundo del análisis financiero, la automatización del procesamiento de documentos electrónicos es una necesidad creciente. En Ecuador, el Servicio de Rentas Internas (SRI) utiliza el formato XML para sus comprobantes electrónicos, lo que abre la puerta a la integración de estos datos con herramientas de análisis como Power BI.

En este artículo, aprenderás cómo construir un script en Python que extrae la información clave de facturas XML del SRI y genera una tabla estructurada lista para análisis. Además, te mostraré cómo ejecutar este proceso dentro de Power BI utilizando el conector de Python.


📦 ¿Qué contiene una factura electrónica del SRI?

Cada archivo XML de factura contiene una estructura jerárquica con bloques importantes:

  • <infoTributaria>: datos del emisor
  • <infoFactura>: información general de la venta
  • <detalles>: productos o servicios vendidos
  • <impuestos>: tributos aplicados
  • <comprobante>: en algunos casos está envuelto en una sección CDATA

🔧 El script en Python

A continuación, te comparto un script que:

  1. Carga el XML desde archivo
  2. Extrae el contenido del <comprobante> si existe
  3. Parsea el contenido como XML
  4. Extrae la información general de la factura
  5. Recorre los productos y genera un DataFrame de pandas
import pandas as pd
import os
from lxml import etree as ET

def cargar_xml_desde_archivo(ruta_archivo: str) -> ET.Element:
    try:
        return ET.parse(ruta_archivo).getroot()
    except ET.XMLSyntaxError as e:
        print(f"Error al parsear XML: {e}")
        return None

def extraer_cdata_comprobante(root: ET.Element) -> str:
    comprobante = root.find("comprobante")
    if comprobante is None or comprobante.text is None:
        raise ValueError("Etiqueta <comprobante> o CDATA ausente.")
    return comprobante.text

def parsear_comprobante(cdata: str) -> ET.Element:
    try:
        return ET.fromstring(cdata.encode('utf-8'))
    except ET.XMLSyntaxError as e:
        print(f"Error al parsear CDATA como XML: {e}")
        return None

def extraer_info_general(factura_root: ET.Element) -> dict:
    info = factura_root.find("infoTributaria")
    info_factura = factura_root.find("infoFactura")
    return {
        "razonSocial": info.findtext("razonSocial", ""),
        "fechaEmision": info_factura.findtext("fechaEmision", ""),
        "estab": info.findtext("estab", ""),
        "ptoEmi": info.findtext("ptoEmi", ""),
        "secuencial": info.findtext("secuencial", ""),
        "ruc": info.findtext("ruc", "")
    }

def extraer_detalles_productos(factura_root: ET.Element, info_general: dict) -> list:
    productos = []
    for detalle in factura_root.findall(".//detalle"):
        descripcion = detalle.findtext("descripcion", "")
        cantidad = float(detalle.findtext("cantidad", "0"))
        precio_unitario = float(detalle.findtext("precioUnitario", "0"))
        base_imponible = sum(float(imp.findtext("baseImponible", "0"))
                             for imp in detalle.findall(".//impuesto"))
        producto = {
            **info_general,
            "descripcion": descripcion,
            "cantidad": cantidad,
            "precioUnitario": precio_unitario,
            "baseImponible": base_imponible
        }
        productos.append(producto)
    return productos

def construir_tabla(productos: list) -> pd.DataFrame:
    return pd.DataFrame(productos)

def procesar_factura_xml(ruta_archivo: str) -> pd.DataFrame:
    root = cargar_xml_desde_archivo(ruta_archivo)
    if root is None:
        return pd.DataFrame()
    try:
        cdata = extraer_cdata_comprobante(root)
        factura_root = parsear_comprobante(cdata)
        if factura_root is None:
            return pd.DataFrame()
    except ValueError as e:
        print(e)
        return pd.DataFrame()

    info_general = extraer_info_general(factura_root)
    productos = extraer_detalles_productos(factura_root, info_general)
    return construir_tabla(productos)

if __name__ == '__main__':
    facturas = os.listdir("../uploads")
    data_f = []
    for fact in facturas:
        if fact.endswith(".xml"):
            df_factura = procesar_factura_xml(os.path.join("../uploads", fact))
            data_f.append(df_factura)
    df = pd.concat(data_f, ignore_index=True)
    print(df)

📊 ¿Cómo integrar este script con Power BI?

  1. Ubica el script anterior en un archivo .py. Guarda por ejemplo como procesar_facturas.py.
  2. En Power BI Desktop:
    • Ve a Inicio > Obtener datos > Más > Otros > Script de Python
    • Selecciona el archivo o copia el fragmento que contiene solo la función principal (procesar_factura_xml) y la ejecución del bloque final.
  3. Coloca los archivos XML en una carpeta local, preferiblemente dentro del proyecto Power BI.
  4. Asegúrate de tener instaladas las librerías pandas y lxml en tu entorno Python usado por Power BI.
pip install pandas lxml

📈 Beneficios del análisis automatizado

  • Reducción de errores humanos
  • Estandarización de datos contables
  • Preparación para BI y modelos de predicción
  • Visibilidad rápida de montos, fechas, productos y clientes

🟢 Alternativa sin Python: extraer el XML con Power Query (lenguaje M)

El conector de Python es ideal para explorar, pero en el servicio de Power BI requiere una puerta de enlace personal y suele ser frágil al refrescar. Si necesitas que el dataset se actualice en la nube sin fricción, hazlo 100% en Power Query (lenguaje M): lee la carpeta, abre cada XML, navega al nodo <comprobante> (que trae la factura como texto CDATA) y vuélvelo a parsear. Este es el punto de partida:

let
    Carpeta = Folder.Files("C:\Facturas_SRI"),
    SoloXml = Table.SelectRows(Carpeta, each Text.EndsWith([Name], ".xml")),
    Parseado = Table.AddColumn(SoloXml, "Factura", each
        let
            doc = Xml.Document([Content]),
            // el nodo <comprobante> trae el XML de la factura como texto (CDATA)
            textoFactura = doc{[Name="autorizacion"]}[Value]{[Name="comprobante"]}[Value],
            factura = Xml.Document(Text.ToBinary(textoFactura))
        in
            factura),
    // a partir de aqui expandes infoTributaria, infoFactura y detalles
    Expandida = Table.ExpandTableColumn(Parseado, "Factura", {"Name", "Value"})
in
    Expandida

⚠️ Errores comunes al parsear facturas del SRI

SíntomaCausaSolución
Etiqueta <comprobante> o CDATA ausenteEl XML es la factura directa, no el comprobante autorizado del SRIParsea el root directamente, sin extraer el CDATA
baseImponible vacío o 0El detalle no trae el bloque <impuestos>Usa un valor por defecto y valida con findtext(…, «0»)
Caracteres corruptos (tildes, ñ)Codificación distinta de UTF-8Codifica con .encode("utf-8") antes de re-parsear
Refresco falla en el servicioScript de Python sin gatewayMigra a la versión en Power Query (M) de arriba

¿Te topas con el clásico DataFormat.Error al cargar? Revisa cómo resolver el DataFormat.Error en Power Query. Y si reutilizas la lógica en varias consultas, mira cómo una consulta puede referenciar a otra. La estructura oficial del comprobante está en la documentación de facturación electrónica del SRI.


🧠 Conclusión

Automatizar la extracción de datos de las facturas electrónicas del SRI usando Python es una excelente manera de preparar información para su análisis en Power BI. Este enfoque te permite tener control total sobre la estructura de tus datos y garantizar la calidad del análisis financiero o comercial que realices.

¿Te gustaría que preparemos una plantilla de Power BI con este flujo ya armado? Déjamelo saber en los comentarios.

Comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *