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