context: DocumentContext = Field(DocumentContext, required=True)
header: Header = Field(Header, required=True)
trade: TradeTransaction = Field(TradeTransaction, required=True)
+ __namespaces = {
+ "rsm": NS_RSM,
+ "qdt": NS_QDT,
+ "ram": NS_RAM,
+ "xs": "http://www.w3.org/2001/XMLSchema",
+ "xsi": "http://www.w3.org/2001/XMLSchema-instance",
+ "udt": NS_UDT,
+ }
def __init__(self):
super().__init__()
- ET.register_namespace("rsm", NS_RSM)
- ET.register_namespace("qdt", NS_QDT)
- ET.register_namespace("ram", NS_RAM)
- ET.register_namespace("xs", "http://www.w3.org/2001/XMLSchema")
- ET.register_namespace("udt", NS_UDT)
+ for ns, url in self.__namespaces.items():
+ ET.register_namespace(ns, url)
+
+ def serialize(self, schema="FACTUR-X_BASIC"):
+ # First pass
+ xml = super().serialize(schema)
+
+ # Second pass to ensure all namespaces are defined even if they are unused
+ root = ET.fromstring(xml)
+ for ns, url in self.__namespaces.items():
+ if ns.encode() not in xml:
+ root.set(f"xmlns:{ns}", url)
+ return ET.tostring(root, "utf-8")
class Meta:
namespace = NS_RSM
attach_xml(invoice_pdf17_bytes, "invalid_xml_type")
assert str(exc_info.value) == "Please supply XML data as bytes."
+
+
+@pytest.mark.parametrize("invoice_document", ["380"], indirect=True)
+def test_unused_name_spaces_included(invoice_document):
+ doc = invoice_document
+ doc.context.guideline_parameter.id = (
+ "urn:cen.eu:en16932:2017#conformant#urn:factur-x.eu:1p0:wrong"
+ )
+ xml = doc.serialize(schema="FACTUR-X_EXTENDED")
+ assert 'xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"' in xml.decode()
+ assert 'xmlns:xs="http://www.w3.org/2001/XMLSchema"' in xml.decode()
+ assert 'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' in xml.decode()
+ assert 'xs:' not in xml.decode()
+ assert 'xsi:' not in xml.decode()