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      TestON is free software: you can redistribute it and/or modify 
  7      it under the terms of the GNU General Public License as published by 
  8      the Free Software Foundation, either version 2 of the License, or 
  9      (at your option) any later version. 
 10   
 11      TestON is distributed in the hope that it will be useful, 
 12      but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14      GNU General Public License for more details. 
 15   
 16      You should have received a copy of the GNU General Public License 
 17      along with TestON.  If not, see <http://www.gnu.org/licenses/>. 
 18   
 19  ''' 
 20   
 21  """ 
 22      xmldict 
 23      ~~~~~~~~~~~~~~~~~~~~~~~~~ 
 24   
 25      Convert xml to python dictionaries. 
 26  """ 
 27  import datetime 
 28   
29 -def xml_to_dict(root_or_str, strict=True):
30 """ 31 Converts `root_or_str` which can be parsed xml or a xml string to dict. 32 33 """ 34 root = root_or_str 35 if isinstance(root, str): 36 import xml.etree.cElementTree as ElementTree 37 root = ElementTree.XML(root_or_str) 38 try : 39 return {root.tag: _from_xml(root, strict)} 40 except Exception: 41 return None
42
43 -def dict_to_xml(dict_xml):
44 """ 45 Converts `dict_xml` which is a python dict to corresponding xml. 46 """ 47 return _to_xml(dict_xml)
48
49 -def _to_xml(el):
50 """ 51 Converts `el` to its xml representation. 52 """ 53 val = None 54 if isinstance(el, dict): 55 val = _dict_to_xml(el) 56 elif isinstance(el, bool): 57 val = str(el).lower() 58 else: 59 val = el 60 if val is None: val = 'null' 61 return val
62
63 -def _extract_attrs(els):
64 """ 65 Extracts attributes from dictionary `els`. Attributes are keys which start 66 with '@' 67 """ 68 if not isinstance(els, dict): 69 return '' 70 return ''.join(' %s="%s"' % (key[1:], value) for key, value in els.iteritems() 71 if key.startswith('@'))
72
73 -def _dict_to_xml(els):
74 """ 75 Converts `els` which is a python dict to corresponding xml. 76 """ 77 def process_content(tag, content): 78 attrs = _extract_attrs(content) 79 text = isinstance(content, dict) and content.get('#text', '') or '' 80 return '<%s%s>%s%s</%s>' % (tag, attrs, _to_xml(content), text, tag)
81 82 tags = [] 83 for tag, content in els.iteritems(): 84 # Text and attributes 85 if tag.startswith('@') or tag == '#text': 86 continue 87 elif isinstance(content, list): 88 for el in content: 89 tags.append(process_content(tag, el)) 90 elif isinstance(content, dict): 91 tags.append(process_content(tag, content)) 92 else: 93 tags.append('<%s>%s</%s>' % (tag, _to_xml(content), tag)) 94 return ''.join(tags) 95
96 -def _is_xml_el_dict(el):
97 """ 98 Returns true if `el` is supposed to be a dict. 99 This function makes sense only in the context of making dicts out of xml. 100 """ 101 if len(el) == 1 or el[0].tag != el[1].tag: 102 return True 103 return False
104
105 -def _is_xml_el_list(el):
106 """ 107 Returns true if `el` is supposed to be a list. 108 This function makes sense only in the context of making lists out of xml. 109 """ 110 if len(el) > 1 and el[0].tag == el[1].tag: 111 return True 112 return False
113
114 -def _str_to_datetime(date_str):
115 try: 116 val = datetime.datetime.strptime(date_str, "%Y-%m-%dT%H:%M:%SZ") 117 except ValueError: 118 val = date_str 119 return val
120
121 -def _str_to_boolean(bool_str):
122 if bool_str.lower() != 'false' and bool(bool_str): 123 return True 124 return False
125
126 -def _from_xml(el, strict):
127 """ 128 Extracts value of xml element element `el`. 129 """ 130 val = None 131 # Parent node. 132 if el: 133 if _is_xml_el_dict(el): 134 val = _dict_from_xml(el, strict) 135 elif _is_xml_el_list(el): 136 val = _list_from_xml(el, strict) 137 # Simple node. 138 else: 139 attribs = el.items() 140 # An element with attributes. 141 if attribs and strict: 142 val = dict(('@%s' % k, v) for k, v in dict(attribs).iteritems()) 143 if el.text: 144 converted = _val_and_maybe_convert(el) 145 val['#text'] = el.text 146 if converted != el.text: 147 val['#value'] = converted 148 elif el.text: 149 # An element with no subelements but text. 150 val = _val_and_maybe_convert(el) 151 elif attribs: 152 val = dict(attribs) 153 return val
154
155 -def _val_and_maybe_convert(el):
156 """ 157 Converts `el.text` if `el` has attribute `type` with valid value. 158 """ 159 text = el.text.strip() 160 data_type = el.get('type') 161 convertor = _val_and_maybe_convert.convertors.get(data_type) 162 if convertor: 163 return convertor(text) 164 else: 165 return text
166 _val_and_maybe_convert.convertors = { 167 'boolean': _str_to_boolean, 168 'datetime': _str_to_datetime, 169 'integer': int 170 } 171
172 -def _list_from_xml(els, strict):
173 """ 174 Converts xml elements list `el_list` to a python list. 175 """ 176 177 temp = {} 178 for el in els: 179 tag = el.attrib["name"] 180 temp[tag] = (_from_xml(el, strict)) 181 return temp
182
183 -def _dict_from_xml(els, strict):
184 """ 185 Converts xml doc with root `root` to a python dict. 186 """ 187 # An element with subelements. 188 res = {} 189 for el in els: 190 res[el.tag] = _from_xml(el, strict) 191 return res
192