ATLAS Offline Software
Loading...
Searching...
No Matches
xmldict.py
Go to the documentation of this file.
1# Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
2
3# @file PyUtils/python/xmldict.py
4# @purpose converts an XML file into a python dict, back and forth
5# @author http://code.activestate.com/recipes/573463
6# slightly adapted to follow PEP8 conventions
7
8__doc__ = """\
9functions to convert an XML file into a python dict, back and forth
10"""
11__author__ = "Sebastien Binet <binet@cern.ch>"
12
13
14from xml.etree import ElementTree
15
16from xml.sax.saxutils import escape as _xml_escape
17from xml.sax.saxutils import unescape as _xml_unescape
18
19
20__all__ = [
21 'xml2dict',
22 'dict2xml',
23 ]
24
25
26class XmlDictObject(dict):
27 def __init__(self, initdict=None):
28 if initdict is None:
29 initdict = {}
30 dict.__init__(self, initdict)
31
32 def __getattr__(self, item):
33 return self.__getitem__(item)
34
35 def __setattr__(self, item, value):
36 self.__setitem__(item, value)
37
38
43
44
48
49 def __str__(self):
50 if '_text' in self:
51 return self['_text']
52 else:
53 return dict.__str__(self)
54
55 @staticmethod
56 def wrap(x):
57 if isinstance(x, dict):
58 return XmlDictObject ((k, XmlDictObject.wrap(v))
59 for (k, v) in x.iteritems())
60 elif isinstance(x, list):
61 return [XmlDictObject.wrap(v) for v in x]
62 else:
63 return x
64
65 @staticmethod
66 def _unwrap(x):
67 if isinstance(x, dict):
68 return dict ((k, XmlDictObject._unwrap(v))
69 for (k, v) in x.iteritems())
70 elif isinstance(x, list):
71 return [XmlDictObject._unwrap(v) for v in x]
72 else:
73 return x
74
75 def unwrap(self):
76 return XmlDictObject._unwrap(self)
77
78def _dict2xml_recurse(parent, dictitem):
79 assert type(dictitem) is not type(list)
80
81 if isinstance(dictitem, dict):
82 for (tag, child) in dictitem.iteritems():
83 if isinstance(child, str):
84 child = _xml_escape(child)
85 if str(tag) == '_text':
86 parent.text = str(child)
87 elif type(child) is type(list):
88 for listchild in child:
89 elem = ElementTree.Element(tag)
90 parent.append(elem)
91 _dict2xml_recurse (elem, listchild)
92 else:
93 elem = ElementTree.Element(tag)
94 parent.append(elem)
95 _dict2xml_recurse (elem, child)
96 else:
97 parent.text = str(dictitem)
98
99def dict2xml(xmldict):
100 """convert a python dictionary into an XML tree"""
101 roottag = xmldict.keys()[0]
102 root = ElementTree.Element(roottag)
103 _dict2xml_recurse (root, xmldict[roottag])
104 return root
105
106def _xml2dict_recurse (node, dictclass):
107 nodedict = dictclass()
108
109 if len(node.items()) > 0:
110 # if we have attributes, set them
111 nodedict.update(dict((k, _xml_unescape(v) if isinstance(v, str) else v)
112 for k,v in node.items()))
113
114 for child in node:
115 # recursively add the element's children
116 newitem = _xml2dict_recurse (child, dictclass)
117 if isinstance(newitem, str):
118 newitem = _xml_unescape(newitem)
119 if child.tag in nodedict:
120 # found duplicate tag, force a list
121 if isinstance(nodedict[child.tag], list):
122 # append to existing list
123 nodedict[child.tag].append(newitem)
124 else:
125 # convert to list
126 nodedict[child.tag] = [nodedict[child.tag], newitem]
127 else:
128 # only one, directly set the dictionary
129 nodedict[child.tag] = newitem
130
131 if node.text is None:
132 text = ''
133 else:
134 text = node.text.strip()
135
136 if len(nodedict) > 0:
137 # if we have a dictionary add the text as a dictionary value
138 # (if there is any)
139 if len(text) > 0:
140 nodedict['_text'] = text
141 else:
142 # if we don't have child nodes or attributes, just set the text
143 if node.text: nodedict = node.text.strip()
144 else: nodedict = ""
145
146 return nodedict
147
148def xml2dict (root, dictclass=XmlDictObject):
149 """convert an xml tree into a python dictionary
150 """
151 return dictclass({root.tag: _xml2dict_recurse (root, dictclass)})
module implementation ---------------------------------------------------—
Definition xmldict.py:26
__setattr__(self, item, value)
Definition xmldict.py:35
__init__(self, initdict=None)
Definition xmldict.py:27
__str__(self)
def getitem(self, item): o = dict.__getitem__(self, item) if isinstance(o, str): return _xml_unescape...
Definition xmldict.py:49
_dict2xml_recurse(parent, dictitem)
Definition xmldict.py:78
_xml2dict_recurse(node, dictclass)
Definition xmldict.py:106
dict2xml(xmldict)
Definition xmldict.py:99
xml2dict(root, dictclass=XmlDictObject)
Definition xmldict.py:148