en16931-cii2ubl

June 3, 2026 · View on GitHub

Sonatype Central javadoc

If this project saved you some time or made your day a little easier, a star would mean a lot — it helps others find it too.

Unidirectional converter for EN16931 invoices from CII D16B to UBL 2.1, 2.2, 2.3 or 2.4.

This is a Java 11+ library that converts a Cross Industry Invoice (CII) into a Universal Business Language (UBL) document following the rules of the European Norm (EN) 16931 that defines a common semantic data model for electronic invoices in Europe.

Special care was given to XRechnung invoices - all the CII examples of them translate to UBL that is valid according to the EN 16931 validation rules.

See https://peppol.helger.com/public/locale-en_US/menuitem-tools-rest-api#cii2ubl for a service implementation using this library.

This library is licensed under the Apache License Version 2.0.

The binary releases are available on Maven Central at https://repo1.maven.org/maven2/com/helger/en16931-cii2ubl/ and below.

Usage

This is a pure Java library and not a self-contained conversion tool. You can convert CII D16B invoices following the EN 16931 rules to different UBL versions. The entrance classes are:

  • Create UBL 2.1: com.helger.en16931.cii2ubl.CIIToUBL21Converter
  • Create UBL 2.2: com.helger.en16931.cii2ubl.CIIToUBL22Converter
  • Create UBL 2.3: com.helger.en16931.cii2ubl.CIIToUBL23Converter (since v1.3.0)
  • Create UBL 2.4: com.helger.en16931.cii2ubl.CIIToUBL24Converter (since v2.1.0)

The main conversion method is called convertCIItoUBL and takes either a File as input or a pre-parsed un.unece.uncefact.data.standard.crossindustryinvoice._100.CrossIndustryInvoiceType object (that reading is done with class com.helger.cii.d16b.CIID16BCrossIndustryInvoiceTypeMarshaller from ph-cii). Additionally an ErrorList object must be provided as a container for all the errors that occur.

The conversion is deemed successful, if a non-null object is returned and if the error list contains no error (errorList.containsNoError ()).

Maven usage

Replace x.y.z with the effective version you want to use:

<dependency>
  <groupId>com.helger</groupId>
  <artifactId>en16931-cii2ubl</artifactId>
  <version>x.y.z</version>
</dependency>

Commandline usage

Call it via java -jar en16931-cii2ubl-cli-full.jar followed by the options and parameters.

[INFO] CII to UBL Converter v3.1.7 (build 2026-04-22T11:56:27Z)
Missing required parameter: 'source files'
Usage: CIItoUBLConverter [-hV] [--disable-wildcard-expansion]
                         [--swap-price-sign] [--swap-quantity-sign] [--verbose]
                         [--mode mode] [--output-suffix filename part] [-t
                         directory] [--ubl version] [--ubl-cardaccountnetworkid
                         ID] [--ubl-customizationid ID]
                         [--ubl-defaultorderrefid ID] [--ubl-profileid ID]
                         [--ubl-vatscheme vat scheme] source files...
CII to UBL Converter for EN 16931 invoices
      source files...        One or more CII file(s)
      --disable-wildcard-expansion
                             Disable wildcard expansion of filenames
  -h, --help                 Show this help message and exit.
      --mode mode            Allowed values: AUTOMATIC, INVOICE, CREDIT_NOTE
                               (default: 'AUTOMATIC')
      --output-suffix filename part
                             The suffix added to the output filename (default:
                               '-ubl')
      --swap-price-sign      Swap price sign if needed for credit notes
                               (default: 'true')
      --swap-quantity-sign   Swap quantity sign if needed for credit notes
                               (default: 'true')
  -t, --target directory     The target directory for result output (default:
                               '.')
      --ubl version          Version of the target UBL Format: '2.1', '2.2',
                               '2.3' or '2.4' (default: '2.1')
      --ubl-cardaccountnetworkid ID
                             The UBL CardAccount network ID to be used
                               (default: 'mapped-from-cii')
      --ubl-customizationid ID
                             The UBL customization ID to be used
      --ubl-defaultorderrefid ID
                             The UBL default order reference ID to be used
                               (default: '')
      --ubl-profileid ID     The UBL profile ID to be used
      --ubl-vatscheme vat scheme
                             The UBL VAT scheme to be used (default: 'VAT')
  -V, --version              Print version information and exit.
      --verbose              Enable debug logging (default: 'false')

Open issues

  • The migration of CII NetPriceProductTradePrice/BasisQuantity to UBL Price/BaseQuantity is not consistent for me
    • See example files 2, 8 and 9
    • The UBL example files use a BaseQuanity of 1 in all cases

News and noteworthy

