Welcome | Get started | Dive | Contribute | Topics | Reference | Changes | More

Lino and XML

This page contains code snippets (lines starting with >>>), which are being tested during our development workflow. The following snippet initializes the demo project used throughout this page.

>>> from lino_book.projects.cosi1.startup import *

Payment orders

See Write an XML file of a payment order.

Intracom statements

Peppol documents

Peppol documents means invoices and credit notes, both sales and purchases.

While Payment orders and Intracom statements still have a button that opens the generated XML file in a new browser window, this is actually just a temporary solution. Actually the end user shouldn’t even see these files.

So unlike payment orders and Intracom statements, Peppol documents use the new lino.modlib.jinja.XMLMaker model mixin.

>>> for m in rt.models_by_base(jinja.XMLMaker):
...     if m.xml_file_template:
...         print(full_model_name(m), m.xml_file_template, m.xml_validator_file)
...
trading.VatProductInvoice vat/peppol-ubl.xml .../lino_xl/lib/vat/XSD/PEPPOL-EN16931-UBL.sch
vat.VatAccountInvoice vat/peppol-ubl.xml .../lino_xl/lib/vat/XSD/PEPPOL-EN16931-UBL.sch

The following starts as in Outbound documents to find our latest sales invoice and call XmlMaker.make_xml_file() on it, but then we focus on validation.

>>> ar = rt.login("robin")
>>> qs = trading.VatProductInvoice.objects.filter(journal__ref="SLS")
>>> obj = qs.order_by("accounting_period__year", "number").last()
>>> obj
VatProductInvoice #177 ('SLS 15/2015')

XmlMaker.make_xml_file() renders the XML file and returns a MediaFile descriptor for it:

>>> with ar.print_logger("DEBUG"):
...     xmlfile = obj.make_xml_file(ar)
weasy2pdf render ['trading/VatProductInvoice/default.weasy.html', 'excerpts/default.weasy.html']
-> .../media/cache/weasy2pdf/SLS-2015-15.pdf ('de', {})
SLS-2015-15.pdf has been built.
Make .../cosi1/media/xml/2015/SLS-2015-15.xml from SLS 15/2015 ...
>>> xmlfile.path
PosixPath('.../cosi1/media/xml/2015/SLS-2015-15.xml')
>>> xmlfile.url
'/media/xml/2015/SLS-2015-15.xml'

We can see that the jinja.XmlMaker.xml_validator_file() points to the file PEPPOL-EN16931-UBL.sch, which is an unmodified copy from https://docs.peppol.eu/poacc/billing/3.0/

Despite the logger message, jinja.XmlMaker.make_xml_file() currently does nothing when the validator file ends with “.sch”.

This is because we didn’t yet find a way to run Schematron validation under Python. See Schematron validation for more about this.

>>> dbhash.check_virgin()
Database ...isn't virgin:
- excerpts.Excerpt: 1 rows added
Tidy up 1 rows from database: [(<class 'lino_xl.lib.excerpts.models.Excerpt'>, {...})].
Database has been restored.