2 # -*- coding: utf-8 -*-
3 #################################################################################
4 # POLYMERAZE XML UTILITIES
5 #################################################################################
8 # Utilities to deal with xml nodes.
11 # (c) 2005 - 2008 Gunnar Wrobel
12 # Distributed under the terms of the GNU General Public License v2
15 # Gunnar Wrobel <wrobel@gentoo.org>
18 '''Utility functions to deal with xml nodes. '''
20 __version__
= '$Id: utils.py 236 2006-09-05 20:39:37Z wrobel $'
22 #===============================================================================
26 #-------------------------------------------------------------------------------
30 #===============================================================================
34 #-------------------------------------------------------------------------------
36 def node_to_text(node
):
38 Reduces an xml node to its text elements. The function does not
39 collect the text nodes recursively.
41 >>> import xml.dom.minidom
42 >>> imp = xml.dom.minidom.getDOMImplementation()
43 >>> doc = imp.createDocument('test', 'root', None)
44 >>> root = doc.childNodes[0]
45 >>> node = doc.createTextNode('text')
46 >>> a = root.appendChild(node)
47 >>> node = doc.createElement('text')
48 >>> node2 = doc.createTextNode('text')
49 >>> a = node.appendChild(node2)
50 >>> a = root.appendChild(node)
51 >>> node = doc.createTextNode('text')
52 >>> a = root.appendChild(node)
53 >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS
54 '<?xml version="1.0" ?>...<root>text<text>text</text>text</root>'
56 >>> node_to_text(root)
62 for child
in node
.childNodes
:
63 if child
.nodeType
== child
.TEXT_NODE
:
64 text
= text
+ child
.data
68 def node_to_dict(node
):
69 ''' Converts a xml node to a dictionary. The function collects the
70 nodes recursively. Attributes will be prepended with '&', child
71 nodes will be surrounded with tags. An index will be appended
72 since several child nodes with the same tag may exist. Text
73 elements will be collapsed and stored in a n entry prepended with
74 '@'. Comments will be ignored.
76 >>> import xml.dom.minidom
77 >>> imp = xml.dom.minidom.getDOMImplementation()
78 >>> doc = imp.createDocument('test', 'root', None)
79 >>> root = doc.childNodes[0]
80 >>> node = doc.createTextNode('text')
81 >>> a = root.appendChild(node)
82 >>> node = doc.createElement('text')
83 >>> node2 = doc.createTextNode('text')
84 >>> comm = doc.createComment('comment')
85 >>> attr = doc.createAttribute('&attr')
86 >>> a = node.appendChild(node2)
87 >>> a = root.appendChild(comm)
88 >>> node.setAttributeNode(attr)
89 >>> node.setAttribute('&attr','test')
90 >>> a = root.appendChild(node)
91 >>> node3 = doc.createElement('text')
92 >>> a = root.appendChild(node3)
93 >>> node = doc.createTextNode('text')
94 >>> a = root.appendChild(node)
95 >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS
96 '<?xml version="1.0" ?>...<root>text<!--comment--><text &attr="test">text</text><text/>text</root>'
98 >>> node_to_dict(root)
99 {'<text>1': {'@': 'text', '&&attr': 'test'}, '<text>2': {'@': ''}, '@': 'texttext'}
105 for index
in range(0, node
.attributes
.length
):
106 attr
= node
.attributes
.item(index
)
107 result
['&' + attr
.name
] = attr
.nodeValue
112 for child
in node
.childNodes
:
113 if child
.nodeType
== child
.TEXT_NODE
:
114 text
= text
+ child
.data
115 if child
.nodeType
== child
.ELEMENT_NODE
:
117 while ('<' + child
.tagName
+ '>' + str(index
)) in result
.keys():
119 result
['<' + child
.tagName
+ '>' + str(index
)] = node_to_dict(child
)
125 def dict_to_node(data
, document
, root_name
):
126 ''' Reverts the node_to_dict operation.
128 >>> import xml.dom.minidom
129 >>> imp = xml.dom.minidom.getDOMImplementation()
130 >>> doc = imp.createDocument('test', 'root', None)
131 >>> a = {'<text>1': {'@': 'text', '&&attr': 'test'}, '<text>2': {'@': ''}, '@': 'texttext'}
132 >>> doc.childNodes[0] = dict_to_node(a, doc, 'root')
133 >>> doc.toprettyxml('', '') #doctest: +ELLIPSIS
134 '<?xml version="1.0" ?>...<root><text &attr="test">text</text><text></text>texttext</root>'
137 node
= document
.createElement(root_name
)
139 for i
, j
in data
.items():
142 attr
= document
.createAttribute(i
[1:])
143 node
.setAttributeNode(attr
)
144 node
.setAttribute(i
[1:], j
)
147 while k
[-1] in '0123456789':
149 child
= dict_to_node(data
[i
],
152 node
.appendChild(child
)
154 child
= document
.createTextNode(j
)
155 node
.appendChild(child
)
159 def path(path_elements
):
161 Concatenate a path from several elements.
171 >>> path(['/a/','b'])
173 >>> path(['/a/','b/'])
175 >>> path(['/a/','b/'])
177 >>> path(['/a/','/b/'])
179 >>> path(['/a/','/b','c/'])
184 if type(path_elements
) in types
.StringTypes
:
185 path_elements
= [path_elements
]
187 # Concatenate elements and seperate with /
188 for i
in path_elements
:
191 # Replace multiple consecutive slashes
192 pathname
= re
.compile('/+').sub('/', pathname
)
194 # Remove the final / if there is one
195 if pathname
and pathname
[-1] == '/':
196 pathname
= pathname
[:-1]
200 #===============================================================================
204 #-------------------------------------------------------------------------------
206 if __name__
== '__main__':
208 doctest
.testmod(sys
.modules
[__name__
])