Source code for sdmx.writer.xml

from lxml import etree
from lxml.builder import ElementMaker

import sdmx.urn
from sdmx import message, model
from sdmx.format.xml import NS, qname
from sdmx.writer.base import BaseWriter

_element_maker = ElementMaker(nsmap={k: v for k, v in NS.items() if v is not None})


def Element(name, *args, **kwargs):
    return _element_maker(qname(name), *args, **kwargs)


Writer = BaseWriter("XML")


[docs]def to_xml(obj, **kwargs): """Convert an SDMX *obj* to SDMX-ML. Parameters ---------- kwargs Passed to :meth:`lxml.etree.to_string`, e.g. `pretty_print` = :obj:`True`. Raises ------ NotImplementedError If writing specific objects to SDMX-ML has not been implemented in :mod:`sdmx`. """ return etree.tostring(Writer.recurse(obj), **kwargs)
# Utility functions def i11lstring(obj, name): """InternationalString. Returns a list of elements with name `name`. """ elems = [] for locale, label in obj.localizations.items(): child = Element(name, label) child.set(qname("xml", "lang"), locale) elems.append(child) return elems def annotable(obj, name, *args, **kwargs): elem = Element(name, *args, **kwargs) if len(obj.annotations): e_anno = Element("com:Annotations") e_anno.extend(Writer.recurse(a) for a in obj.annotations) elem.append(e_anno) return elem def identifiable(obj, name, *args, **kwargs): return annotable(obj, name, *args, id=obj.id, **kwargs) def nameable(obj, name, *args, **kwargs): elem = identifiable(obj, name, *args, **kwargs) elem.extend(i11lstring(obj.name, "com:Name")) return elem def maintainable(obj, parent=None): return nameable( obj, f"str:{obj.__class__.__name__}", urn=sdmx.urn.make(obj, parent) ) @Writer.register def _sm(obj: message.StructureMessage): msg = Element("mes:Structure") # Empty header element msg.append(Element("mes:Header")) structures = Element("mes:Structures") msg.append(structures) codelists = Element("str:Codelists") structures.append(codelists) codelists.extend(Writer.recurse(cl) for cl in obj.codelist.values()) return msg @Writer.register def _is(obj: model.ItemScheme): elem = maintainable(obj) elem.extend(Writer.recurse(i, parent=obj) for i in obj.items.values()) return elem @Writer.register def _i(obj: model.Item, parent): elem = maintainable(obj, parent=parent) if obj.parent: # Reference to parent code e_parent = Element("str:Parent") e_parent.append(Element(":Ref", id=obj.parent.id)) elem.append(e_parent) return elem @Writer.register def _a(obj: model.Annotation): elem = Element("com:Annotation") if obj.id: elem.attrib["id"] = obj.id elem.extend(i11lstring(obj.text, "com:AnnotationText")) return elem