Source code for sunpy.util.xml

"""XML helper functions"""

from __future__ import absolute_import, division, print_function

from xml.dom.minidom import parseString #pylint: disable=E0611,F0401

__all__ = ['NotTextNodeError', 'xml_to_dict', 'node_to_dict', 'get_node_text']

#
# Converting XML to a Dictionary
# Author: Christoph Dietze
# URL   : http://code.activestate.com/recipes/116539/
#
[docs]class NotTextNodeError(Exception): pass
[docs]def xml_to_dict(xmlstring): """ Converts an XML string to a Python dictionary .. Warning:: This method does not support multiple inner nodes of the same name but with different values. It always takes the last value. Examples -------- :: <outer> <inner>one</inner> <inner>two</inner> </outer> gives you the dict:: {u'outer': {u'inner': u'two'}} """ return node_to_dict(parseString(xmlstring))
[docs]def node_to_dict(node): """ node_to_dict() scans through the children of node and makes a dictionary from the content. Three cases are differentiated: 1. If the node contains no other nodes, it is a text-node and {nodeName: text} is merged into the dictionary. 2. If the node has the attribute "method" set to "true", then it's children will be appended to a list and this list is merged to the dictionary in the form: {nodeName:list}. 3. Else, node_to_dict() will call itself recursively on the nodes children (merging {nodeName: node_to_dict()} to the dictionary). """ dic = {} for n in node.childNodes: if n.nodeType != n.ELEMENT_NODE: continue if n.getAttribute("multiple") == "true": # node with multiple children: put them in a list l = [] for c in n.childNodes: if c.nodeType != n.ELEMENT_NODE: continue l.append(node_to_dict(c)) dic.update({n.nodeName: l}) continue try: text = get_node_text(n) except NotTextNodeError: # 'normal' node dic.update({n.nodeName: node_to_dict(n)}) continue # text node dic.update({n.nodeName: text}) continue return dic
[docs]def get_node_text(node): """ scans through all children of node and gathers the text. if node has non-text child-nodes, then NotTextNodeError is raised. """ t = "" for n in node.childNodes: if n.nodeType == n.TEXT_NODE: t += n.nodeValue else: raise NotTextNodeError return t