Convertir documentos del SII (Chile), de XML a PDF

Usar Python para parsear documentos XML del SII y transformarlos a formato pdf, incluyendo el código de barras.

Toni Cañada
5 min readFeb 23, 2021

El Servicio de Impuestos Internos de Chile (SII) funciona mediante archivos XML. Es decir, todos los documentos (facturas, guías de despacho, notas de crédito, etc) son en realidad archivos XML.

Estos XML llegan a un email que cada empresa designa, también se pueden bajar desde el portal web del SII (sistema de facturación gratuito), o mediante software’s de pago que gestionan la facturación. La mayoría de estos últimos los permite bajar masivamente.

Conocer la estructura de estos XML y poderlos parsear es algo muy conveniente para cualquier empresa, dado que contienen la información de las compras/ventas con todo el detalle. Las empresas, mediante eso, pueden, por ejemplo:

  • Generar un excel donde se detallan todas las facturas de compra de la empresa, a nivel de detalle de item (posteriormente en el artículo se explica cómo).
  • Permitir la integración del sistema de facturación con otros sofware de la empresa (por ejemplo ERPNext).
  • Generar una base de datos que puede ser usada en Machine Learning para estudiar las compras o ventas, y estudiar tendencias sacando conclusiones.
  • Generar un PDF a partir de cada XML (de esto trata este artículo).
  • Etcétera… En resumen, estos XML están al alcance de todas las empresas chilenas, y son una fuente de información estructurada de la cual normalmente no se obtiene todo su potencial.

A continuación se explican los pasos para escribir un programa en Python que transforme todos los documentos XML que estén en una carpeta “input” y los guarde como PDF en la carpeta “output”.

El código está subido en el siguiente repositorio de Github:

La estructura de los archivos XML está explicada en detalle por el SII en el siguiente link, pero básicamente se compone de:

  • Encabezado
    Aquí están los datos generales del documento (IdDoc), información del emisor, del receptor, y los totales. El código de ejemplo siguiente es de una factura ficticia.
<Encabezado>
<IdDoc>
<TipoDTE>33</TipoDTE>
<Folio>284380</Folio>
<FchEmis>2021-01-30</FchEmis>
<FmaPago>2</FmaPago>
<TermPagoCdg>9</TermPagoCdg>
<TermPagoGlosa>3 Cta Cte - 30 D</TermPagoGlosa>
<TermPagoDias>30</TermPagoDias>
</IdDoc>
<Emisor>
<RUTEmisor>22222222-2</RUTEmisor>
<RznSoc>Centro Hermanos SpA</RznSoc>
<GiroEmis>Ferreteria Y Materiales De Construccion</GiroEmis>
<Telefono>996445598</Telefono>
<CorreoEmisor>fgarcia@centrohermanos.cl</CorreoEmisor>
<Acteco>475201</Acteco>
<DirOrigen>Atesur 4201</DirOrigen>
<CmnaOrigen>Renca</CmnaOrigen>
<CiudadOrigen>Santiago</CiudadOrigen>
<CdgVendedor>6</CdgVendedor>
</Emisor>
<Receptor>
<RUTRecep>11111111-1</RUTRecep>
<RznSocRecep>Constructora Begur S.A.</RznSocRecep>
<GiroRecep>No Indicado</GiroRecep>
<Contacto>Manuel García</Contacto>
<CorreoRecep>mgarcia@begur.cl</CorreoRecep>
<DirRecep>Isidora Valdivia 3600 oficina 61</DirRecep>
<CmnaRecep>Las Condes</CmnaRecep>
<CiudadRecep>Santiago</CiudadRecep>
</Receptor>
<Totales>
<MntNeto>1051267</MntNeto>
<MntExe>0</MntExe>
<TasaIVA>19</TasaIVA>
<IVA>199741</IVA>
<MntTotal>1251008</MntTotal>
</Totales>
</Encabezado>
  • Detalle
    Aquí va el detalle por item del documento, habrá tantas etiquetas “Detalle” como items tenga el documento electrónico. En cada línea se especifica, por lo menos, el nombre del item (NmbItem), la cantidad (QtyItem), el precio (PrcItem), y el monto (MontoItem). Hay muchas otras etiquetas que se pueden usar, como descuento, códigos internos del proveedor, etc, pero no es obligatorio usarlas.
<Detalle>
<NroLinDet>1</NroLinDet>
<CdgItem>
<TpoCodigo>INT1</TpoCodigo>
<VlrCodigo>002867</VlrCodigo>
</CdgItem>
<NmbItem>Llave P/Corona 6 Force</NmbItem>
<QtyItem>6.00</QtyItem>
<UnmdItem>Unid</UnmdItem>
<PrcItem>1252</PrcItem>
<MontoItem>7512</MontoItem>
</Detalle>
<Detalle>
<NroLinDet>2</NroLinDet>
<CdgItem>
<TpoCodigo>INT1</TpoCodigo>
<VlrCodigo>002869</VlrCodigo>
</CdgItem>
<NmbItem>Llave P/Corona 8 Force</NmbItem>
<QtyItem>6.00</QtyItem>
<UnmdItem>Unid</UnmdItem>
<PrcItem>1269</PrcItem>
<MontoItem>7614</MontoItem>
</Detalle>
<Detalle>
<NroLinDet>3</NroLinDet>
<CdgItem>
<TpoCodigo>INT1</TpoCodigo>
<VlrCodigo>007097</VlrCodigo>
</CdgItem>
<NmbItem>Dado 1/2*06Mm Force</NmbItem>
<QtyItem>3.00</QtyItem>
<UnmdItem>Unid</UnmdItem>
<PrcItem>1288</PrcItem>
<MontoItem>3864</MontoItem>
</Detalle>
  • Referencias
    Aquí se indican las referencias del documento electrónico, por ejemplo, en el caso de una factura de compra, pueden ser las guías de despacho, o la orden de compra. Este dato es relevante para la integración con otros software’s de la empresa.
