pain001.xml package#

Submodules#

pain001.xml.create_root_element module#

Module for creating XML payment initiation message documents compliant with the ISO 20022 standard. The generated XML documents include essential namespaces and schema locations.

Note: This module does not include additional security features for XML parsing. It is advisable to consider measures to prevent XML vulnerabilities when using it.

pain001.xml.create_root_element.create_root_element(message_type: str) Element[source]#

Creates the root Element for a payment initiation XML document based on the specified message type. The function sets the required namespaces and schema locations.

Parameters:

message_type – The message type, for example “pain.001.001.09”. Used to construct the namespace and schema location attributes.

Returns:

The root Element node for the XML document,

configured with the necessary namespaces and schema location attributes.

Return type:

et.Element

Examples

>>> create_root_element("pain.001.001.09")
<Element 'Document' at 0x7f8c0a309db0>

pain001.xml.create_xml_element module#

Helper for creating XML child elements.

pain001.xml.create_xml_element.create_xml_element(parent: Element, tag: str, text: str | None = None, attributes: dict[str, str] | None = None) Element[source]#

Create and append an XML element with the specified tag, text, and attributes to a given parent element in the XML tree. The new element becomes a child of the parent element.

Parameters:
  • parent (xml.etree.ElementTree.Element) – The parent XML element to which the new element will be appended.

  • tag (str) – The name of the XML tag for the new element.

  • text (str, optional) – The text content to be inserted into the new XML element. Defaults to None.

  • attributes (dict of {str: str}, optional) – A dictionary containing the attribute names and their corresponding values to be set in the new XML element. Defaults to None.

Returns:

The newly created and appended XML element.

Return type:

xml.etree.ElementTree.Element

pain001.xml.generate_updated_xml_file_path module#

Derive the legacy template-relative output path for generated XML.

pain001.xml.generate_updated_xml_file_path.generate_updated_xml_file_path(xml_file_path: str, payment_initiation_message_type: str) str[source]#

Generates the file path for an updated XML file.

Given the original XML file path and payment message type, this function constructs the file path for an updated version of the XML file with the provided message type in the filename.

Parameters:
  • xml_file_path – The path to the original XML file.

  • payment_initiation_message_type – The payment message type (e.g. ‘pain.001.001.04’).

Returns:

The file path to the updated XML file.

Return type:

str

pain001.xml.generate_xml module#

Generate and XSD-validate ISO 20022 XML payment messages.

pain001.xml.generate_xml.canonicalize_payment_record(row: dict[str, Any]) dict[str, Any][source]#

Map a record’s alias keys to canonical field names, preserving values.

The key-mapping half of normalize_payment_records(): amount becomes payment_amount, currency and payment_currency mirror each other, and lower-case *_iban / *_bic spellings are canonicalized - without reformatting any value. Use this before JSON-Schema validation, where typed values (numbers, booleans) must keep their types.

Parameters:

row – The raw input record.

Returns:

A new dict with canonical keys; the input is not mutated.

pain001.xml.generate_xml.generate_xml(data: list[dict[str, Any]], payment_initiation_message_type: str, xml_file_path: str, xsd_file_path: str, output_path: str | None = None) str[source]#

Generates an ISO 20022 pain.001 XML file from input data.

This function writes XML to a file. For in-memory XML generation (serverless/API use cases), use generate_xml_string() instead.

Parameters:
  • data – List of dictionaries containing payment data

  • payment_initiation_message_type – Message type identifier. Any supported version from “pain.001.001.03” through “pain.001.001.12”, or “pain.008.001.02” for direct debits.

  • xml_file_path – Path to the Jinja2 XML template file

  • xsd_file_path – Path to XML schema file for validation

  • output_path – Explicit path to write the generated XML file to. Parent directories are created if needed. When omitted, the file is written next to the template (deprecated behavior that only works when the template lives under the current working directory).

Returns:

The path the XML file was written to.

Raises:

ValueError – If message type is invalid, data is empty, or the output path fails validation. RuntimeError from XSD validation in generate_xml_string propagates unchanged.

pain001.xml.generate_xml.generate_xml_string(data: list[dict[str, object]], payment_initiation_message_type: str, xml_template_path: str, xsd_schema_path: str) str[source]#

Generate ISO 20022 pain.001 XML content as a string (in-memory).

This function is ideal for serverless architectures, REST APIs, and microservices where XML needs to be returned without writing to disk.

Parameters:
  • data – List of dictionaries containing payment data.

  • payment_initiation_message_type – Message type (e.g., “pain.001.001.03”).

  • xml_template_path – Path to the Jinja2 XML template file.

  • xsd_schema_path – Path to XSD schema file for validation.

Returns:

The generated and validated XML content.

Return type:

str

