Revision 840
Added by Aaron Marcuse-Kubitza almost 13 years ago
lib/xml_dom.py | ||
---|---|---|
8 | 8 |
import strings |
9 | 9 |
import util |
10 | 10 |
|
11 |
##### Escaping input |
|
12 |
|
|
11 | 13 |
def escape(str_): |
12 | 14 |
return strings.to_unicode(cgi.escape(str_, True)).encode('ascii', |
13 | 15 |
'xmlcharrefreplace') |
14 | 16 |
|
15 | 17 |
def unescape(str_): return HTMLParser().unescape(str_) |
16 | 18 |
|
17 |
##### |
|
19 |
##### IDs
|
|
18 | 20 |
|
19 | 21 |
def get_id(node): return node.getAttribute('id') |
20 | 22 |
|
21 | 23 |
def set_id(node, id_): node.setAttribute('id', id_) |
22 | 24 |
|
23 |
##### |
|
25 |
##### Element node contents
|
|
24 | 26 |
|
27 |
def is_elem(node): return node.nodeType == Node.ELEMENT_NODE |
|
28 |
|
|
25 | 29 |
def is_completely_empty(node): return node.firstChild == None |
26 | 30 |
|
27 | 31 |
def has_one_child(node): |
28 | 32 |
return node.firstChild != None and node.firstChild.nextSibling == None |
29 | 33 |
|
34 |
def is_simple(node): |
|
35 |
'''Whether every child recursively has no more than one child''' |
|
36 |
return (not is_elem(node) or is_completely_empty(node) |
|
37 |
or (has_one_child(node) and is_simple(node.firstChild))) |
|
38 |
|
|
30 | 39 |
class NodeIter: |
31 | 40 |
def __init__(self, node): self.child = node.firstChild |
32 | 41 |
|
... | ... | |
41 | 50 |
self.child = self.child.nextSibling |
42 | 51 |
return child |
43 | 52 |
|
44 |
##### |
|
53 |
##### Comments
|
|
45 | 54 |
|
46 | 55 |
def is_comment(node): return node.nodeType == Node.COMMENT_NODE |
47 | 56 |
|
... | ... | |
50 | 59 |
if not is_comment(child): return False |
51 | 60 |
return True |
52 | 61 |
|
53 |
##### |
|
62 |
##### Child nodes that are elements
|
|
54 | 63 |
|
55 |
def is_elem(node): return node.nodeType == Node.ELEMENT_NODE |
|
56 |
|
|
57 | 64 |
class NodeElemIter: |
58 | 65 |
def __init__(self, node): self.child = node.firstChild |
59 | 66 |
|
... | ... | |
94 | 101 |
|
95 | 102 |
def last_elem(node): return NodeElemReverseIter(node).next() |
96 | 103 |
|
104 |
##### Parent nodes |
|
105 |
|
|
97 | 106 |
class NodeParentIter: |
98 | 107 |
def __init__(self, node): self.node = node |
99 | 108 |
|
... | ... | |
108 | 117 |
self.node = self.node.parentNode |
109 | 118 |
return node |
110 | 119 |
|
111 |
def is_simple(node): |
|
112 |
'''Whether every child recursively has no more than one child''' |
|
113 |
return (not is_elem(node) or is_completely_empty(node) |
|
114 |
or (has_one_child(node) and is_simple(node.firstChild))) |
|
120 |
##### Element nodes containing text |
|
115 | 121 |
|
116 |
##### |
|
117 |
|
|
118 | 122 |
def is_text_node(node): return node.nodeType == Node.TEXT_NODE |
119 | 123 |
|
120 | 124 |
def is_text(node): return has_one_child(node) and is_text_node(node.firstChild) |
... | ... | |
151 | 155 |
def __init__(self, iterable): |
152 | 156 |
util.CheckedIter.__init__(self, is_text_node_entry, iterable) |
153 | 157 |
|
154 |
##### |
|
158 |
##### Modifying/replacing a node
|
|
155 | 159 |
|
156 | 160 |
def set_child(node, name, value): |
157 | 161 |
'''Note: does not remove any existing child of the same name''' |
... | ... | |
168 | 172 |
if util.is_str(new): new = node.ownerDocument.createTextNode(new) |
169 | 173 |
replace(node, new) |
170 | 174 |
|
171 |
##### |
|
175 |
##### Searching child nodes
|
|
172 | 176 |
|
173 | 177 |
def by_tag_name(node, name, last_only=False): |
174 | 178 |
'''last_only optimization returns last matching node''' |
... | ... | |
179 | 183 |
if last_only: break |
180 | 184 |
return children |
181 | 185 |
|
182 |
##### |
|
186 |
##### XML documents
|
|
183 | 187 |
|
184 | 188 |
def create_doc(root='_'): |
185 | 189 |
return minidom.getDOMImplementation().createDocument(None, root, None) |
186 | 190 |
|
187 |
##### |
|
191 |
##### Printing XML
|
|
188 | 192 |
|
189 | 193 |
prettyxml_config = dict(addindent=' ', newl='\n') |
190 | 194 |
toprettyxml_config = prettyxml_config.copy() |
191 | 195 |
util.rename_key(toprettyxml_config, 'addindent', 'indent') |
192 | 196 |
|
193 |
##### |
|
197 |
##### minidom modifications
|
|
194 | 198 |
|
195 |
# minidom modifications |
|
196 |
|
|
197 | 199 |
minidom._write_data = lambda writer, data: writer.write(escape(data)) |
198 | 200 |
|
199 | 201 |
minidom.Node.__iter__ = lambda self: NodeIter(self) |
Also available in: Unified diff
xml_dom.py: Added documentation labels to each section