Usar XSL-FO para personalizar facturas electrónicas – Parte 1

Hace poco me preguntaron si había alguna forma de personalizar las facturas electrónicas que produce el SAT en México, ya saben, las facturas generadas por la opción de facturación gratuita en la página del SAT que parece haber sido diseñada por un alumno de prepa en su primer curso de HTML (te perdiste la mejor parte si no estuviste ahí para ver la página cuando requería versiones viejas/obsoletas de Java). En fin, ya que tengo esta mala costumbre de siempre hacer las cosas de la manera difícil 😛 decidí buscar las alternativas free open source para llevar a cabo la tarea de personalizar las facturas electrónicas. Por supuesto, hay versiones comerciales de software que prometen hacerlo de una forma sencilla, incluso versiones online “gratuitas” que no puedes personalizar a menos que compres una licencia. Las alternativas free open source existen pero, como era de esperarse, requiren hacerlo de la manera difícil. En este caso, una de estas alternativas es usar XSL-FO en conjunto con Apache FOP. Usar CSS3 para formatear el documento XML de la factura es otra opción1.

Nota: En la versión 3.3 del formato XML oficial del SAT, algunos campos cambiaron únicamente en el nombre de los campos de minúsculas (por ejemplo, nombre) a primera letra mayúscula (por ejemplo, Nombre). Ese es un cambio estúpido. No sólo pudieron mantener compatibilidad con versiones viejas al mantener el nombre el minúsculas, sino que al hacer este cambio innecesario rompieron todo el software que ya se había programado para versiones viejas; ¡el campo DomicilioFiscal no sólo ya no es requerido sino que ya no es ni siquera opcional ni está documentado! ¡¿Qué rayos estaban pensando?! Esto significa que ahora el domicilio debe estar escrito manualmente en el código y que debes crear una versión diferente del archivo XSL-FO para cada empresa que quiera facturar usando tu código, ¡es estúpido!. Lo mismo pasa con el domicilio del receptor, si quieres imprimir la dirección del receptor en cada una de tus facturas, entonces estás en problemas, buena suerte con eso. Al menos supongo que aún se puede inyectar ese campo en un XML para hacerlo más o menos compatible con software viejo sin tener que hacer grandes cambios.

En fin, ¿qué más se puede esperar de la gente que programó el portal de facturación electrónica del SAT?. En esta serie de posts usaré la versión 3.3 del formato XML del SAT.

Ya antes había usado la combinación de XSL-FO y Apache FOP así que decidí probar suerte con esta opción. XSL-FO permite definir un diseño para imprimir documentos XML como el de las facturas electrónicas del SAT.

En este post trataremos de crear un diseño simple para una factura sencilla. La definición del diseño se lleva a cabo creando un archivo con la extensión .fo que junto con el .xml de la factura nos permitirá generar un archivo PDF. Debo dejar claro que no soy un experto en este tema así que sólo debes tomar el contenido de este post como un ejemplo o guía básica de XSL y XSL-FO.

El punto principal a comprender aquí es que un documento XML como el de la factura electrónica está diseñado para contener datos pero un documento XML no incluye información sobre cómo deben ser presentados esos datos en la pantalla. Normalmente, sin embargo, es necesario mostrar esos datos de una forma amigable al usuario, aquí es donde entra en juego XSL. XSL es un lenguaje definido por el W3C para auxiliar en la presentación de los datos de un archivo XML. Básicamente, haciendo uso de XSL, puedes extraer los datos de un archivo XML y transformarlos, por ejemplo, en código HTML que puede ser presentado en un navegador de internet y formateado con CSS, o transformarlos en código XSL-FO para definir el diseño de un documento y producir un archivo PDF. Cuál opción es mejor depende de ti; por ejemplo, si eres un mago del CSS tal vez la primera opción sea lo mejor para ti. En el caso de este post, usaremos XSL-FO; lo importante es recordar que XSL y XSL-FO son dos cosas distintas que al usarse juntas nos permitirán generar un documento PDF. XSL nos permite extraer y transformar los datos de un archivo XML, XSL-FO nos permite definir un diseño para presentar esos datos.

