Skip to content

Commit

Permalink
fix issue quandyfactory#39 ability to not include item tags
Browse files Browse the repository at this point in the history
  • Loading branch information
Euphorbium committed Nov 6, 2015
1 parent 0e57a49 commit 3b50379
Showing 1 changed file with 32 additions and 18 deletions.
50 changes: 32 additions & 18 deletions dicttoxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def make_valid_xml_name(key, attr):
key = 'key'
return key, attr

def convert(obj, ids, attr_type, parent='root'):
def convert(obj, ids, attr_type, parent='root', item_tags=True):
"""Routes the elements of an object to the right function to convert them based on their data type"""
LOG.info('Inside convert(). obj type is: "%s", obj="%s"' % (type(obj).__name__, unicode_me(obj)))
if isinstance(obj, numbers.Number) or type(obj) in (str, unicode):
Expand All @@ -142,12 +142,12 @@ def convert(obj, ids, attr_type, parent='root'):
if obj == None:
return convert_none('item', '', attr_type)
if isinstance(obj, dict):
return convert_dict(obj, ids, parent, attr_type)
return convert_dict(obj, ids, parent, attr_type, item_tags=item_tags)
if isinstance(obj, collections.Iterable):
return convert_list(obj, ids, parent, attr_type)
return convert_list(obj, ids, parent, attr_type, item_tags=item_tags)
raise TypeError('Unsupported data type: %s (%s)' % (obj, type(obj).__name__))

def convert_dict(obj, ids, parent, attr_type):
def convert_dict(obj, ids, parent, attr_type, item_tags=True):
"""Converts a dict into an XML string."""
LOG.info('Inside convert_dict(): obj type is: "%s", obj="%s"' % (type(obj).__name__, unicode_me(obj)))
output = []
Expand All @@ -172,49 +172,63 @@ def convert_dict(obj, ids, parent, attr_type):
if attr_type:
attr['type'] = get_xml_type(val)
addline('<%s%s>%s</%s>' % (
key, make_attrstring(attr), convert_dict(val, ids, key, attr_type), key)
key, make_attrstring(attr), convert_dict(val, ids, key, attr_type, item_tags=item_tags), key)
)
elif isinstance(val, collections.Iterable):
if attr_type:
attr['type'] = get_xml_type(val)
addline('<%s%s>%s</%s>' % (
key, make_attrstring(attr), convert_list(val, ids, key, attr_type), key)
key, make_attrstring(attr), convert_list(val, ids, key, attr_type, item_tags=item_tags), key)
)
elif val is None:
addline(convert_none(key, val, attr_type, attr))
else:
raise TypeError('Unsupported data type: %s (%s)' % (val, type(val).__name__))
return ''.join(output)

def convert_list(items, ids, parent, attr_type):
def convert_list(items, ids, parent, attr_type, item_tags=True):
"""Converts a list into an XML string."""
LOG.info('Inside convert_list()')
output = []
addline = output.append

if ids:
this_id = get_unique_id(parent)

for i, item in enumerate(items):
LOG.info('Looping inside convert_list(): item="%s", type="%s"' % (unicode_me(item), type(item).__name__))
attr = {} if not ids else { 'id': '%s_%s' % (this_id, i+1) }
if isinstance(item, numbers.Number) or type(item) in (str, unicode):
addline(convert_kv('item', item, attr_type, attr))
if item_tags:
addline(convert_kv('item', item, attr_type, attr))
else: addline(str(item)+'\n')

elif hasattr(item, 'isoformat'): # datetime
addline(convert_kv('item', item.isoformat(), attr_type, attr))
elif type(item) == bool:
addline(convert_bool('item', item, attr_type, attr))
elif isinstance(item, dict):
if not attr_type:
addline('<item>%s</item>' % (convert_dict(item, ids, parent, attr_type)))
if item_tags:
addline('<item>%s</item>' % (convert_dict(item, ids, parent, attr_type)))
else:
addline(convert_dict(item, ids, parent, attr_type, item_tags=item_tags))
else:
addline('<item type="dict">%s</item>' % (convert_dict(item, ids, parent, attr_type)))
if item_tags:
addline('<item type="dict">%s</item>' % (convert_dict(item, ids, parent, attr_type)))
else:
addline(convert_dict(item, ids, parent, attr_type))
elif isinstance(item, collections.Iterable):
if not attr_type:
addline('<item %s>%s</item>' % (make_attrstring(attr), convert_list(item, ids, 'item', attr_type)))
if item_tags:
addline('<item %s>%s</item>' % (make_attrstring(attr), convert_list(item, ids, 'item', attr_type,)))
else:
addline(make_attrstring(attr), convert_list(item, ids, 'item', attr_type, item_tags=item_tags))
else:
addline('<item type="list"%s>%s</item>' % (make_attrstring(attr), convert_list(item, ids, 'item', attr_type)))
elif item is None:
if item_tags:
addline('<item type="list"%s>%s</item>' % (make_attrstring(attr), convert_list(item, ids, 'item', attr_type)))
else:
addline(make_attrstring(attr), convert_list(item, ids, 'item', attr_type, item_tags=item_tags))
elif item is None and item_tags:
addline(convert_none('item', None, attr_type, attr))
else:
raise TypeError('Unsupported data type: %s (%s)' % (item, type(item).__name__))
Expand Down Expand Up @@ -255,18 +269,18 @@ def convert_none(key, val, attr_type, attr={}):
attrstring = make_attrstring(attr)
return '<%s%s></%s>' % (key, attrstring, key)

def dicttoxml(obj, root=True, custom_root='root', ids=False, attr_type=True):
def dicttoxml(obj, root=True, custom_root='root', ids=False, attr_type=True, item_tags=True):
"""Converts a python object into XML
attr_type is used to specify if data type for each element should be included in the resulting xml.
By default, it is set to True.
By default, it is set to True. item_tags specify if elements of iterables should be wrapped in <item> tags.
"""
LOG.info('Inside dicttoxml(): type(obj) is: "%s", obj="%s"' % (type(obj).__name__, unicode_me(obj)))
output = []
addline = output.append
if root == True:
addline('<?xml version="1.0" encoding="UTF-8" ?>')
addline('<%s>%s</%s>' % (custom_root, convert(obj, ids, attr_type, parent=custom_root), custom_root))
addline('<%s>%s</%s>' % (custom_root, convert(obj, ids, attr_type, parent=custom_root, item_tags=item_tags), custom_root))
else:
addline(convert(obj, ids, attr_type, parent=''))
addline(convert(obj, ids, attr_type, parent='', item_tags=item_tags))
return ''.join(output).encode('utf-8')

0 comments on commit 3b50379

Please sign in to comment.