This page documents the multi-layer XML validation system used in gobl.cii to ensure generated CII documents comply with European e-invoicing standards. The validation infrastructure validates both structural correctness (XSD schemas) and business rules (Schematron). For information about the test framework that integrates these validation tools, see 6.2. For details on the conversion functions that produce the XML being validated, see 3.1.
Sources: README.md:121-122, examples_test.go:38-46
The validation system implements three progressive validation layers, each providing increasingly strict compliance checks:
Sources: examples_test.go:256-281, examples_test.go:328-414
The first validation layer uses XSD (XML Schema Definition) to validate structural correctness against the EN16931 base standard. This validation ensures that all required XML elements are present, properly nested, and contain valid data types.
The validateAgainstSchema function uses the libxml2 library's XSD parser:
| Component | Purpose | Location |
|---|---|---|
xsd.ParseFromFile() | Load XSD schema | examples_test.go:329 |
libxml2.Parse() | Parse XML document | examples_test.go:333 |
schema.Validate() | Validate against schema | examples_test.go:338 |
When XSD validation fails, the function collects all errors from xsd.SchemaValidationError and formats them as a single error message:
validation errors: error1,
error2,
error3
Sources: examples_test.go:328-350
After passing base EN16931 validation, documents may be validated against additional format-specific schemas if they exist. This layer is optional and only executes when the format directory contains a schema.xsd file.
The validation logic checks for format-specific schemas using os.Stat:
| Check | Location | Purpose |
|---|---|---|
| Base schema | tools/schema/en16931/schema.xsd | Always validated (except for en16931 format) |
| Format schema | tools/schema/{format}/schema.xsd | Validated if file exists |
The validateXML function implements format-specific validation:
Sources: examples_test.go:257-270
The final validation layer uses Schematron to enforce business rules that cannot be expressed in XSD schemas. Schematron validation requires an external XSLT 3.0 processor.
| Tool | Purpose | Installation |
|---|---|---|
xslt3 | XSLT 3.0 processor | npm install -g xslt3 |
| Compiled SEF | Schematron stylesheet | Pre-compiled in tools/schematron/{format}/compiled/stylesheet.sef |
The validateAgainstSchematron function executes Schematron validation through the xslt3 command:
The xslt3 command is executed with these parameters:
-s: + temporary XML file path-xsl: + stylesheet.sef pathSources: examples_test.go:353-414, README.md:121-122
Schematron validation produces SVRL (Schematron Validation Report Language) XML output, which is parsed to identify failed assertions.
The system defines two structures for parsing SVRL output:
| Struct | XML Mapping | Purpose |
|---|---|---|
FailedAssert | failed-assert element | Individual failed assertion |
SVRL | schematron-output root | Container for all assertions |
The validation distinguishes between fatal and non-fatal assertions:
flag="fatal"): Cause validation to failError messages for fatal assertions follow this format:
{ID}: {Text} (location: {Location})
Sources: examples_test.go:309-321, examples_test.go:401-410
Validation is integrated into the test suite through command-line flags and can be enabled selectively.
| Flag | Type | Default | Purpose |
|---|---|---|---|
--validate | bool | false | Enable XSD and Schematron validation |
--update | bool | false | Update golden test files |
To execute tests with validation enabled:
This command:
Sources: examples_test.go:49-52, examples_test.go:74-110, README.md:116-123
The validation tools rely on a structured directory layout for schema and Schematron files.
tools/
├── schema/
│ ├── en16931/
│ │ └── schema.xsd # Base EN16931 XSD schema
│ ├── xrechnung/
│ │ └── schema.xsd # XRechnung-specific schema
│ ├── facturx/
│ │ └── schema.xsd # Factur-X-specific schema
│ └── peppol/
│ └── schema.xsd # Peppol-specific schema
└── schematron/
├── en16931/
│ └── compiled/
│ └── stylesheet.sef # Compiled Schematron rules
├── xrechnung/
│ └── compiled/
│ └── stylesheet.sef
└── peppol/
└── compiled/
└── stylesheet.sef
| Constant | Value | Usage |
|---|---|---|
schemaPath | "tools/schema" | Base directory for XSD schemas |
schematronPath | "tools/schematron" | Base directory for Schematron files |
compiledPath | "compiled" | Subdirectory for compiled SEF files |
schemaFile | "schema.xsd" | XSD schema filename |
styleFile | "stylesheet.sef" | Compiled Schematron filename |
defaultFormat | "en16931" | Base format for validation |
Sources: examples_test.go:39-46, examples_test.go:265-277
The validation system requires specific external dependencies to function correctly.
| Dependency | Purpose | Installation |
|---|---|---|
libxml2 | XSD schema validation | Go module: github.com/lestrrat-go/libxml2 |
xslt3 | XSLT 3.0 processor for Schematron | npm: npm install -g xslt3 |
The XSD validation uses these Go packages:
github.com/lestrrat-go/libxml2 - XML parsing and manipulationgithub.com/lestrrat-go/libxml2/xsd - XSD schema validationInstall Go dependencies:
Install xslt3 globally:
Verify installation:
The GitHub Actions test workflow automatically installs xslt3 before running tests. See 6.5 for details on the CI/CD pipeline.
Sources: examples_test.go:21-22, README.md:121-122
When validation fails, the system provides detailed error messages identifying the specific rule violations and their locations in the XML document.
XSD validation errors are collected and formatted as comma-separated messages:
validation errors: error1,
error2,
error3
Schematron errors follow this format for each failed fatal assertion:
{AssertionID}: {ErrorText} (location: {XPathLocation})
Multiple failures are joined with newlines:
schematron validation failed:
BR-01: Missing buyer reference (location: /Invoice)
BR-02: Invalid tax category (location: /Invoice/Line[1]/Tax)
Sources: examples_test.go:340-347, examples_test.go:405-410
Refresh this wiki