En general, el elemento principal de un archivo XSL es el elemento xsl:stylesheet; en este elemento principal podemos definir los namespaces de XML que serán usados en el documento2. Así, por ejemplo, nuestro archivo XSL para las facturas del SAT se vería así:

¡Felicidades, acabas de crear tu primer archivo XSL para las facturas del SAT! Sin embargo no hace mucho por ahora 😛 .

Para que nuestro archivo haga algo útil debemos definir al menos un elemento de tipo xsl:template que define, como el nombre lo indica, una plantilla para transformar un bloque de datos en el archivo XML. Cada elemento xsl:template está asignado a una coincidencia con algún elemento en el archivo XML. Cuando XSL encuentre una coincidencia en el archivo XML, aplicará la plantilla definida en el elemento xsl:template. La coincidencia “/” es equivalente a todo el documento XML. Por ejemplo, agreguemos una plantilla simple a nuestro archivo XSL:

Debes poner esta plantilla como un elemento anidado dentro del elemento xsl:stylesheet en el archivo XSL, de forma que el archivo completo debe lucir así:

En adelante no escribiré el código completo del archivo así que espero que puedas seguir el resto del post 😛 . El archivo XSL anterior usa la plantilla que hemos definido para generar el código HTML cuando encuentra un documento XML, indicado por la coincidencia “/”. Como lo mencioné antes, hay varias opciones para procesar XSL; para ver este ejemplo sencillo en acción, podemos comenzar instalando el paquete xsltproc desde el gestor de paquetes. Una vez instalado, podemos probar el código XSL anterior con el siguiente comando:

monstruosoft@monstruosoft-PC:~$ xsltproc -o ejemplo.html ejemplo.xsl factura.xml

El comando anterior produce el siguiente archivo HTML:

2017-10-05-181338_1366x768_scrot

Hay otra forma de aplicar las transformaciones definidas en un archivo XSL a un documento XML y consiste en editar el documento XML para hacer referencia al archivo XSL; al hacer esto, la transformación será aplicada automáticamente al abrir el XML en el navegador (adelante, inténtalo):

De acuerdo, imprimir “Hola mundo” es difícilmente útil. En nuestro archivo XSL podemos definir más de una plantilla para distintas coincidencias en el código XML de la factura. Así por ejemplo, podemos cambiar la plantilla básica que escribimos en el ejemplo anterior para aplicar recursivamente otras plantillas según encuentre coincidencias en el archivo XML, para esto usamos el elemento xsl:apply-templates. Como el nombre lo indica, este elemento aplicará otras plantillas si encuentra elementos que coincidan con las plantillas definidas, así que en nuestro archivo XSL podemos cambiar nuestra plantilla principal y definir nuevas plantillas, por ejemplo (nota que la plantilla original ha sido modificada):

2017-10-05-182819_1366x768_scrot

Como puedes ver, el código anterior aplica las plantillas de forma recursiva e imprime la información del campo de descripción de cada concepto en el XML de la factura. Si pruebas este código con un archivo de factura electrónica del SAT verás que el HTML resultante ahora tiene mucha más información relevante. A pesar de ser un ejemplo tan sencillo, demuestra el potencial de XSL para definir la presentación de los datos contenidos en un archivo XML como el de la factura electrónica. Si estás interesado en la ruta de usar HTML y CSS3 para personalizar tus facturas, este simple ejemplo debería darte las bases para continuar.

En esta serie de posts, estamos interesados en usar XSL-FO. Cabe notar que actualmente XSL+HTML+CSS3 es considerada la mejor opción para presentar la información de un archivo XML. Si eres un mago del CSS3 tal vez te resulte más fácil usar esa opción. Yo no soy un mago del CSS3, así que en el siguiente post veremos una introducción a XSL-FO.


Referencias:

2. Es imposible discutir a fondo todos los temas tratados en este post. Para más información sobre los namespaces de XML visita la siguiente página: https://www.w3schools.com

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s