Skip to content

Pretty-printing exported XML introduces ns0: namespace prefix, rejected by German bank #78

Description

@ralfblask

When the output of sepa.export() is parsed and re-serialized using Python's xml.etree.ElementTree for pretty-printing (indentation), the resulting XML contains ns0: prefixes on all elements. German banks (tested with Volksbank using DK-SEPA validator v1.13.1) reject this with 577 warnings:

Line 2, Col 2: Das Setzen von individuellen Präfixen ist unzulässig (ns0).
Line 3, Col 4: Das Setzen von individuellen Präfixen ist unzulässig (ns0).
...

Steps to reproduce

import xml.etree.ElementTree as ET
from sepaxml import SepaTransfer
import datetime

config = {
    "name": "Test GmbH",
    "IBAN": "DE12345678901234567890",
    "BIC": "TESTDE99XXX",
    "batch": True,
    "currency": "EUR",
}
sepa = SepaTransfer(config, clean=True)
sepa.add_payment({
    "name": "Recipient",
    "IBAN": "DE98765432109876543210",
    "BIC": "EMPFDE99XXX",
    "amount": 1500,
    "execution_date": datetime.date(2026, 3, 17),
    "description": "Test",
})
xml_bytes = sepa.export(validate=True)

# Pretty-print via ElementTree
ET.register_namespace("", "urn:iso:std:iso:20022:tech:xsd:pain.001.001.03")
root = ET.fromstring(xml_bytes)
print(ET.tostring(root, encoding="unicode")[:200])
# Output contains: <ns0:Document xmlns:ns0="urn:iso:std:iso:20022:tech:xsd:pain.001.001.03">

Root cause

ET.register_namespace() must be called before ET.fromstring(). Once the document is parsed, ElementTree has already assigned internal namespace prefixes and register_namespace() has no effect on already-parsed nodes.

Workaround

Regex-based cleanup after serialization:

import re

serialised = ET.tostring(root, encoding="unicode")
serialised = re.sub(r'<ns\d+:(\w)', r'<\1', serialised)
serialised = re.sub(r'</ns\d+:', r'</', serialised)
serialised = re.sub(r'\bxmlns:ns\d+="', 'xmlns="', serialised)

Suggested fix

The library could register all its namespaces as default namespaces at module import time, so that ET.fromstring() already uses the correct prefix mapping. Alternatively, the library could expose a export(pretty=True) option that returns properly indented XML without namespace prefix issues.

Environment

  • python-sepaxml version: latest (pip)
  • Python: 3.12
  • Tested schema: pain.001.001.03
  • Validator: DK-SEPA v1.13.1 (used by German Volksbank/Raiffeisenbank)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions