A conversion between CII and UBL is not a format guess, it is a re-serialization of the same semantic model: EN 16931 defines the fields, both syntaxes carry them, and for the core invoice the mapping is defined rather than inferred. That is why the round trip works. It is also why the losses, where they exist, are predictable: anything that lives outside the standardized core has no guaranteed slot on the other side. Knowing the boundary turns lossless conversion into a property you can verify on your own files.
What converts losslessly, and why
Every business term of the core model, parties and identifiers, lines with quantities and prices, the VAT breakdown, the totals chain, payment data, references, has a defined representation in both syntaxes. A converter that walks the semantic model, CII to UBL or UBL to CII, reproduces these one for one; validation rules apply identically afterwards because the rules are written against the model, not the syntax.
The practical consequence: if your invoice consists of core fields, the converted file is the same invoice, and the same rule set will pass or fail both.
Where the boundary runs
| Content | Fate in conversion |
|---|---|
| Core EN 16931 fields (BT/BG) | Defined mapping, lossless |
| Embedded attachments (BG-24) | Part of the core: name, type and content carry over |
| ZUGFeRD EXTENDED-profile extras beyond the core | No guaranteed target slot in a core UBL invoice |
| Syntax-specific extension containers | Not portable by definition |
| Ordering, whitespace, comments in the XML | Not semantics; expect them to change |
Two edge notes for practitioners. First, a hybrid ZUGFeRD is a PDF wrapping CII: converting to UBL yields a pure XML file, the PDF face does not travel, by design. Second, if your generator emits vendor extensions, decide deliberately whether the receiving side needs them; the core model is the interoperable contract, extensions are a bilateral agreement.
The test protocol: four checks that prove it
- Round-trip your golden files. Convert CII to UBL and back, then compare the semantic fields, not the bytes: parties, line values, VAT categories and amounts, totals, references. Byte-level diffs are noise; field-level equality is the claim worth having.
- Validate both sides with the same rule set. The validator runs the official EN 16931 artefacts over either syntax; a conversion that turns a passing file into a failing one has left the core somewhere, and the failing rule names where.
- Pin the cases your invoices actually use. Reverse charge, discounts, an attachment, a credit note: one golden file per real-world shape you emit. The rule layers those files must satisfy are the same four described in validating output from your own code.
- Watch the totals chain. Amount formatting differs in style, never in value; any drift of a cent after conversion means a rounding site in your own pipeline, not the syntax.
When to convert at all
The common triggers are receiver-driven: an XRechnung recipient whose system wants the other syntax, a Peppol route (UBL territory), or a toolchain that speaks only one dialect. Converting is cheaper than re-keying and safer than maintaining two generators; generate in one syntax, convert at the boundary, validate after. Which side to standardize on follows your ecosystem: ZUGFeRD work is CII-native, network delivery leans UBL.
Legal position as at September 2026, last reviewed on 25 September 2026. Based on EN 16931 with its CII and UBL syntax bindings and the XRechnung specification, which admits both syntaxes.
Frequently asked questions
Is CII-to-UBL conversion lossless?
For the standardized core of EN 16931, yes: both syntaxes carry the same semantic fields with defined mappings. Losses concern content outside the core, such as profile extras and vendor extensions.
Do embedded attachments survive the conversion?
Yes. Supporting documents are core-model content, and their name, type and payload carry over between the syntaxes.
Does the converted file pass the same validation?
That is the correct expectation and the best test: the rules are written against the semantic model, so a valid core invoice stays valid across syntaxes. A file that fails after conversion has revealed non-core content or a defect worth knowing about.
What happens to the PDF part of a ZUGFeRD when converting to UBL?
It stays behind. The conversion operates on the invoice data; the result is a pure XML file. If the receiver needs a human-readable page again, that is a rendering step, not a conversion property.
Should we generate both syntaxes natively instead of converting?
Usually not: two generators mean two sets of bugs. One well-tested generator plus a boundary conversion with post-validation gives the same coverage with half the surface.