Raises:
  • ValueError – If message type is invalid, data is empty, the template or schema path fails validation, or the template contains disabled Jinja filesystem directives.

  • RuntimeError – If XML validation fails against XSD schema.

PaymentValidationError from amount normalization (missing, non-numeric, non-positive, or over-precise payment_amount values) propagates unchanged.

Examples

>>> data = [{"id": "MSG001", "date": "2026-01-15", ...}]
>>> xml_str = generate_xml_string(
...     data,
...     "pain.001.001.03",
...     "templates/pain.001.001.03/template.xml",
...     "templates/pain.001.001.03/pain.001.001.03.xsd"
... )
>>> xml_str.startswith('<?xml')
True
pain001.xml.generate_xml.normalize_payment_records(data: list[dict[str, Any]]) list[dict[str, Any]][source]#

Normalize caller records into the canonical pain.001 input shape.

Applies the same ergonomics the generators use internally, so records can also be pre-normalized before JSON-Schema validation:

  • field aliases (amount -> payment_amount, currency <-> payment_currency, lower-case IBAN/BIC key spellings, …);

  • amounts formatted as exact two-decimal strings;

  • Python/JSON booleans (and "True"/"FALSE" strings) rendered in XSD form ("true"/"false");

  • bare dates coerced to the XSD lexical form each field requires (date -> YYYY-MM-DDT00:00:00, requested_execution_date truncated to YYYY-MM-DD);

  • nb_of_txs and ctrl_sum computed from the rows themselves.

Parameters:

data – The raw payment rows.

Returns:

A new list of normalized rows; the input is not mutated.

A PaymentValidationError from amount normalization (missing, non-numeric, non-positive, or over-precise payment amounts) propagates unchanged.

pain001.xml.register_namespaces module#

Register ISO 20022 XML namespaces for ElementTree serialization.

pain001.xml.register_namespaces.register_namespaces(payment_initiation_message_type: str) None[source]#

This function registers the namespaces for the payment initiation message type.

Parameters:

payment_initiation_message_type – The payment initiation message type (e.g. “pain.001.001.03”).

pain001.xml.validate_via_xsd module#

Validate XML documents against XSD schemas.

pain001.xml.validate_via_xsd.collect_xsd_validation_errors(xml_content: str, xsd_file_path: str, max_errors: int = 20) list[str][source]#

Collect every XSD validation error for an XML string, human-readably.

Unlike validate_xml_string_via_xsd() (a boolean gate), this returns one concise message per violation - element path plus reason - so callers can report everything that is wrong in a single pass.

Parameters:
  • xml_content – XML content as a string.

  • xsd_file_path – Path to the XSD schema file.

  • max_errors – Cap on the number of collected messages.

Returns:

A list of error messages; empty when the document is valid.

pain001.xml.validate_via_xsd.validate_via_xsd(xml_file_path: str, xsd_file_path: str) bool[source]#

Validates an XML file against an XSD schema.

Parameters:
  • xml_file_path – Path to the XML file to validate.

  • xsd_file_path – Path to the XSD schema file.

Returns:

True if the XML file is valid, False otherwise.

Return type:

bool

pain001.xml.validate_via_xsd.validate_xml_string_via_xsd(xml_content: str, xsd_file_path: str) bool[source]#

Validates an XML string against an XSD schema.

This function is ideal for serverless/API architectures where XML is generated in-memory without writing to disk.

Parameters:
  • xml_content – XML content as a string.

  • xsd_file_path – Path to the XSD schema file.

Returns:

True if the XML content is valid, False otherwise.

Return type:

bool

Examples

>>> xml_str = '<?xml version="1.0"?><Document></Document>'
>>> xsd_path = "schema.xsd"
>>> validate_xml_string_via_xsd(xml_str, xsd_path)
True

pain001.xml.write_xml_to_file module#

This module contains a utility function for writing XML content to a file. The XML content is pretty-formatted with proper indentation for better readability.

pain001.xml.write_xml_to_file.indent_xml(elem: Element, level: int = 0) None[source]#

Add indentation to XML elements in-place for pretty printing.

This is a fast, memory-efficient way to format XML without re-parsing.

Parameters:
  • elem (xml.etree.ElementTree.Element) – The element to indent.

  • level (int) – The current indentation level.

pain001.xml.write_xml_to_file.write_xml_to_file(xml_file_path: str, root: Element) None[source]#

Write the XML tree to a file, with pretty formatting (indentation).

This optimized version uses in-place indentation instead of minidom, providing ~70% faster performance and ~50% memory reduction.

Parameters:
  • xml_file_path (str) – The file path where the XML content will be written.

  • root (xml.etree.ElementTree.Element) – The root element of the XML tree.

Returns:

The function writes the XML content to a file and does not return any value.

Return type:

None

Module contents#

XML generation and validation package for pain001.