xinvoice

package module
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 15, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

README

GOBL ➡️ German XRechnung and ZUGFeRD

German electronic invoicing formats for GOBL: XRechnung 3.0 in UBL and CII syntax, and the EN 16931 profile of ZUGFeRD.

Copyright Invopop S.L. 2026. Released publicly under the Apache License Version 2.0. For commercial licenses, please contact the dev team at invopop. To accept contributions to this library, we require transferring copyrights to Invopop S.L.

Lint Test Go Go Report Card codecov GoDoc Latest Tag Ask DeepWiki

The XML mapping is done by gobl.ubl and gobl.cii, called with their default EN 16931 behavior. This module owns the German formats, writes the document identity headers (customization, guideline, and business process IDs) onto the converted documents, and detects the syntax when parsing, so the base libraries stay free of anything German. The German addon on the GOBL invoice shapes the document content.

Formats

Key Format File name
xrechnung-ubl-v3 XRechnung 3.0, UBL syntax xrechnung-ubl.xml
xrechnung-cii-v3 XRechnung 3.0, CII syntax xrechnung-cii.xml
zugferd-v2 ZUGFeRD EN 16931 profile, CII syntax factur-x.xml

ZUGFeRD and France's Factur-X are the same specification published under two national names. The ZUGFeRD file name is set by that specification: readers locate the XML inside the PDF/A-3 by the exact name factur-x.xml. Embedding the XML into the PDF is not part of this module; the gov-de app does that with the factur-x CLI.

Usage

Convert GOBL to a German format
package main

import (
	"encoding/json"
	"os"

	"github.com/invopop/gobl"
	xinvoice "github.com/invopop/gobl.de.xinvoice"
	"github.com/invopop/gobl/bill"
)

func main() {
	// The fixtures store the bare invoice document; wrap it in an
	// envelope. An existing envelope JSON unmarshals directly instead.
	data, err := os.ReadFile("./test/data/convert/invoice.json")
	if err != nil {
		panic(err)
	}

	inv := new(bill.Invoice)
	if err := json.Unmarshal(data, inv); err != nil {
		panic(err)
	}
	env := gobl.NewEnvelope()
	if err := env.Insert(inv); err != nil {
		panic(err)
	}

	doc, err := xinvoice.Convert(env, xinvoice.FormatXRechnungUBL)
	if err != nil {
		// The error carries the BR-DE rule violations when the invoice
		// does not satisfy the format.
		panic(err)
	}

	// doc.Data is the XML; doc.VESID names the validation rule set;
	// doc.Format.FileName is the conventional file name.
	if err := os.WriteFile(doc.Format.FileName, doc.Data, 0644); err != nil {
		panic(err)
	}
}

The conversion adds the format's GOBL addon (de-xrechnung-v3 or de-zugferd-v2) to invoices that do not declare it, recalculating and revalidating the envelope so the German rules run before any mapping.

To embed a file inside the generated XML, such as the PDF rendition of the invoice, pass xinvoice.WithAttachment.

Parse a German XML document
package main

import (
	"encoding/json"
	"os"

	xinvoice "github.com/invopop/gobl.de.xinvoice"
)

func main() {
	data, err := os.ReadFile("./test/data/parse/invoice-zugferd-v2.xml")
	if err != nil {
		panic(err)
	}

	parsed, err := xinvoice.Parse(data)
	if err != nil {
		panic(err)
	}

	// parsed.Envelope is the GOBL envelope; parsed.Syntax says UBL or
	// CII; parsed.Attachments carries files embedded in the XML.
	out, err := json.MarshalIndent(parsed.Envelope, "", "  ")
	if err != nil {
		panic(err)
	}
	os.Stdout.Write(out)
}

The syntax is detected from the document's root namespace. Both XRechnung syntaxes and the XML inside ZUGFeRD PDFs are supported, including UBL credit notes.

Testing

The library uses testify. Run the tests with:

go test ./...

The examples/ directory holds complete German invoices in GOBL form, with their calculated and validated envelopes under examples/out. Those, and the golden files under test/data/convert/out and test/data/parse/out, are regenerated with:

go test . -update

The -update flag belongs to the root package's suites, so the command names that package rather than ./....

Considerations

  • Mapping limitations are those of the base libraries; see gobl.ubl and gobl.cii directly.
  • The addon definitions still live in GOBL core (gobl/addons/de). Moving them into this module's addon/ packages with the external addon registration in GOBL's addons/external.go is a planned follow-up.
  • gobl.ubl and gobl.cii still carry their own German context values, but this module no longer uses them. They are removed together with the deprecation of the German document types in the ubl and cii apps.
  • Schematron validation is not part of the conversion. The opt-in TestSchematron (run with -validate and a phorm service; CI runs it with a service container) checks every converted fixture against the KoSIT and FeRD rule sets named by Document.VESID.

References

