Saxon Visualize electronic Invoices in Xojo

When you receive an electronic invoice in the formats ZUGFeRD, Factur-X, X-Rechnung or UBL, you may need to visualize the XML file in your Xojo application. You can use our DynaPDF classes to extract the XML from the ZUGFeRD invoice. Once you have the XML for one of the formats UBL or Cross Industry Invoice, you may want to convert it to HTML and show it in a HTMLviewer.

We leverage the XRechnung Visualization Transformators project from GitHub. This project has a couple of XML stylesheets to convert our invoices to HTML. For this they first convert the UBL or CII XML to an intermediate XML and finally convert that to XML with a second transformation. There is also an alternative output to produce a XML for Apache FOP to make it a PDF file.

Step 1: Load Saxon

First load the Saxon library using our SaxonMBS module. You download the libraries either from our website or directly from Saxonica website. We suggest to copy the Saxon library to the same folder as the plugin. Then you only need to pass the library file name to load it.

	// load library
	
	#If TargetMacOS
		Var path As String = "/Users/cs/Libs/saxon/SaxonCEE-12.9/SaxonCEE-macos-universal-12-9-0/libsaxonc-core-ee.12.9.0.dylib"
	#ElseIf TargetWindows
		Var path As String = "saxonc-core-ee.dll"
	#ElseIf TargetLinux Then
		Var path As String = "libsaxonc-core-ee.so.12.9.0"
	#Else
		// not supported
	#EndIf
	
	Var bb As Boolean = SaxonMBS.LoadLibrary(path)
	
	// we have libraries here:
	// https://www.monkeybreadsoftware.com/filemaker/files/Libs/Saxon/
	
	If bb Then
		// okay
	Else
		MessageBox "Failed to load Saxon library. Did you download it and adjust path in this example?"_
			+EndOfLine+SaxonMBS.LoadErrorString
		Break
		Return
	End If

Step 2: Check the type

The main script loads Saxon if needed. Then we check if we got the folder with the xrechnung-visualization xsl files. You download the release of xrechnung-visualization, unpack the zip/tar file and then tell our plugin the native path to the xsl folder, e.g. “/Users/cs/xrechnung-3.0.2-xrechnung-visualization-2024-06-20/xsl”.

We check the content of the XML and if it contains the namespace declaration for UBL, we use the ubl-invoice-xr.xsl stylesheet to transform the XML. But if we find the CrossIndustryInvoice namespace, we can use the cli-xr.xsl stylesheet instead and call the Run method.

	// you can use DynaPDF functions to extract XML from PDF
		
	Var f As FolderItem = FolderItem.ShowOpenFileDialog(FileTypeGroup1.XML)
		
	If f = Nil Then Return
		
	Var b As BinaryStream = BinaryStream.Open(f)
	Var XML As String = b.Read(b.Length, encodings.UTF8)
		
	// is it an UBL or CII file?
	If XML.InStr("urn:oasis:names:specification:ubl:schema:xsd:Invoice") > 0 Then
		Run XML, UBLFile
	elseif XML.InStr("unece:uncefact:data:standard:CrossIndustryInvoice") > 0 Then
		Run XML, CIIFile
	End If

Step 3: Perform conversion

In the following script we perform the transformation. We first set the working directory to the xsl folder, so the related files referenced by the stylesheet can be found. Technically you could resolve this and make it one big stylesheet, but we just use them as they are. And the stylesheets need the common-xr.xsl file with common transformations. We read the XSLT to use and apply it on the invoice XML. When we get that XML, we can apply the stylesheet xrechnung-html.xsl to create the HTML using the XSLT convenience function in SaxonMBS module. When we store the HTML in the field, our web viewer shows it.

Sub Run(XML as string, XSLFile as FolderItem)
	// Apply XSLT to create html and show invoice.
	
	// Set the folder to find related files
	SaxonMBS.CWD = XSLFolder.NativePath
	
	// read the XSLT to convert
	Var b As BinaryStream = BinaryStream.Open(XSLFile)
	Var styleSheet As String = b.Read(b.Length, Encodings.UTF8)
	
	// Apply the XSLT
	// we use the quick function here. For more options use Xslt30ProcessorMBS class.
	var IntermediateXML as string = SaxonMBS.XSLT(XML, styleSheet)
	
	// now read second XSL to convert to html
	var xf as FolderItem = XSLFolder.Child("xrechnung-html.xsl")
	Var b2 As BinaryStream = BinaryStream.Open(xf)
	Var HTMLXSLT As String = B2.Read(b2.Length, encodings.UTF8)
	
	// Generate the HTML
	var InvoiceHTML as string = SaxonMBS.XSLT(IntermediateXML, HTMLXSLT)
	
	HTMLViewer1.LoadPage InvoiceHTML, xf
End Sub

To have the Xojo HTMLViewer show the html, we call LoadPage method and pass the html. To clear the HTMLViewer, you can load “about:blank” to see an empty page.

If you need more control, you can use Xslt30ProcessorMBS class and set various properties and options. Then call transform yourself there.

Please try and let us know if you like it. You may want to modify the stylesheet if you prefer a different style. Our Saxon classes are in the MBS Xojo XML Plugin.

3 Likes

Thanks, Christian! It’s always interesting and useful!

1 Like

Sure, see also:

Validate electronic invoices with Saxon in Xojo

1 Like