Using XRechnung / ZUGFeRD XML to Create PDF/A-3b Invoices with ASP.NET Core C#
This article shows how to create invoices with XRechnung and ZUGFeRD XML files using ASP.NET Core C# and the MailMerge class of TX Text Control .NET Server. The MailMerge class is used to merge data into templates to create invoices in PDF/A format.

XRechnung is an XML-only format specifically created for processing digital invoices. ZUGFeRD, on the other hand, integrates a human-readable PDF format with a machine-readable XML format. Since the release of ZUGFeRD version 2.1, it is possible to combine the XML output from XRechnung with the method of embedding XML into a PDF file.
Generating ZUGFeRD Invoices
TX Text Control can be used to create ZUGFeRD documents by generating a PDF/A-3b document and attaching the XML content.
Learn More
This article shows how to create valid XRechnung and ZUGFeRD invoices with ASP.NET Core C#. The invoice is created with the help MailMerge component and the ZUGFeRD-csharp library.
Creating Valid XRechnung / ZUGFeRD Invoices with ASP.NET Core C#
The above article explains how to generate the XML that is required and how to attach the XML to a PDF document in order to generate a valid electronic invoice (e-invoice).
But what if you get the valid XML from your ERP system or any other billing system?
In this case, TX Text Control can be used to generate a human-readable, perfectly formatted invoice based on the valid XML data used as the data source for Mail
MailMerge with XML Data Source
MailMerge takes a template with placeholder merge fields and repeating merge blocks and populates them with data from data sources such as JSON or XML. This example shows how to use the XRechnung / ZUGFeRD XML as a data source to create a PDF invoice.
Consider the following sample XRechnung 3.0 XML:
<?xml version="1.0" encoding="utf-8"?>
<rsm:CrossIndustryInvoice xmlns:a="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
<rsm:ExchangedDocumentContext>
<ram:GuidelineSpecifiedDocumentContextParameter>
<ram:ID>urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0</ram:ID>
</ram:GuidelineSpecifiedDocumentContextParameter>
</rsm:ExchangedDocumentContext>
<rsm:ExchangedDocument>
<ram:ID>471102</ram:ID>
<ram:TypeCode>380</ram:TypeCode>
<ram:IssueDateTime>
<udt:DateTimeString format="102">20130605</udt:DateTimeString>
</ram:IssueDateTime>
</rsm:ExchangedDocument>
<rsm:SupplyChainTradeTransaction>
<ram:IncludedSupplyChainTradeLineItem>
<ram:AssociatedDocumentLineDocument>
<ram:LineID>1</ram:LineID>
</ram:AssociatedDocumentLineDocument>
<ram:SpecifiedTradeProduct>
<ram:Name>Item name</ram:Name>
<ram:Description>Detail description</ram:Description>
</ram:SpecifiedTradeProduct>
<ram:SpecifiedLineTradeAgreement>
<ram:GrossPriceProductTradePrice>
<ram:ChargeAmount>11.9000</ram:ChargeAmount>
<ram:BasisQuantity unitCode="H87">1.0000</ram:BasisQuantity>
</ram:GrossPriceProductTradePrice>
<ram:NetPriceProductTradePrice>
<ram:ChargeAmount>10.0000</ram:ChargeAmount>
<ram:BasisQuantity unitCode="H87">1.0000</ram:BasisQuantity>
</ram:NetPriceProductTradePrice>
</ram:SpecifiedLineTradeAgreement>
<ram:SpecifiedLineTradeDelivery>
<ram:BilledQuantity unitCode="H87">1.0000</ram:BilledQuantity>
</ram:SpecifiedLineTradeDelivery>
<ram:SpecifiedLineTradeSettlement>
<ram:ApplicableTradeTax>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradeSettlementLineMonetarySummation>
<ram:LineTotalAmount>10.00</ram:LineTotalAmount>
</ram:SpecifiedTradeSettlementLineMonetarySummation>
</ram:SpecifiedLineTradeSettlement>
</ram:IncludedSupplyChainTradeLineItem>
<ram:ApplicableHeaderTradeAgreement>
<ram:BuyerReference>AB-312</ram:BuyerReference>
<ram:SellerTradeParty>
<ram:ID>+4942142706710</ram:ID>
<ram:Name>Lieferant GmbH</ram:Name>
<ram:DefinedTradeContact>
<ram:PersonName>Max Mustermann</ram:PersonName>
<ram:TelephoneUniversalCommunication>
<ram:CompleteNumber>+4942142706710</ram:CompleteNumber>
</ram:TelephoneUniversalCommunication>
<ram:EmailURIUniversalCommunication>
<ram:URIID>max@mustermann.de</ram:URIID>
</ram:EmailURIUniversalCommunication>
</ram:DefinedTradeContact>
<ram:PostalTradeAddress>
<ram:PostcodeCode>80333</ram:PostcodeCode>
<ram:LineOne>Lieferantenstraße</ram:LineOne>
<ram:CityName>München</ram:CityName>
<ram:CountryID>DE</ram:CountryID>
</ram:PostalTradeAddress>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">DE123456789</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:SellerTradeParty>
<ram:BuyerTradeParty>
<ram:ID>22342424</ram:ID>
<ram:Name>Kunden Mitte AG</ram:Name>
<ram:DefinedTradeContact>
<ram:PersonName>Hans Muster</ram:PersonName>
</ram:DefinedTradeContact>
<ram:PostalTradeAddress>
<ram:PostcodeCode>69876</ram:PostcodeCode>
<ram:LineOne>Kundenstraße</ram:LineOne>
<ram:CityName>Frankfurt</ram:CityName>
<ram:CountryID>DE</ram:CountryID>
</ram:PostalTradeAddress>
<ram:SpecifiedTaxRegistration>
<ram:ID schemeID="VA">DE234567890</ram:ID>
</ram:SpecifiedTaxRegistration>
</ram:BuyerTradeParty>
<ram:BuyerOrderReferencedDocument>
<ram:IssuerAssignedID>2013-471102</ram:IssuerAssignedID>
</ram:BuyerOrderReferencedDocument>
</ram:ApplicableHeaderTradeAgreement>
<ram:ApplicableHeaderTradeDelivery>
<ram:ActualDeliverySupplyChainEvent>
<ram:OccurrenceDateTime>
<udt:DateTimeString format="102">20130603</udt:DateTimeString>
</ram:OccurrenceDateTime>
</ram:ActualDeliverySupplyChainEvent>
</ram:ApplicableHeaderTradeDelivery>
<ram:ApplicableHeaderTradeSettlement>
<ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
<ram:SpecifiedTradeSettlementPaymentMeans>
<ram:TypeCode>97</ram:TypeCode>
<ram:Information />
</ram:SpecifiedTradeSettlementPaymentMeans>
<ram:ApplicableTradeTax>
<ram:CalculatedAmount>1.90</ram:CalculatedAmount>
<ram:TypeCode>VAT</ram:TypeCode>
<ram:BasisAmount>10.00</ram:BasisAmount>
<ram:CategoryCode>S</ram:CategoryCode>
<ram:RateApplicablePercent>19.00</ram:RateApplicablePercent>
</ram:ApplicableTradeTax>
<ram:SpecifiedTradePaymentTerms>
<ram:Description>Zahlbar innerhalb 30 Tagen netto bis 04.07.2023</ram:Description>
<ram:DueDateDateTime>
<udt:DateTimeString format="102">20230704</udt:DateTimeString>
</ram:DueDateDateTime>
</ram:SpecifiedTradePaymentTerms>
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
<ram:LineTotalAmount>10.00</ram:LineTotalAmount>
<ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>
<ram:AllowanceTotalAmount>0.00</ram:AllowanceTotalAmount>
<ram:TaxBasisTotalAmount>10.00</ram:TaxBasisTotalAmount>
<ram:TaxTotalAmount currencyID="EUR">1.90</ram:TaxTotalAmount>
<ram:GrandTotalAmount>11.90</ram:GrandTotalAmount>
<ram:TotalPrepaidAmount>0.00</ram:TotalPrepaidAmount>
<ram:DuePayableAmount>11.90</ram:DuePayableAmount>
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
</ram:ApplicableHeaderTradeSettlement>
</rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>
We can use this XML directly as a data source to create the template and merge the data to generate the PDF. In TX Words, our sample application, you can load the XML as a data source to see all available node elements.
The interesting node is SupplyChainTradeTransaction, which is used as our root node to generate the document. Now we can insert two merge blocks: ApplicableHeaderTradeAgreement and IncludedSupplyChainTradeLineItem.
The first merge block is not inserted to repeat content, but to access the data of this node. Here we can add the fields for the seller party and the buyer party. The second block repeats all line items of the invoice.
During the design of the template we can directly do a preview to see the results.
Programmatically Merging Data
After the template is designed, we can merge the data programmatically using the MailMerge class. The following code snippet shows how to merge the data from the XML data source and save the document as a PDF file:
using System.Data;
using System.Text;
using TXTextControl.DocumentServer;
string xmlData = File.ReadAllText("data.xml");
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
{
tx.Create();
tx.Load("zugferd_template.tx", TXTextControl.StreamType.InternalUnicodeFormat);
MailMerge mailMerge = new MailMerge();
mailMerge.TextComponent = tx;
// dataset from XML
DataSet ds = new DataSet();
ds.ReadXml(new MemoryStream(Encoding.UTF8.GetBytes(xmlData)));
// merge data
mailMerge.Merge(ds.Tables["SupplyChainTradeTransaction"]);
// save as PDF
tx.Save("output.pdf", TXTextControl.StreamType.AdobePDF);
}
In line 20, you can see that we are using the SupplyChainTradeTransaction node as the root node for the merge process.
Embedding XML Data in PDF/A-3b
In the next step, we can embed the used XML data in the PDF/A document to generate a valid ZUGFeRD PDF/A-3b document. The following code snippet shows how to embed the XML data in the PDF document:
using System.Data;
using System.Text;
using TXTextControl.DocumentServer;
string xmlData = File.ReadAllText("data.xml");
using (TXTextControl.ServerTextControl tx = new TXTextControl.ServerTextControl())
{
tx.Create();
tx.Load("zugferd_template.tx", TXTextControl.StreamType.InternalUnicodeFormat);
MailMerge mailMerge = new MailMerge();
mailMerge.TextComponent = tx;
// dataset from XML
DataSet ds = new DataSet();
ds.ReadXml(new MemoryStream(Encoding.UTF8.GetBytes(xmlData)));
// merge data
mailMerge.Merge(ds.Tables["SupplyChainTradeTransaction"]);
// load Xml file
string metaData = File.ReadAllText("metadata.xml");
TXTextControl.SaveSettings saveSettings = new TXTextControl.SaveSettings();
// create a new embedded file
var zugferdInvoice = new TXTextControl.EmbeddedFile(
"ZUGFeRD-invoice.xml",
Encoding.UTF8.GetBytes(xmlData),
metaData);
zugferdInvoice.Description = "ZUGFeRD-invoice";
zugferdInvoice.Relationship = "Alternative";
zugferdInvoice.MIMEType = "application/xml";
zugferdInvoice.LastModificationDate = DateTime.Now;
// set the embedded files
saveSettings.EmbeddedFiles = new TXTextControl.EmbeddedFile[] { zugferdInvoice };
// save as PDF
tx.Save("output.pdf", TXTextControl.StreamType.AdobePDFA, saveSettings);
}
After the document is saved, it can be opened in any PDF viewer that supports PDF/A-3b such as Adobe Acrobat Reader.
Conclusion
TX Text Control provides a powerful template designer to create perfectly formatted invoices based on XML data sources. We learned how to generate the human readable part of the invoice based on the XML data. The MailMerge component can be used to merge the data into the template and generate a PDF document. By embedding the XML data in the PDF document, it is possible to generate valid ZUGFeRD PDF/A-3b documents.
ASP.NET
Integrate document processing into your applications to create documents such as PDFs and MS Word documents, including client-side document editing, viewing, and electronic signatures.
- Angular
- Blazor
- React
- JavaScript
- ASP.NET MVC, ASP.NET Core, and WebForms
Related Posts
Visualize and Preview XRechnung, ZUGFeRD, and Factur-X Documents in .NET C#
This article shows how to visualize and preview ZUGFeRD, XRechnung, and Factur-X documents in .NET C#. It uses TX Text Control .NET Server to render the documents from the XML data.
Creating ZUGFeRD 2.3 (XRechnung, Factur-X) Documents with .NET C#
This article shows how to create ZUGFeRD 2.3 compliant invoices using TX Text Control .NET Server. ZUGFeRD 2.3 is the latest version of the ZUGFeRD data model and complies with the European…
ASP.NETASP.NET CoreElectronic Invoicing
Generating a ZUGFeRD PDF with Existing XML Data using .NET C#
This article shows how to generate a ZUGFeRD invoice with existing XML data using .NET C#. A valid PDF/A-3b file is created with a ZUGFeRD XML attachment using TX Text Control .NET Server.
ASP.NETMailMergeServerTextControl
Creating Valid XRechnung / ZUGFeRD Invoices with ASP.NET Core C#
This article shows how to create valid XRechnung and ZUGFeRD invoices with ASP.NET Core C#. The invoice is created with the help MailMerge component and the ZUGFeRD-csharp library.
Creating Trusted Document Containers with PDF/A-3b in .NET C#
TX Text Control allows developers to do more than just generate PDFs. They can also build trusted digital archives that combine human-readable documents and machine-readable data in one secure,…