Package TestON :: Package core :: Module xmldict
[hide private]
[frames] | no frames]

Source Code for Module TestON.core.xmldict

  1  ''' 
  2  Created on 03-Dec-2012 
  3   
  4  @author: Anil Kumar (anilkumar.s@paxterrasolutions.com) 
  5  ''' 
  6   
  7  """ 
  8      xmldict 
  9      ~~~~~~~~~~~~~~~~~~~~~~~~~ 
 10   
 11      Convert xml to python dictionaries. 
 12  """ 
 13  import datetime 
 14   
15 -def xml_to_dict(root_or_str, strict=True):
16 """ 17 Converts `root_or_str` which can be parsed xml or a xml string to dict. 18 19 """ 20 root = root_or_str 21 if isinstance(root, str): 22 import xml.etree.cElementTree as ElementTree 23 root = ElementTree.XML(root_or_str) 24 return {root.tag: _from_xml(root, strict)}
25
26 -def dict_to_xml(dict_xml):
27 """ 28 Converts `dict_xml` which is a python dict to corresponding xml. 29 """ 30 return _to_xml(dict_xml)
31
32 -def _to_xml(el):
33 """ 34 Converts `el` to its xml representation. 35 """ 36 val = None 37 if isinstance(el, dict): 38 val = _dict_to_xml(el) 39 elif isinstance(el, bool): 40 val = str(el).lower() 41 else: 42 val = el 43 if val is None: val = 'null' 44 return val
45
46 -def _extract_attrs(els):
47 """ 48 Extracts attributes from dictionary `els`. Attributes are keys which start 49 with '@' 50 """ 51 if not isinstance(els, dict): 52 return '' 53 return ''.join(' %s="%s"' % (key[1:], value) for key, value in els.iteritems() 54 if key.startswith('@'))
55
56 -def _dict_to_xml(els):
57 """ 58 Converts `els` which is a python dict to corresponding xml. 59 """ 60 def process_content(tag, content): 61 attrs = _extract_attrs(content) 62 text = isinstance(content, dict) and content.get('#text', '') or '' 63 return '<%s%s>%s%s</%s>' % (tag, attrs, _to_xml(content), text, tag)
64 65 tags = [] 66 for tag, content in els.iteritems(): 67 # Text and attributes 68 if tag.startswith('@') or tag == '#text': 69 continue 70 elif isinstance(content, list): 71 for el in content: 72 tags.append(process_content(tag, el)) 73 elif isinstance(content, dict): 74 tags.append(process_content(tag, content)) 75 else: 76 tags.append('<%s>%s</%s>' % (tag, _to_xml(content), tag)) 77 return ''.join(tags) 78
79 -def _is_xml_el_dict(el):
80 """ 81 Returns true if `el` is supposed to be a dict. 82 This function makes sense only in the context of making dicts out of xml. 83 """ 84 if len(el) == 1 or el[0].tag != el[1].tag: 85 return True 86 return False
87
88 -def _is_xml_el_list(el):
89 """ 90 Returns true if `el` is supposed to be a list. 91 This function makes sense only in the context of making lists out of xml. 92 """ 93 if len(el) > 1 and el[0].tag == el[1].tag: 94 return True 95 return False
96
97 -def _str_to_datetime(date_str):
98 try: 99 val = datetime.datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%SZ") 100 except ValueError: 101 val = date_str 102 return val
103
104 -def _str_to_boolean(bool_str):
105 if bool_str.lower() != 'false' and bool(bool_str): 106 return True 107 return False
108
109 -def _from_xml(el, strict):
110 """ 111 Extracts value of xml element element `el`. 112 """ 113 val = None 114 # Parent node. 115 if el: 116 if _is_xml_el_dict(el): 117 val = _dict_from_xml(el, strict) 118 elif _is_xml_el_list(el): 119 val = _list_from_xml(el, strict) 120 # Simple node. 121 else: 122 attribs = el.items() 123 # An element with attributes. 124 if attribs and strict: 125 val = dict(('@%s' % k, v) for k, v in dict(attribs).iteritems()) 126 if el.text: 127 converted = _val_and_maybe_convert(el) 128 val['#text'] = el.text 129 if converted != el.text: 130 val['#value'] = converted 131 elif el.text: 132 # An element with no subelements but text. 133 val = _val_and_maybe_convert(el) 134 elif attribs: 135 val = dict(attribs) 136 return val
137
138 -def _val_and_maybe_convert(el):
139 """ 140 Converts `el.text` if `el` has attribute `type` with valid value. 141 """ 142 text = el.text.strip() 143 data_type = el.get('type') 144 convertor = _val_and_maybe_convert.convertors.get(data_type) 145 if convertor: 146 return convertor(text) 147 else: 148 return text
149 _val_and_maybe_convert.convertors = { 150 'boolean': _str_to_boolean, 151 'datetime': _str_to_datetime, 152 'integer': int 153 } 154
155 -def _list_from_xml(els, strict):
156 """ 157 Converts xml elements list `el_list` to a python list. 158 """ 159 160 temp = {} 161 for el in els: 162 tag = el.attrib["name"] 163 temp[tag] = (_from_xml(el, strict)) 164 return temp
165
166 -def _dict_from_xml(els, strict):
167 """ 168 Converts xml doc with root `root` to a python dict. 169 """ 170 # An element with subelements. 171 res = {} 172 for el in els: 173 res[el.tag] = _from_xml(el, strict) 174 return res
175