1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
|
# -*- coding: utf-8 -*-
try:
from xml.etree import ElementTree as ET
except ImportError:
pass
def dict2xml(d, elementname="element", pretty=True, allow_attributes=True, level=0):
indent = pretty and "\t" * level or ""
xml = []
attributes = []
children = []
if isinstance(d, (dict, list)):
start_tag = []
start_tag.append(indent + "<" + elementname)
if isinstance(d, dict):
for key in d:
value = d[key]
if isinstance(value, (dict, list)) or not allow_attributes:
children.append(
dict2xml(value, key, pretty, allow_attributes, level + 1)
)
else:
if pretty:
attributes.append("\n" + indent)
attributes.append(' %s="%s"' % (key, escape(str(value))))
else:
for value in d:
children.append(
dict2xml(value, "item", pretty, allow_attributes, level + 1)
)
start_tag.extend(attributes)
start_tag.append(children and ">" or "/>")
xml.append("".join(start_tag))
if children:
for child in children:
xml.append(child)
xml.append("%s</%s>" % (indent, elementname))
else:
xml.append("%s<%s>%s</%s>" % (indent, elementname, escape(str(d)), elementname))
return (pretty and "\n" or "").join(xml)
def escape(xml):
return (
xml.replace("&", "&")
.replace("<", "<")
.replace(">", ">")
.replace('"', """)
)
class ETreeDict(dict):
# Roughly follow "Converting Between XML and JSON"
# https://www.xml.com/pub/a/2006/05/31/converting-between-xml-and-json.html
def __init__(self, etree):
super(ETreeDict, self).__init__()
children = len(etree)
if etree.attrib or etree.text or children:
self[etree.tag] = dict(("@" + k, v) for k, v in etree.attrib.items())
if etree.text:
text = etree.text.strip()
if etree.attrib or children:
if text:
self[etree.tag]["#text"] = text
else:
self[etree.tag] = text
if children:
d = self[etree.tag]
for child in etree:
for k, v in ETreeDict(child).items():
if k in d:
if not isinstance(d[k], list):
d[k] = [d[k]]
d[k].append(v)
else:
d[k] = v
else:
self[etree.tag] = None
def __repr__(self):
"""od.__repr__() <==> repr(od)"""
l = []
for k in self:
v = self[k]
l.append("%r: %r" % (k, v))
return "{%s}" % ", ".join(l)
@property
def json(self):
import json
return json.dumps(self)
class XMLDict(ETreeDict):
def __init__(self, xml):
etree = ET.fromstring(xml)
ETreeDict.__init__(self, etree)
|