v3.1.7 - 2026-04-22

  • Fixed BT-150 (Item price base quantity unit of measure): now falls back to the net price unitCode when no gross price is present, instead of losing it
  • Fixed BT-61/BT-61-1 (Payee legal registration identifier): _convertPartyLegalEntity is now called for the Payee party, mapping SpecifiedLegalOrganization/ID to PartyLegalEntity/CompanyID
  • Fixed UBL-CR-275 compliance: RegistrationName fallback is no longer set on the Payee PartyLegalEntity, as the EN 16931 Schematron forbids it
  • Fixed BT-11 (Project reference) for UBL 2.1 CreditNote: now mapped to AdditionalDocumentReference since UBL 2.1 CreditNote lacks ProjectReference

v3.1.6 - 2026-04-22

  • Added CLI options --swap-quantity-sign and --swap-price-sign to expose the full converter API
  • Improved BT-90 mapping so that it is correctly set to the PayeeParty if present
  • Improved BT-11 mapping for UBL CreditNote

v3.1.5 - 2026-04-13

  • Fixed the "main class" attribute for the manifest

v3.1.4 - 2026-04-13

  • No more OSGI bundle packaging
  • Avoid creating an empty UBL Delivery Party Name element. See issue #47
  • Fixed the Delivery element to also be created when only a delivery date is present but no ShipToParty
  • Unified the CreditNote line-item price handling (BT-147, BT-148, BT-149, BT-150) to match the Invoice logic

v3.1.3 - 2026-02-02

  • Fixed the BT-9 mapping of CreditNotes. See issue #45 - thx @AWickSimova
  • The list of allowed Invoice Type Codes was extended: Added 71, 81, 102, 218, 219, 331, 382, 471, 472, 473, 500, 501, 502, 503, 553, 817 and 870

v3.1.2 - 2026-01-05

  • Fixed a bug in the BG-17 conversion towards UBL 2.4. See issue #44 - thx @matmen

v3.1.1 - 2025-12-29

  • Fixed invalid mapping to BillingReference/CreditNoteDocumentReference. See issue #43 - thx @ycheuv-lgtm

v3.1.0 - 2025-11-16

  • Updated to ph-commons 12.1.0
  • Using JSpecify annotations

v3.0.1 - 2025-09-19

  • Added the mapping of BT-86 for DirectDebit case

v3.0.0 - 2025-08-27

  • Requires Java 17 as the minimum version
  • Updated to ph-commons 12.0.0

v2.3.1 - 2025-06-26

  • Avoid NullPointerException if a CII line item has no quantity

v2.3.0 - 2025-03-25

  • Removed the default values for BT-24 (CustomizationID) and BT-23 (ProfileID)
  • Emitting UBL 2.4 documents correctly
  • Taking the values of BT-23 and BT-24 from the source CII fields. See issue #37 - thx @shenazz
  • Handling BG-17 only if PayeePartyCreditorFinancialAccount is present. See issue #38 - thx @msccip

v2.2.6 - 2024-12-23

  • Supporting all values of the UNTDID 4461 code list. See issue #34 - thx @shenazz

v2.2.5 - 2024-10-22

  • Fixed the automatic module name. See issue #32 - thx @toherrmann

v2.2.4 - 2024-06-17

  • Fixed a regression from v2.2.3. See issue #31 - thx @msccip

v2.2.3 - 2024-06-12

  • Added additional mapping of BT-41. See issue #28 - thx @bdewein
  • Fixed the mapping of the Due Date Type Code for BT-8. See issue #29 - thx @bdewein
  • Fixed the mapping of BT-27 and BT-28. See issue #26 - thx @bdewein
  • Fixed the item price mapping around BT-146, BT-147, BT-148, BT-149 and BT-150. See issue #27 - thx @bdewein

v2.2.2 - 2024-04-12

  • Added support for providing the default UBL order reference ID, in case the empty String is not good enough. See issue #23 - thx @lkumai

v2.2.1 - 2024-03-29

  • Updated to ph-commons 11.1.5
  • Ensured Java 21 compatibility

v2.2.0 - 2024-03-08

  • Updated to ph-ubl 9.0.0
  • Tested output against EN 16931 rules v1.3.10 and v1.3.11 - no changes necessary
  • Updated to create UBL 2.4-CS01
  • Added support for BT-8 mapping. See issue #22

v2.1.0 - 2023-04-28

  • Updated to ph-ubl 8.0.1
  • Added support for converting to UBL 2.4

v2.0.3 - 2023-04-20

  • Improved mapping of references to external documents in additional document references. See issue #20 - thanks @msccip

v2.0.2 - 2023-03-30

  • Changed the default mode of the CLI version from INVOICE to AUTOMATIC. See issue #19 - thanks @msccip

v2.0.1 - 2023-03-15

  • Added manual wildcard expansion of filenames
  • Added new CLI option --disable-wildcard-expansion to disable the wildcard expansion and stick to the old resolution logic

