Source code for wss_tools.utils.io

"""Module to handle I/O for files."""

# STDLIB
import os
import xml.etree.ElementTree as ET
from collections import defaultdict
from datetime import datetime
from xml.dom import minidom

__all__ = ['output_xml']


# --------------------- #
# GENERIC XML FUNCTIONS #
# --------------------- #

# https://stackoverflow.com/questions/7684333/converting-xml-to-dictionary-using-elementtree
def _etree_to_dict(t):
    """Convert XML element tree to dictionary."""
    d = {t.tag: {} if t.attrib else None}
    children = list(t)
    if children:
        dd = defaultdict(list)
        for dc in map(_etree_to_dict, children):
            for k, v in dc.items():
                dd[k].append(v)
        d = {t.tag: {k: v[0] if len(v) == 1 else v for k, v in dd.items()}}
    if t.attrib:
        d[t.tag].update(('@' + k, v) for k, v in t.attrib.items())
    if t.text:
        text = t.text.strip()
        if children or t.attrib:
            if text:
                d[t.tag]['#text'] = text
        else:
            d[t.tag] = text
    return d


# https://code.activestate.com/recipes/573463-converting-xml-to-dictionary-and-back/
def _dict_to_etree(parent, dictitem):
    """Convert dictionary to XML element tree."""
    assert not isinstance(dictitem, list)

    if isinstance(dictitem, dict):
        for (tag, child) in dictitem.items():
            if str(tag) == '#text':
                parent.text = str(child)
            elif str(tag).startswith('@'):
                parent.attrib[str(tag)[1:]] = str(child)
            elif isinstance(child, list):
                # iterate through the array and convert
                for listchild in child:
                    elem = ET.Element(tag)
                    parent.append(elem)
                    _dict_to_etree(elem, listchild)
            else:
                elem = ET.Element(tag)
                parent.append(elem)
                _dict_to_etree(elem, child)
    else:
        parent.text = str(dictitem)


# https://stackoverflow.com/questions/17402323/use-xml-etree-elementtree-to-write-out-nicely-formatted-xml-files
[docs]def output_xml(xmldict, filename): """Write given dictionary to XML. Parameters ---------- xmldict : dict Dictionary to be converted. filename : str Output XML file. Raises ------ OSError Output file exists. """ roottag = list(xmldict)[0] root = ET.Element(roottag) _dict_to_etree(root, xmldict[roottag]) rough_string = ET.tostring(root, 'utf-8') reparsed = minidom.parseString(rough_string) if os.path.exists(filename): raise OSError(f'{filename} exists') with open(filename, 'w') as fout: fout.write(reparsed.toprettyxml(indent=' '))
# -------------- # # OUTPUTS TO WEx # # -------------- # def _get_timestamp(): """Return dictionary with UTC timestamp metadata.""" d = datetime.utcnow() return {'@date': d.strftime('%Y-%m-%dZ'), '@time': d.strftime('%H:%M:%S.%fZ')}