XRechnung
ZUGFeRD

Documentation

Overview

Package xinvoice converts GOBL envelopes into the German electronic invoicing formats and back: XRechnung 3.0 in UBL and CII syntax, and ZUGFeRD's EN 16931 profile.

Index

Constants

View Source
const (
	// CustomizationIDXRechnung identifies XRechnung 3.0 documents in
	// both syntaxes (BT-24).
	CustomizationIDXRechnung = "urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0"
	// GuidelineIDEN16931 identifies plain EN 16931 CII documents, the
	// guideline ZUGFeRD's EN 16931 profile uses.
	GuidelineIDEN16931 = "urn:cen.eu:en16931:2017"
	// ProfileIDPeppolBilling is the Peppol billing process identifier.
	ProfileIDPeppolBilling = "urn:fdc:peppol.eu:2017:poacc:billing:01:1.0"
)

German document identifiers, written into the identity headers of the converted documents.

View Source
const (
	// FormatXRechnungUBL is XRechnung 3.0 in UBL syntax.
	FormatXRechnungUBL cbc.Key = "xrechnung-ubl-v3"
	// FormatXRechnungCII is XRechnung 3.0 in CII syntax.
	FormatXRechnungCII cbc.Key = "xrechnung-cii-v3"
	// FormatZUGFeRD is the XML side of ZUGFeRD's EN 16931 profile.
	// Readers locate the XML inside the PDF/A-3 by the exact file name
	// factur-x.xml.
	FormatZUGFeRD cbc.Key = "zugferd-v2"
)

Format keys for the supported German document formats.

Variables

View Source
var ErrUnknownDocument = errors.New("not a recognized UBL or CII invoice")

ErrUnknownDocument is returned when the data is neither a UBL nor a CII invoice.

View Source
var ErrUnsupportedFormat = errors.New("unsupported format")

ErrUnsupportedFormat is returned for an unknown format key.

Functions

This section is empty.

Types

type BinaryAttachment

type BinaryAttachment struct {
	// ID is the identifier for this attachment reference.
	ID string
	// Description provides a human-readable description.
	Description string
	// Data contains the raw binary data.
	Data []byte
	// MimeCode specifies the MIME type (e.g. "application/pdf").
	MimeCode string
	// Filename is the name of the file.
	Filename string
}

BinaryAttachment represents a file embedded inside the XML document, unifying the attachment shape of the two conversion libraries.

type Document

type Document struct {
	// Data is the XML document.
	Data []byte
	// Format is the format the document was generated in.
	Format *Format
	// Namespace and Element identify the XML root.
	Namespace string
	Element   string
	// CustomizationID and ProfileID identify the document flavor and
	// business process.
	CustomizationID string
	ProfileID       string
	// Version is the syntax version (UBL "2.1", CII "D16B").
	Version string
	// VESID is the validation rule set the document must satisfy.
	VESID string
}

Document carries the serialized XML and its transmission metadata.

func Convert

func Convert(env *gobl.Envelope, format cbc.Key, opts ...Option) (*Document, error)

Convert converts a GOBL envelope into the given German format. The invoice gains the format's addon when missing, so the German rules run before any mapping.

type Format

type Format struct {
	Key      cbc.Key
	Name     string
	FileName string
	// contains filtered or unexported fields
}

Format describes one supported German document format.

func FormatFor

func FormatFor(key cbc.Key) *Format

FormatFor returns a copy of the format with the given key, or nil.

func Formats

func Formats() []*Format

Formats returns copies of the supported German document formats.

func (*Format) Addons

func (f *Format) Addons() []cbc.Key

Addons returns a copy of the GOBL addon keys the format requires.

type Option

type Option func(*options)

Option configures a conversion.

func WithAttachment

func WithAttachment(a BinaryAttachment) Option

WithAttachment embeds a file inside the generated XML.

type ParseOption

type ParseOption func(*parseOptions)

ParseOption configures parsing.

func WithRouting

func WithRouting(from, to cbc.URI) ParseOption

WithRouting records the transport direction on the parsed envelope's header. Both values must be set for the option to take effect.

type Parsed

type Parsed struct {
	// Envelope contains the GOBL invoice.
	Envelope *gobl.Envelope
	// Attachments are the binary attachments embedded in the XML.
	Attachments []BinaryAttachment
	// Syntax the document was written in.
	Syntax Syntax
}

Parsed carries the outcome of parsing a German XML document.

func Parse

func Parse(data []byte, opts ...ParseOption) (*Parsed, error)

Parse reads a German XML invoice in either syntax and converts it to a GOBL envelope. The syntax is decided by the document's root namespace.

type Syntax

type Syntax string

Syntax identifies which of the two German XML syntaxes a parsed document uses.

const (
	SyntaxUBL Syntax = "ubl"
	SyntaxCII Syntax = "cii"
)

The two syntaxes German invoices arrive in.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL