# Create python xml structures compatible with
# http://search.cpan.org/~grantm/XML-Simple-2.18/lib/XML/Simple.pm
from lxml import etree
from itertools import groupby
def xml2d(e):
"""Convert an etree into a dict structure
@type e: etree.Element
@param e: the root of the tree
@return: The dictionary representation of the XML tree
"""
def _xml2d(e):
kids = dict(e.attrib)
if e.text:
kids['__text__'] = e.text
if e.tail:
kids['__tail__'] = e.tail
for k, g in groupby(e, lambda x: x.tag):
g = [ _xml2d(x) for x in g ]
kids[k]= g
return kids
return { e.tag : _xml2d(e) }
def d2xml(d):
"""convert dict to xml
1. The top level d must contain a single entry i.e. the root element
2. Keys of the dictionary become sublements or attributes
3. If a value is a simple string, then the key is an attribute
4. if a value is dict then, then key is a subelement
5. if a value is list, then key is a set of sublements
a = { 'module' : {'tag' : [ { 'name': 'a', 'value': 'b'},
{ 'name': 'c', 'value': 'd'},
],
'gobject' : { 'name': 'g', 'type':'xx' },
'uri' : 'test',
}
}
>>> d2xml(a)
<module uri="test">
<gobject type="xx" name="g"/>
<tag name="a" value="b"/>
<tag name="c" value="d"/>
</module>
@type d: dict
@param d: A dictionary formatted as an XML document
@return: A etree Root element
"""
def _d2xml(d, p):
for k,v in d.items():
if isinstance(v,dict):
node = etree.SubElement(p, k)
_d2xml(v, node)
elif isinstance(v,list):
for item in v:
node = etree.SubElement(p, k)
_d2xml(item, node)
elif k == "__text__":
p.text = v
elif k == "__tail__":
p.tail = v
else:
p.set(k, v)
k,v = d.items()[0]
node = etree.Element(k)
_d2xml(v, node)
return node
if __name__=="__main__":
X = """<T uri="boo"><a n="1"/><a n="2"/><b n="3"><c x="y"/></b></T>"""
print X
Y = xml2d(etree.XML(X))
print Y
Z = etree.tostring (d2xml(Y) )
print Z
assert X == Z
Diff to Previous Revision
--- revision 1 2011-05-26 01:48:00
+++ revision 2 2012-10-24 00:44:30
@@ -13,6 +13,10 @@
"""
def _xml2d(e):
kids = dict(e.attrib)
+ if e.text:
+ kids['__text__'] = e.text
+ if e.tail:
+ kids['__tail__'] = e.tail
for k, g in groupby(e, lambda x: x.tag):
g = [ _xml2d(x) for x in g ]
kids[k]= g
@@ -56,6 +60,10 @@
for item in v:
node = etree.SubElement(p, k)
_d2xml(item, node)
+ elif k == "__text__":
+ p.text = v
+ elif k == "__tail__":
+ p.tail = v
else:
p.set(k, v)