Skip to content

fix: correct Factur-X XMP attribute and CII element ordering in merged profiles#112

Open
jankal wants to merge 2 commits intojslno:mainfrom
jankal:fix/zugferd-bugs
Open

fix: correct Factur-X XMP attribute and CII element ordering in merged profiles#112
jankal wants to merge 2 commits intojslno:mainfrom
jankal:fix/zugferd-bugs

Conversation

@jankal
Copy link

@jankal jankal commented Feb 10, 2026

Summary

  • Fix xmlns:about=""rdf:about="" in the Factur-X rdf:Description XMP metadata, which prevented validators (KoSIT, sevDesk) from discovering the embedded XML attachment
  • Fix CII XML element ordering when profile schemas are merged via defu, which produced invalid element sequences for profiles that extend BASIC (EN16931, EXTENDED)

Details

1. Factur-X XMP rdf:about attribute (formatter/pdf)

The Factur-X rdf:Description block used xmlns:about="" which declares an invalid XML namespace prefix instead of the correct rdf:about="" RDF resource identifier. Validators parse XMP/RDF to locate the Factur-X XML attachment filename — this malformed attribute caused them to fail, even though the XML was
correctly embedded via /Names/EmbeddedFiles and /AF.

Note: #111 fixed the other rdf:Description blocks but missed this Factur-X-specific one.

2. Schema merge key ordering (formatter/xml)

mergeSchemas uses defu({}, mergedExtensions, profile.schema) to combine base and extending profile schemas. Internally, defu clones the last argument first via Object.assign({}, defaults), giving its key order priority. When the extending profile (e.g. EN16931) only defines a subset of keys
(tradeProduct, tradeAgreement, tradeSettlement), base-only keys (identifier, note, tradeDelivery) get appended at the end instead of their correct CII position.

This adds a reorderSchema post-processing step that walks the merged schema tree and reorders keys to match the base profiles' element sequence.

Test plan

  • All existing tests pass (19/19 across both packages)
  • Generate a PDF with EN16931 profile and validate with KoSIT validator
  • Verify Factur-X XML attachment is discoverable via XMP metadata

@vercel
Copy link
Contributor

vercel bot commented Feb 10, 2026

@jankal is attempting to deploy a commit to the better-auth-extended Team on Vercel.

A member of the Team first needs to authorize it.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Feb 10, 2026

Open in StackBlitz

npm i https://pkg.pr.new/jslno/node-zugferd/@node-zugferd/api@112
npm i https://pkg.pr.new/jslno/node-zugferd@112

commit: cd29e24

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 2 files

jankal and others added 2 commits February 10, 2026 17:31
defu's internal `Object.assign({}, defaults)` clones the last source
argument first, giving its key order priority.  In `mergeSchemas`,
the extending profile's schema (e.g. EN16931) is the last argument
to `defu()`, so its incomplete key set determines the element order.
Keys that only exist in the base profiles (e.g. identifier, note,
tradeDelivery from BASIC) get appended at the end instead of appearing
in the correct CII XML element order.

Add a `reorderSchema` step after the merge that walks the schema tree
and reorders keys to match the base (extended) profiles' key order,
which defines the correct CII element sequence.  Keys only present in
the extending profile are appended at the end.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
chrizzellu added a commit to chrizzellu/node-zugferd that referenced this pull request Feb 12, 2026
When profiles like EN16931 or EXTENDED extend BASIC, defu's internal
Object.assign gives the extending profile's key order priority. This
pushes base-only keys (identifier, note, tradeDelivery) to the end,
producing invalid CII XML element sequences.

Adds a reorderSchema post-processing step that walks the merged schema
tree and reorders keys to match the base profiles' element sequence.

Based on jslno#112.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant