diff --git a/CHANGES b/CHANGES index 39e6725..70d9904 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,7 @@ Changes ======= +* 0.64: huTools.structured.dict2xml now supports flat lists and unordered content * 0.63: huTools.cache added * 0.62: huTools.structured.Struct has a __nonzero__ method * 0.61: huTools.structured.Struct and make_struct handle lists and get an items() method diff --git a/huTools/structured.py b/huTools/structured.py index 145b817..0cc1ddc 100644 --- a/huTools/structured.py +++ b/huTools/structured.py @@ -8,7 +8,6 @@ import xml.etree.cElementTree as ET from StringIO import StringIO - # Basic conversation goal here is converting a dict to an object allowing # more comfortable access. `Struct()` and `make_struct()` are used to archive # this goal. @@ -206,20 +205,31 @@ def make_struct(obj, default=None, nodefault=False): # Code is based on http://code.activestate.com/recipes/573463/ -def _convert_dict_to_xml_recurse(parent, dictitem, listnames): +def _convert_dict_to_xml_recurse(parent, dictitem, listnames, sort=True): """Helper Function for XML conversion.""" - # we can't convert bare lists - assert not isinstance(dictitem, list) + + if isinstance(dictitem, list): + raise TypeError('Unable to convert bare lists') if isinstance(dictitem, dict): - for (tag, child) in sorted(dictitem.iteritems()): + items = dictitem.iteritems() + if sort: + items = sorted(items) + for (tag, child) in items: if isinstance(child, list): # iterate through the array and convert - listelem = ET.Element(tag) - parent.append(listelem) + itemname = listnames.get(tag, 'item') + if itemname is not None: + listelem = ET.SubElement(parent, tag) + else: + listelem = parent + for listchild in child: - elem = ET.Element(listnames.get(tag, 'item')) - listelem.append(elem) + if itemname is not None: + elem = ET.SubElement(listelem, itemname) + else: + elem = ET.SubElement(listelem, tag) + _convert_dict_to_xml_recurse(elem, listchild, listnames) else: if tag.startswith('@'): @@ -232,7 +242,7 @@ def _convert_dict_to_xml_recurse(parent, dictitem, listnames): parent.text = unicode(dictitem) -def dict2et(xmldict, roottag='data', listnames=None): +def dict2et(xmldict, roottag='data', listnames=None, sort=True): """Converts a dict to an ElementTree. Converts a dictionary to an XML ElementTree Element:: @@ -242,9 +252,9 @@ def dict2et(xmldict, roottag='data', listnames=None): >>> ET.tostring(root) 'xq12122' - Per default ecerything ins put in an enclosing '' element. Also per default lists are converted - to collecitons of `` elements. But by provding a mapping between list names and element names, - you van generate different elements:: + Per default everything is put in an enclosing '' element. Also per default lists are converted + to collections of `` elements. By provding a mapping between list names and element names, + you can generate different elements: >>> data = {"positionen": [{"m": 12}, {"m": 2}]} >>> root = dict2et(data, roottag='xml') @@ -255,6 +265,11 @@ def dict2et(xmldict, roottag='data', listnames=None): >>> ET.tostring(root) '122' + If you explictly set the elementname to None, a flat list is created: + >>> root = dict2et(data, roottag='flat', listnames={'positionen': None}) + >>> ET.tostring(root) + '122' + >>> data = {"kommiauftragsnr":2103839, "anliefertermin":"2009-11-25", "prioritaet": 7, ... "ort": u"Hücksenwagen", ... "positionen": [{"menge": 12, "artnr": "14640/XL", "posnr": 1},], @@ -285,12 +300,14 @@ def dict2et(xmldict, roottag='data', listnames=None): 7 2103839 ''' + + Sorting can be disabled which is only useful for collections.OrderedDict. """ if not listnames: listnames = {} root = ET.Element(roottag) - _convert_dict_to_xml_recurse(root, xmldict, listnames) + _convert_dict_to_xml_recurse(root, xmldict, listnames, sort=sort) return root @@ -304,12 +321,12 @@ def list2et(xmllist, root, elementname): return basexml.find(root) -def dict2xml(datadict, roottag='data', listnames=None, pretty=False): +def dict2xml(datadict, roottag='data', listnames=None, pretty=False, sort=True): """Converts a dictionary to an UTF-8 encoded XML string. See also dict2et() """ - root = dict2et(datadict, roottag, listnames) + root = dict2et(datadict, roottag, listnames, sort=sort) return to_string(root, pretty=pretty) diff --git a/setup.py b/setup.py index 4498a74..3bfb30a 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,7 @@ from distutils.core import setup -version = '0.63' +version = '0.64' setup( name='huTools',