Integrating with Peppol and parsing electronic invoices
28 maart 2025 - Brecht Loos
Peppol enables the secure exchange of invoices within an international network, allowing businesses and customers to seamlessly share critical documents such as invoices and orders across the globe. With the EU mandating that all B2B invoices be electronic by 2026, it’s becoming more and more important to understand what Peppol is and how it works.
In this blog post, I’ll provide a brief overview of Peppol, its functionality, and the format of electronic invoices. We’ll also explore how to develop a Java application to process these invoices.
What is Peppol?
Peppol is a network that enables businesses to send and receive structured documents. While primarily used for invoicing, it also supports electronic orders, order confirmations, and shipping documents. The network ensures compliance and governance, handling the complexities of electronic document exchange.
Most businesses don’t connect directly to Peppol but instead use a service provider. Originally developed as an EU standard, Peppol is now used globally, and it’s adopted in companies from Canada, New Zealand, the United States, and more.
For more information: What is PEPPOL?

Service Provider
A service provider offers the necessary software to connect to the Peppol network and register companies within it.
To send an invoice, a company must connect with a service provider, providing invoice details and buyer information. In most cases, businesses rely on accounting software to handle invoice generation and formatting. Many accounting platforms already integrate with a Peppol service provider, while some even function as service providers themselves.
Working with electronic invoices
Now that we’ve discussed Peppol, let’s take a deeper look into the format of electronic invoices. These are represented in the UBL (Universal Business Language) XML format version 2.1. The electronic invoice is an XML file containing all the information typically found on an invoice and can even embed the PDF file for easy viewing.
XSD
Before working with XML files, it’s important to understand their structure, which is defined by an XSD (XML Schema Definition) file. An XSD specifies the format and rules for XML documents, ensuring consistency and validity. A visual representation of a UBL document structure can be found here.
Technical implementation
Let’s explore how to work with UBL invoice XML files in Java. Our goal is to parse an XML file, extract key information, and save any embedded PDFs.
A useful open-source project for handling UBL files is ph-UBL, which supports all UBL versions. This library uses JAXB2 to convert XSD specifications into Java classes.
To use ph-UBL, add the following dependencies to your Maven project:
<dependency>
<groupId>com.helger.ubl</groupId>
<artifactId>ph-ubl21</artifactId>
<version>9.0.3</version>
</dependency>
<dependency>
<groupId>com.helger.ubl</groupId>
<artifactId>ph-ubl21-codelists</artifactId>
<version>9.0.3</version>
</dependency>
Using this, we can start processing the UBL XML invoice files.
Reading an UBL XML file
public static void readUBLXMLFile(String ublXmlFile) {
UBL21Marshaller.UBL21JAXBMarshaller invoiceMarshaller = UBL21Marshaller.invoice();
InvoiceType invoice = invoiceMarshaller.read(ublXmlFile);
}
Writing to an UBL XML file
public static void writeUBLXMLFile(File ublXmlFile, InvoiceType invoice) {
UBL21Marshaller.UBL21JAXBMarshaller invoiceMarshaller = UBL21Marshaller.invoice();
invoiceMarshaller.write(invoice, ublXmlFile);
}
Working with the generated InvoiceType
The InvoiceType object (generated by the dependencies) represents an electronic invoice but contains many nested objects and methods, making direct usage cumbersome. To simplify processing, we should transform it into a more manageable domain object.
Since method calls may return null, we need to handle potential NullPointerExceptions carefully. Here are two approaches:
1. Higher order functions with Supplier<T>
With the Supplier<T> type, we can create a function that takes no arguments but returns a value. This allows us to delay execution and catch NullPointerException errors gracefully.
public static T returnValueOrNull(Supplier supplier) {
try {
return supplier.get();
} catch (NullPointerException e) {
return null;
}
}
Usage:
buyer = getValueOrNull(() ->
invoice.getAccountingCustomerParty().getParty().getPartyName().get(0).getNameValue());
2. Optional pattern
An alternative approach is to use Java’s Optional API for safer method chaining:
buyer = Optional.ofNullable(invoice)
.map(InvoiceType::getAccountingCustomerParty)
.map(CustomerPartyType::getParty)
.map(PartyType::getPartyName)
.map(List::getFirst)
.map(PartyNameType::getNameValue)
.orElse(null);
Extracting Embedded PDFs
Suppliers can optionally embed a PDF file within the XML invoice. This is useful because the XML allows software to process invoice data, while the PDF provides a human-readable version.
To extract the PDF:
file = getValueOrNull(() ->
invoice.getAdditionalDocumentReference().get(1).getAttachment().getEmbeddedDocumentBinaryObjectValue());
Conclusion
In this blog post, we explored multiple methods for extracting data from an electronic invoice. We discussed the Peppol network, how service providers facilitate communication, and how UBL XML invoices are structured.
We also examined different approaches for parsing, reading, and writing these XML files using Java. Additionally, we looked at best practices for safely extracting data using higher-order functions and the Optional pattern, ensuring robust and error-free code.
By leveraging open-source libraries like ph-UBL, developers can seamlessly integrate Peppol invoices into their applications. Whether it’s handling structured invoice data or extracting embedded PDFs.
This approach allows us to develop applications capable of generating and reading Peppol invoices. It is especially useful as it reduces our reliance on existing providers and their specific implementations. Instead, we can create a custom solution tailored to the needs of our own applications.