ATLAS Offline Software
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__ = """\
9 functions to convert an XML file into a python dict, back and forth
10 """
11 __author__ = "Sebastien Binet <binet@cern.ch>"
12 
13 
14 # hack: LCGCMT had the py-2.5 xml.etree module hidden by mistake.
15 # this is to import it, by hook or by crook
17  import xml
18  # first try the usual way
19  try:
20  import xml.etree
21  return xml.etree
22  except ImportError:
23  pass
24  # do it by hook or by crook...
25  import os, imp
26  xml_site_package = os.path.join(os.path.dirname(os.__file__), 'xml')
27  m = imp.find_module('etree', [xml_site_package])
28 
29  etree = imp.load_module('xml.etree', *m)
30  xml.etree = etree
31  return etree
32 
33 etree = import_etree()
34 from xml.etree import ElementTree
35 
36 from xml.sax.saxutils import escape as _xml_escape
37 from xml.sax.saxutils import unescape as _xml_unescape
38 
39 
40 __all__ = [
41  'xml2dict',
42  'dict2xml',
43  ]
44 
45 
46 class XmlDictObject(dict):
47  def __init__(self, initdict=None):
48  if initdict is None:
49  initdict = {}
50  dict.__init__(self, initdict)
51 
52  def __getattr__(self, item):
53  return self.__getitem__(item)
54 
55  def __setattr__(self, item, value):
56  self.__setitem__(item, value)
57 
58 
63 
64 
68 
69  def __str__(self):
70  if '_text' in self:
71  return self['_text']
72  else:
73  return dict.__str__(self)
74 
75  @staticmethod
76  def wrap(x):
77  if isinstance(x, dict):
78  return XmlDictObject ((k, XmlDictObject.wrap(v))
79  for (k, v) in x.iteritems())
80  elif isinstance(x, list):
81  return [XmlDictObject.wrap(v) for v in x]
82  else:
83  return x
84 
85  @staticmethod
86  def _unwrap(x):
87  if isinstance(x, dict):
88  return dict ((k, XmlDictObject._unwrap(v))
89  for (k, v) in x.iteritems())
90  elif isinstance(x, list):
91  return [XmlDictObject._unwrap(v) for v in x]
92  else:
93  return x
94 
95  def unwrap(self):
96  return XmlDictObject._unwrap(self)
97 
98 def _dict2xml_recurse(parent, dictitem):
99  assert type(dictitem) is not type(list)
100 
101  if isinstance(dictitem, dict):
102  for (tag, child) in dictitem.iteritems():
103  if isinstance(child, str):
104  child = _xml_escape(child)
105  if str(tag) == '_text':
106  parent.text = str(child)
107  elif type(child) is type(list):
108  for listchild in child:
109  elem = ElementTree.Element(tag)
110  parent.append(elem)
111  _dict2xml_recurse (elem, listchild)
112  else:
113  elem = ElementTree.Element(tag)
114  parent.append(elem)
115  _dict2xml_recurse (elem, child)
116  else:
117  parent.text = str(dictitem)
118 
119 def dict2xml(xmldict):
120  """convert a python dictionary into an XML tree"""
121  roottag = xmldict.keys()[0]
122  root = ElementTree.Element(roottag)
123  _dict2xml_recurse (root, xmldict[roottag])
124  return root
125 
126 def _xml2dict_recurse (node, dictclass):
127  nodedict = dictclass()
128 
129  if len(node.items()) > 0:
130  # if we have attributes, set them
131  nodedict.update(dict((k, _xml_unescape(v) if isinstance(v, str) else v)
132  for k,v in node.items()))
133 
134  for child in node:
135  # recursively add the element's children
136  newitem = _xml2dict_recurse (child, dictclass)
137  if isinstance(newitem, str):
138  newitem = _xml_unescape(newitem)
139  if child.tag in nodedict:
140  # found duplicate tag, force a list
141  if isinstance(nodedict[child.tag], list):
142  # append to existing list
143  nodedict[child.tag].append(newitem)
144  else:
145  # convert to list
146  nodedict[child.tag] = [nodedict[child.tag], newitem]
147  else:
148  # only one, directly set the dictionary
149  nodedict[child.tag] = newitem
150 
151  if node.text is None:
152  text = ''
153  else:
154  text = node.text.strip()
155 
156  if len(nodedict) > 0:
157  # if we have a dictionary add the text as a dictionary value
158  # (if there is any)
159  if len(text) > 0:
160  nodedict['_text'] = text
161  else:
162  # if we don't have child nodes or attributes, just set the text
163  if node.text: nodedict = node.text.strip()
164  else: nodedict = ""
165 
166  return nodedict
167 
168 def xml2dict (root, dictclass=XmlDictObject):
169  """convert an xml tree into a python dictionary
170  """
171  return dictclass({root.tag: _xml2dict_recurse (root, dictclass)})
python.xmldict.dict2xml
def dict2xml(xmldict)
Definition: xmldict.py:119
python.xmldict.XmlDictObject.__getattr__
def __getattr__(self, item)
Definition: xmldict.py:52
dumpHVPathFromNtuple.append
bool append
Definition: dumpHVPathFromNtuple.py:91
python.xmldict.xml2dict
def xml2dict(root, dictclass=XmlDictObject)
Definition: xmldict.py:168
python.xmldict.import_etree
def import_etree()
Definition: xmldict.py:16
python.xmldict.XmlDictObject._unwrap
def _unwrap(x)
Definition: xmldict.py:86
python.xmldict.XmlDictObject.__init__
def __init__(self, initdict=None)
Definition: xmldict.py:47
python.xmldict.XmlDictObject.__str__
def __str__(self)
def getitem(self, item): o = dict.__getitem__(self, item) if isinstance(o, str): return _xml_unescape...
Definition: xmldict.py:69
python.xmldict.XmlDictObject.__setattr__
def __setattr__(self, item, value)
Definition: xmldict.py:55
python.xmldict.XmlDictObject.wrap
def wrap(x)
Definition: xmldict.py:76
python.xmldict._xml2dict_recurse
def _xml2dict_recurse(node, dictclass)
Definition: xmldict.py:126
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
python.xmldict._dict2xml_recurse
def _dict2xml_recurse(parent, dictitem)
Definition: xmldict.py:98
python.xmldict.XmlDictObject
module implementation ---------------------------------------------------—
Definition: xmldict.py:46
str
Definition: BTagTrackIpAccessor.cxx:11
python.xmldict.XmlDictObject.unwrap
def unwrap(self)
Definition: xmldict.py:95