Source code for spyne.util.etreeconv
#
# spyne - Copyright (C) Spyne contributors.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
#
"""This module contains the utility methods that convert an ElementTree
hierarchy to python dicts and vice versa.
"""
import collections
from spyne.util import six
from lxml import etree
from spyne.util.odict import odict
def root_dict_to_etree(d):
[docs] """Converts a dictionary to an xml hiearchy. Just like a valid xml document,
the dictionary must have a single element. The format of the child
dictionaries is the same as :func:`dict_to_etree`.
"""
assert len(d) == 1
key, = d.keys()
retval = etree.Element(key)
for val in d.values():
break
if val is None:
return retval
if isinstance(val, dict) or isinstance(val, odict):
dict_to_etree(val, retval)
elif not isinstance(val, collections.Sized) or isinstance(val, six.string_types):
retval.text=str(val)
else:
for a in val:
dict_to_etree(a, retval)
return retval
def dict_to_etree(d, parent):
[docs] """Takes a the dict whose value is either None or an instance of dict, odict
or an iterable. The iterables can contain either other dicts/odicts or
str/unicode instances.
"""
for k, v in d.items():
if v is None:
etree.SubElement(parent, k)
elif isinstance(v, six.string_types):
etree.SubElement(parent, k).text = v
elif isinstance(v, dict) or isinstance(v, odict):
child = etree.SubElement(parent, k)
dict_to_etree(v, child)
elif not isinstance(v, collections.Sized):
etree.SubElement(parent, k).text = str(v)
elif len(v) == 0:
etree.SubElement(parent, k)
else:
for e in v:
child=etree.SubElement(parent, k)
if isinstance(e, dict) or isinstance(e, odict):
dict_to_etree(e, child)
else:
child.text=str(e)
def root_etree_to_dict(element, iterable=(list, list.append)):
[docs] """Takes an xml root element and returns the corresponding dict. The second
argument is a pair of iterable type and the function used to add elements to
the iterable. The xml attributes are ignored.
"""
return {element.tag: iterable[0]([etree_to_dict(element, iterable)])}
def etree_to_dict(element, iterable=(list, list.append)):
[docs] """Takes an xml root element and returns the corresponding dict. The second
argument is a pair of iterable type and the function used to add elements to
the iterable. The xml attributes are ignored.
"""
if (element.text is None) or element.text.isspace():
retval = odict()
for elt in element:
if not (elt.tag in retval):
retval[elt.tag] = iterable[0]()
iterable[1](retval[elt.tag], etree_to_dict(elt, iterable))
else:
retval = element.text
return retval
def etree_strip_namespaces(element):
[docs] """Removes any namespace information form the given element recursively."""
retval = etree.Element(element.tag.rpartition('}')[-1])
retval.text = element.text
for a in element.attrib:
retval.attrib[a.rpartition('}')[-1]] = element.attrib[a]
for e in element:
retval.append(etree_strip_namespaces(e))
return retval