<Referencia>
<NroLinRef>1</NroLinRef>
<TpoDocRef>ND</TpoDocRef>
<FolioRef>785</FolioRef>
<FchRef>2020-12-31</FchRef>
</Referencia>
<Referencia>
<NroLinRef>2</NroLinRef>
<TpoDocRef>801</TpoDocRef>
<FolioRef>OC-13682</FolioRef>
<FchRef>2020-12-31</FchRef>
</Referencia>
<Referencia>
<NroLinRef>3</NroLinRef>
<TpoDocRef>NV</TpoDocRef>
<FolioRef>5611</FolioRef>
<FchRef>2020-12-31</FchRef>
</Referencia>
<Referencia>
<NroLinRef>4</NroLinRef>
<TpoDocRef>52</TpoDocRef>
<FolioRef>278614</FolioRef>
<FchRef>2021-01-04</FchRef>
</Referencia>
<Referencia>
<NroLinRef>5</NroLinRef>
<TpoDocRef>52</TpoDocRef>
<FolioRef>278641</FolioRef>
<FchRef>2021-01-06</FchRef>
</Referencia>
  • Timbre electrónico
    Aquí va un string (resumen del documento) que se usará posteriormente para generar un código de barras.
<TED version="1.0">
<DD>
<RE>22222222-2</RE>
<TD>33</TD>
<F>284380</F>
<FE>2021-01-30</FE>
<RR>11111111-1</RR>
<RSR>Constructora Begur S.A.</RSR>
<MNT>1251008</MNT>
<IT1>Llave P/Corona 6 Force</IT1>
<CAF version="1.0">
...
</CAF>
<TSTED>2021-01-30T11:49:26</TSTED>
</DD>
<FRMT algoritmo="SHA1withRSA">
...
</FRMT>
</TED>

Una vez hemos entendido la estructura del XML, podemos parsearlo usando la librería xml.etree.elementtree.html de Python. Hay veces que el documento no contiene algunas etiquetas, como el caso del giro o la dirección, es por eso que el código se anticipa a eso, y si no hay datos (None), lo completa con un 0.

# Datos emisorself.rut_proveedor = self.tree.find('.//{http://www.sii.cl/SiiDte}RUTEmisor').textself.razon_social = self.tree.find('.//{http://www.sii.cl/SiiDte}RznSoc').textself.giro_proveedor = self.tree.find('.//{http://www.sii.cl/SiiDte}GiroEmis').text if self.tree.find(
'.//{http://www.sii.cl/SiiDte}GiroEmis') is not None else 0
self.direccion_proveedor = self.tree.find('.//{http://www.sii.cl/SiiDte}DirOrigen').text if self.tree.find(
'.//{http://www.sii.cl/SiiDte}DirOrigen') is not None else 0

El repositorio tiene una clase llamada DTE.py que realiza el parseo necesario para generar el posterior pdf.

Ahora, mediante esta clase, ya podemos sacar cualquier información del archivo XML.

Uno de los usos más simples, tal como se ha comentado anteriormente, y a la vez muy útil, es generar un excel con el detalle de los XML que haya en una carpeta. Esto se hace en el script_obtiene_excel.py de forma muy sencilla mediante pandas.

from xml_to_pdf_functions import append_xml_to_df
import pandas as pd
import os

path = "./input"

# Genera un excel con el detalle de los XML de la carpeta "input"
df = pd.DataFrame(
columns=["rut", "fecha", "folio", "montoNeto", "referencias_oc", "tipoDoc", "items", "comuna"]
)
for filename in os.listdir(path):
df = append_xml_to_df(df, f"{path}/{filename}")
df.to_excel("./output/listado_xml.xlsx")

Para generar el PDF a partir del XML se utiliza la librería WeasyPrint, que mediante un template html y css, genera el documento. Para generar el código de barras se usa la librería pdf417. Hay una app para celular que permite leer estos códigos.

Podemos sacar aún mayor partido del parseo del XML y nombrar estructuradamente cada PDF. Por ejemplo, en el repositorio se nombran los PDF de la siguiente manera:

"AAAAMMDD" + " " + "AbreviaturaTipoDTE" + " " + "Razón Social" + " " + "Número documento " + ".pdf"

Ejemplo de nombre: “20210130 FC Centro Hermanos Spa 284380.pdf”

Finalmente se guardan todos los PDF en la carpeta “output”.

--

--

Toni Cañada

Civil engineer passionate about business administration and coding.