]> git.evergreen-ils.org Git - OpenSRF.git/blob - src/python/osrf/xml_obj.py
Move towards Pythonic API style conventions (as informed by pylint)
[OpenSRF.git] / src / python / osrf / xml_obj.py
1 import xml.dom.minidom
2
3 def xml_file_to_object(filename):
4     """Turns the contents of an XML file into a Python object"""
5     doc = xml.dom.minidom.parse(filename)
6     obj = xml_node_to_object(doc.documentElement)
7     doc.unlink()
8     return obj
9
10 def xml_string_to_object(string):
11     """Turns an XML string into a Python object"""
12     doc = xml.dom.minidom.parseString(string)
13     obj = xml_node_to_object(doc.documentElement)
14     doc.unlink()
15     return obj
16
17 def xml_node_to_object(xml_node):
18     """Turns an XML node into a Python object"""
19     obj = {}
20
21     if xml_node.nodeType != xml_node.ELEMENT_NODE:
22         return obj
23
24     done = False
25     node_name = xml_node.nodeName
26
27     for node_child in xml_node.childNodes:
28         if node_child.nodeType == xml_node.ELEMENT_NODE:
29             sub_obj = xml_node_to_object(node_child)
30             __append_child_node(obj, node_name, node_child.nodeName, sub_obj)
31             done = True
32
33     for attr in xml_node.attributes.values():
34         __append_child_node(obj, node_name, attr.name,
35             dict([(attr.name, attr.value)]))
36         
37
38     if not done and len(xml_node.childNodes) > 0:
39         # If the node has no element children, clean up the text 
40         # content and use that as the data
41         text_node = xml_node.childNodes[0] # extract the text node
42         data = unicode(text_node.nodeValue).replace('^\s*','')
43         data = data.replace('\s*$','')
44
45         if node_name in obj:
46             # the current element contains attributes and text
47             obj[node_name]['#text'] = data
48         else:
49             # the current element contains text only
50             obj[node_name] = data
51
52     return obj
53
54
55 def __append_child_node(obj, node_name, child_name, sub_obj):
56     """ If a node has element children, create a new sub-object 
57         for this node, attach an array for each type of child
58         and recursively collect the children data into the array(s) """
59
60     if not obj.has_key(node_name):
61         obj[node_name] = {}
62
63     if not obj[node_name].has_key(child_name):
64         # we've encountered 1 sub-node with node_child's name
65         if child_name in sub_obj:
66             obj[node_name][child_name] = sub_obj[child_name]
67         else:
68             obj[node_name][child_name] = None
69
70     else:
71         if isinstance(obj[node_name][child_name], list):
72             # we already have multiple sub-nodes with node_child's name
73             obj[node_name][child_name].append(sub_obj[child_name])
74
75         else:
76             # we already have 1 sub-node with node_child's name, make 
77             # it a list and append the current node
78             val = obj[node_name][child_name]
79             obj[node_name][child_name] = [ val, sub_obj[child_name] ]
80
81