v2.0.0 - 2023-02-20

  • Using Java 11 as the baseline
  • Updated to ph-commons 11
  • Updated to JAXB 4.0
  • Added the new CLI parameter --verbose for a few more details
  • Improved logging
  • Successfully tested the CLI parameter with wildcard parameters (because the Java Windows Runtime performs automatic wildcard expansion)

v1.4.10 - 2022-12-16

  • Fixed the conversion of the TypeCode element in AdditionalReferencedDocument. See issue #18 - thanks @L3Mars

v1.4.9 - 2022-11-15

  • Fixed an unnecessary division by 100 for creating MultiplierFactorNumeric. See issue #17 - thanks @L3Mars
  • Tested output against EN 16931 rules v1.3.9 - no changes necessary

v1.4.8 - 2022-09-28

  • Added new option --output-suffix to customize the output file suffix, that is currently hard coded to -ubl
  • Fixed a problem with the mapping of BT-147, BT-148, BT-149 and BT-150. See issue #15. Thanks to @cambid for pointing that out

v1.4.7 - 2022-02-15

  • Further improved null/empty handling to avoid creation of empty elements

v1.4.6 - 2022-02-12

  • Allowing the additional Payment Means Type Codes 1, 42 and 68. See issue #13
  • For decimal values, trailing zeroes are no longer emitted. See issue #13
  • Improved not creating empty UBL elements. See issue #13
  • The SubjectCode of IncludedNote elements is copied over. See issue #13
  • Improved the Party ID handling and allowing for multiple seller IDs. See issue #13

v1.4.5 - 2021-12-20

  • Tested output against EN 16931 rules v1.3.7 - no changes necessary
  • Fixed creating invalid UBL if SellerAssignedID is empty. See issue #12 - thanks @DerHamm

v1.4.4 - 2021-10-14

  • Improved sign swapping of Quantity and Price to avoid negative prices (BT-146)

v1.4.3 - 2021-10-07

  • Tested output against EN 16931 rules v1.3.6 - no changes necessary
  • Changed determination if Invoice or CreditNote primarily to rsm:ExchangedDocument/ram:TypeCode instead of the payable amount

v1.4.2 - 2021-06-10

  • Changed the default customization ID to urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0
  • If the UBL LineExtensionAmount is negative, but the line Quantity is positive, the Quantity will be changed to negative. Customizable via setSwapQuantitySignIfNeeded(boolean)

v1.4.1 - 2021-05-02

  • Updated to ph-commons 10.1
  • Tested output against EN 16931 rules v1.3.5 - no changes necessary

v1.4.0 - 2021-03-22

  • Updated to ph-commons 10

v1.3.0 - 2021-01-05

  • Added support for different CII time formats (2, 3, 4, 101, 102, 103 and 105) where 102 is the default
  • The error handling for the commandline client was improved (checking errors before writing UBL) (see issue #9)
  • Added the possibility to create UBL 2.3
  • Made the API more open to directly convert to Invoice or CreditNote
  • Improved the handling of payment means to be more EN compliant. See issue #7.
  • Added a possibility to retrieve the internal converter version number

v1.2.5 - 2020-11-30

  • Added Jakarta Activation dependency to the standalone CLI version. See issue #6.

v1.2.4 - 2020-10-20

v1.2.3 - 2020-09-17

  • Updated to Jakarta JAXB 2.3.3

v1.2.2 - 2020-08-30

  • Updated to ph-commons 9.4.7
  • Updated to ph-cii 2.3.0
  • Updated to ph-ubl 6.4.0

v1.2.1 - 2020-05-26

  • Updated to new Maven groupIds

v1.2.0 - 2020-03-09

  • Verified against EN 16931 validation artefacts 1.3.0 - no changes in the output
  • Added commandline interface (CLI). See PR #3. Thanks to @rkottmann
  • Fixed creating invalid UBL if SellerOrderReferencedDocument is present but BuyerOrderReferencedDocument is not set (see issue #5)
  • Made default VAT scheme, UBL CustomizationID, UBL ProfileID and the PaymentMeans/CardAccount/NetworkID customizable. See issue #1 and issue #2.
  • Fixed embedded attachment mapping. See issue #4.

v1.1.5 - 2019-09-13

  • Added possibility to enforce invoice creation
  • Verified against EN 16931 validation artefacts 1.3.0

v1.1.4 - 2019-07-15

  • Updated to EN 16931 validation artefacts 1.2.3

v1.1.3 - 2019-05-15

  • Updated to EN 16931 validation artefacts 1.2.1

v1.1.2 - 2019-04-26

  • Updated to EN 16931 validation artefacts 1.2.0

v1.1.1 - 2019-02-27

  • Improved delivery date handling
  • Improved price base quantity handling

v1.1.0 - 2019-02-26

  • Added support to create UBL 2.1 Invoice and CreditNote

v1.0.0 - 2019-02-26

  • Initial release creating UBL 2.2 Invoice and CreditNote

My personal Coding Styleguide | It is appreciated if you star the GitHub project if you like it.