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