blob: cb84987714d44321ec4b1c0b00e6fe28ba80d340 [file] [log] [blame]
Fred Drake17647f52000-07-03 16:37:42 +00001# test for xml.dom.minidom
Paul Prescod7993bcc2000-07-01 14:54:16 +00002
Guido van Rossume2ae77b2001-10-24 20:42:55 +00003import os
Fred Drake17647f52000-07-03 16:37:42 +00004import sys
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +00005import pickle
Fred Drake17647f52000-07-03 16:37:42 +00006import traceback
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +00007from StringIO import StringIO
Barry Warsaw04f357c2002-07-23 19:04:11 +00008from test.test_support import verbose
Fred Drake17647f52000-07-03 16:37:42 +00009
Fred Drakec441f7b2002-07-19 22:16:41 +000010import xml.dom
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +000011import xml.dom.minidom
Fred Drakec441f7b2002-07-19 22:16:41 +000012import xml.parsers.expat
13
14from xml.dom.minidom import parse, Node, Document, parseString
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +000015from xml.dom.minidom import getDOMImplementation
16
Fred Drakec441f7b2002-07-19 22:16:41 +000017
Fred Drake17647f52000-07-03 16:37:42 +000018if __name__ == "__main__":
19 base = sys.argv[0]
20else:
21 base = __file__
Guido van Rossume2ae77b2001-10-24 20:42:55 +000022tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml")
Fred Drake17647f52000-07-03 16:37:42 +000023del base
Paul Prescod7993bcc2000-07-01 14:54:16 +000024
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000025def confirm(test, testname = "Test"):
Fred Drakec441f7b2002-07-19 22:16:41 +000026 if not test:
Paul Prescod10d27662000-09-18 19:07:26 +000027 print "Failed " + testname
28 raise Exception
29
Paul Prescod10d27662000-09-18 19:07:26 +000030def testParseFromFile():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000031 dom = parse(StringIO(open(tstfile).read()))
Paul Prescod4c799192000-09-19 19:33:02 +000032 dom.unlink()
Martin v. Löwis89c528b2000-09-19 16:22:10 +000033 confirm(isinstance(dom,Document))
Paul Prescod10d27662000-09-18 19:07:26 +000034
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000035def testGetElementsByTagName():
36 dom = parse(tstfile)
37 confirm(dom.getElementsByTagName("LI") == \
38 dom.documentElement.getElementsByTagName("LI"))
Paul Prescod7993bcc2000-07-01 14:54:16 +000039 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +000040
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000041def testInsertBefore():
Fred Drakea1bde802000-11-21 22:02:43 +000042 dom = parseString("<doc><foo/></doc>")
43 root = dom.documentElement
44 elem = root.childNodes[0]
45 nelem = dom.createElement("element")
46 root.insertBefore(nelem, elem)
47 confirm(len(root.childNodes) == 2
Fred Drake946f7b12001-09-28 20:31:50 +000048 and root.childNodes.length == 2
Fred Drakea1bde802000-11-21 22:02:43 +000049 and root.childNodes[0] is nelem
Fred Drake946f7b12001-09-28 20:31:50 +000050 and root.childNodes.item(0) is nelem
Fred Drakea1bde802000-11-21 22:02:43 +000051 and root.childNodes[1] is elem
Fred Drake946f7b12001-09-28 20:31:50 +000052 and root.childNodes.item(1) is elem
Fred Drakea1bde802000-11-21 22:02:43 +000053 and root.firstChild is nelem
54 and root.lastChild is elem
55 and root.toxml() == "<doc><element/><foo/></doc>"
56 , "testInsertBefore -- node properly placed in tree")
57 nelem = dom.createElement("element")
58 root.insertBefore(nelem, None)
59 confirm(len(root.childNodes) == 3
Fred Drake946f7b12001-09-28 20:31:50 +000060 and root.childNodes.length == 3
Fred Drakea1bde802000-11-21 22:02:43 +000061 and root.childNodes[1] is elem
Fred Drake946f7b12001-09-28 20:31:50 +000062 and root.childNodes.item(1) is elem
Fred Drakea1bde802000-11-21 22:02:43 +000063 and root.childNodes[2] is nelem
Fred Drake946f7b12001-09-28 20:31:50 +000064 and root.childNodes.item(2) is nelem
Fred Drakea1bde802000-11-21 22:02:43 +000065 and root.lastChild is nelem
66 and nelem.previousSibling is elem
67 and root.toxml() == "<doc><element/><foo/><element/></doc>"
68 , "testInsertBefore -- node properly placed in tree")
69 nelem2 = dom.createElement("bar")
70 root.insertBefore(nelem2, nelem)
71 confirm(len(root.childNodes) == 4
Fred Drake946f7b12001-09-28 20:31:50 +000072 and root.childNodes.length == 4
Fred Drakea1bde802000-11-21 22:02:43 +000073 and root.childNodes[2] is nelem2
Fred Drake946f7b12001-09-28 20:31:50 +000074 and root.childNodes.item(2) is nelem2
Fred Drakea1bde802000-11-21 22:02:43 +000075 and root.childNodes[3] is nelem
Fred Drake946f7b12001-09-28 20:31:50 +000076 and root.childNodes.item(3) is nelem
Fred Drakea1bde802000-11-21 22:02:43 +000077 and nelem2.nextSibling is nelem
78 and nelem.previousSibling is nelem2
79 and root.toxml() == "<doc><element/><foo/><bar/><element/></doc>"
80 , "testInsertBefore -- node properly placed in tree")
Paul Prescod7993bcc2000-07-01 14:54:16 +000081 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +000082
Fred Drakee50959a2001-12-06 04:32:18 +000083def _create_fragment_test_nodes():
84 dom = parseString("<doc/>")
85 orig = dom.createTextNode("original")
86 c1 = dom.createTextNode("foo")
87 c2 = dom.createTextNode("bar")
88 c3 = dom.createTextNode("bat")
89 dom.documentElement.appendChild(orig)
90 frag = dom.createDocumentFragment()
91 frag.appendChild(c1)
92 frag.appendChild(c2)
93 frag.appendChild(c3)
94 return dom, orig, c1, c2, c3, frag
95
96def testInsertBeforeFragment():
97 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
98 dom.documentElement.insertBefore(frag, None)
99 confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
100 "insertBefore(<fragment>, None)")
101 frag.unlink()
102 dom.unlink()
103 #
104 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
105 dom.documentElement.insertBefore(frag, orig)
106 confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig),
107 "insertBefore(<fragment>, orig)")
108 frag.unlink()
109 dom.unlink()
110
Paul Prescod7993bcc2000-07-01 14:54:16 +0000111def testAppendChild():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000112 dom = parse(tstfile)
113 dom.documentElement.appendChild(dom.createComment(u"Hello"))
114 confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
115 confirm(dom.documentElement.childNodes[-1].data == "Hello")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000116 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000117
Fred Drakee50959a2001-12-06 04:32:18 +0000118def testAppendChildFragment():
119 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
120 dom.documentElement.appendChild(frag)
121 confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
122 "appendChild(<fragment>)")
123 frag.unlink()
124 dom.unlink()
125
126def testReplaceChildFragment():
127 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
128 dom.documentElement.replaceChild(frag, orig)
129 orig.unlink()
130 confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
131 "replaceChild(<fragment>)")
132 frag.unlink()
133 dom.unlink()
134
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000135def testLegalChildren():
136 dom = Document()
137 elem = dom.createElement('element')
138 text = dom.createTextNode('text')
Fredrik Lundhf7850422001-01-17 21:51:36 +0000139
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000140 try: dom.appendChild(text)
Fred Drakec441f7b2002-07-19 22:16:41 +0000141 except xml.dom.HierarchyRequestErr: pass
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000142 else:
143 print "dom.appendChild didn't raise HierarchyRequestErr"
144
145 dom.appendChild(elem)
146 try: dom.insertBefore(text, elem)
Fred Drakec441f7b2002-07-19 22:16:41 +0000147 except xml.dom.HierarchyRequestErr: pass
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000148 else:
149 print "dom.appendChild didn't raise HierarchyRequestErr"
150
151 try: dom.replaceChild(text, elem)
Fred Drakec441f7b2002-07-19 22:16:41 +0000152 except xml.dom.HierarchyRequestErr: pass
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000153 else:
154 print "dom.appendChild didn't raise HierarchyRequestErr"
155
Tim Peters0009c4e2001-02-21 07:29:48 +0000156 nodemap = elem.attributes
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000157 try: nodemap.setNamedItem(text)
Fred Drakec441f7b2002-07-19 22:16:41 +0000158 except xml.dom.HierarchyRequestErr: pass
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000159 else:
160 print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr"
161
162 try: nodemap.setNamedItemNS(text)
Fred Drakec441f7b2002-07-19 22:16:41 +0000163 except xml.dom.HierarchyRequestErr: pass
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000164 else:
165 print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr"
166
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000167 elem.appendChild(text)
Fredrik Lundhf7850422001-01-17 21:51:36 +0000168 dom.unlink()
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000169
Fred Drake2998a552001-12-06 18:27:48 +0000170def testNamedNodeMapSetItem():
171 dom = Document()
172 elem = dom.createElement('element')
173 attrs = elem.attributes
174 attrs["foo"] = "bar"
175 a = attrs.item(0)
176 confirm(a.ownerDocument is dom,
177 "NamedNodeMap.__setitem__() sets ownerDocument")
178 confirm(a.ownerElement is elem,
179 "NamedNodeMap.__setitem__() sets ownerElement")
180 confirm(a.value == "bar",
181 "NamedNodeMap.__setitem__() sets value")
182 confirm(a.nodeValue == "bar",
183 "NamedNodeMap.__setitem__() sets nodeValue")
184 elem.unlink()
185 dom.unlink()
186
Paul Prescod7993bcc2000-07-01 14:54:16 +0000187def testNonZero():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000188 dom = parse(tstfile)
189 confirm(dom)# should not be zero
190 dom.appendChild(dom.createComment("foo"))
191 confirm(not dom.childNodes[-1].childNodes)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000192 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000193
194def testUnlink():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000195 dom = parse(tstfile)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000196 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000197
198def testElement():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000199 dom = Document()
200 dom.appendChild(dom.createElement("abc"))
201 confirm(dom.documentElement)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000202 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000203
204def testAAA():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000205 dom = parseString("<abc/>")
206 el = dom.documentElement
207 el.setAttribute("spam", "jam2")
Fred Drakea1bde802000-11-21 22:02:43 +0000208 confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
Fred Drake2998a552001-12-06 18:27:48 +0000209 a = el.getAttributeNode("spam")
210 confirm(a.ownerDocument is dom,
211 "setAttribute() sets ownerDocument")
212 confirm(a.ownerElement is dom.documentElement,
213 "setAttribute() sets ownerElement")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000214 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000215
216def testAAB():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000217 dom = parseString("<abc/>")
218 el = dom.documentElement
219 el.setAttribute("spam", "jam")
220 el.setAttribute("spam", "jam2")
Fred Drakea1bde802000-11-21 22:02:43 +0000221 confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000222 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000223
224def testAddAttr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000225 dom = Document()
226 child = dom.appendChild(dom.createElement("abc"))
Paul Prescod7993bcc2000-07-01 14:54:16 +0000227
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000228 child.setAttribute("def", "ghi")
229 confirm(child.getAttribute("def") == "ghi")
230 confirm(child.attributes["def"].value == "ghi")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000231
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000232 child.setAttribute("jkl", "mno")
233 confirm(child.getAttribute("jkl") == "mno")
234 confirm(child.attributes["jkl"].value == "mno")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000235
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000236 confirm(len(child.attributes) == 2)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000237
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000238 child.setAttribute("def", "newval")
239 confirm(child.getAttribute("def") == "newval")
240 confirm(child.attributes["def"].value == "newval")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000241
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000242 confirm(len(child.attributes) == 2)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000243 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000244
245def testDeleteAttr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000246 dom = Document()
247 child = dom.appendChild(dom.createElement("abc"))
Paul Prescod7993bcc2000-07-01 14:54:16 +0000248
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000249 confirm(len(child.attributes) == 0)
250 child.setAttribute("def", "ghi")
251 confirm(len(child.attributes) == 1)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000252 del child.attributes["def"]
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000253 confirm(len(child.attributes) == 0)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000254 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000255
256def testRemoveAttr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000257 dom = Document()
258 child = dom.appendChild(dom.createElement("abc"))
Paul Prescod7993bcc2000-07-01 14:54:16 +0000259
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000260 child.setAttribute("def", "ghi")
261 confirm(len(child.attributes) == 1)
262 child.removeAttribute("def")
263 confirm(len(child.attributes) == 0)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000264
265 dom.unlink()
266
267def testRemoveAttrNS():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000268 dom = Document()
269 child = dom.appendChild(
270 dom.createElementNS("http://www.python.org", "python:abc"))
Fred Drake004d5e62000-10-23 17:22:08 +0000271 child.setAttributeNS("http://www.w3.org", "xmlns:python",
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000272 "http://www.python.org")
273 child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
274 confirm(len(child.attributes) == 2)
275 child.removeAttributeNS("http://www.python.org", "abcattr")
276 confirm(len(child.attributes) == 1)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000277
278 dom.unlink()
Fred Drake004d5e62000-10-23 17:22:08 +0000279
Paul Prescod7993bcc2000-07-01 14:54:16 +0000280def testRemoveAttributeNode():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000281 dom = Document()
282 child = dom.appendChild(dom.createElement("foo"))
283 child.setAttribute("spam", "jam")
284 confirm(len(child.attributes) == 1)
285 node = child.getAttributeNode("spam")
286 child.removeAttributeNode(node)
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000287 confirm(len(child.attributes) == 0
288 and child.getAttributeNode("spam") is None)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000289
290 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000291
292def testChangeAttr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000293 dom = parseString("<abc/>")
294 el = dom.documentElement
295 el.setAttribute("spam", "jam")
296 confirm(len(el.attributes) == 1)
297 el.setAttribute("spam", "bam")
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000298 # Set this attribute to be an ID and make sure that doesn't change
299 # when changing the value:
300 el.setIdAttribute("spam")
301 confirm(len(el.attributes) == 1
302 and el.attributes["spam"].value == "bam"
303 and el.attributes["spam"].nodeValue == "bam"
304 and el.getAttribute("spam") == "bam"
305 and el.getAttributeNode("spam").isId)
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000306 el.attributes["spam"] = "ham"
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000307 confirm(len(el.attributes) == 1
308 and el.attributes["spam"].value == "ham"
309 and el.attributes["spam"].nodeValue == "ham"
310 and el.getAttribute("spam") == "ham"
311 and el.attributes["spam"].isId)
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000312 el.setAttribute("spam2", "bam")
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000313 confirm(len(el.attributes) == 2
314 and el.attributes["spam"].value == "ham"
315 and el.attributes["spam"].nodeValue == "ham"
316 and el.getAttribute("spam") == "ham"
317 and el.attributes["spam2"].value == "bam"
318 and el.attributes["spam2"].nodeValue == "bam"
319 and el.getAttribute("spam2") == "bam")
320 el.attributes["spam2"] = "bam2"
321 confirm(len(el.attributes) == 2
322 and el.attributes["spam"].value == "ham"
323 and el.attributes["spam"].nodeValue == "ham"
324 and el.getAttribute("spam") == "ham"
325 and el.attributes["spam2"].value == "bam2"
326 and el.attributes["spam2"].nodeValue == "bam2"
327 and el.getAttribute("spam2") == "bam2")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000328 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000329
330def testGetAttrList():
331 pass
332
333def testGetAttrValues(): pass
334
335def testGetAttrLength(): pass
336
337def testGetAttribute(): pass
338
339def testGetAttributeNS(): pass
340
341def testGetAttributeNode(): pass
342
Martin v. Löwis351c3d02001-06-03 14:27:02 +0000343def testGetElementsByTagNameNS():
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000344 d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
Martin v. Löwis351c3d02001-06-03 14:27:02 +0000345 <minidom:myelem/>
346 </foo>"""
347 dom = parseString(d)
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000348 elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", "myelem")
349 confirm(len(elems) == 1
350 and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"
351 and elems[0].localName == "myelem"
352 and elems[0].prefix == "minidom"
353 and elems[0].tagName == "minidom:myelem"
354 and elems[0].nodeName == "minidom:myelem")
Martin v. Löwis351c3d02001-06-03 14:27:02 +0000355 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000356
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000357def get_empty_nodelist_from_elements_by_tagName_ns_helper(doc, nsuri, lname):
358 nodelist = doc.getElementsByTagNameNS(nsuri, lname)
359 confirm(len(nodelist) == 0)
360
361def testGetEmptyNodeListFromElementsByTagNameNS():
362 doc = parseString('<doc/>')
363 get_empty_nodelist_from_elements_by_tagName_ns_helper(
364 doc, 'http://xml.python.org/namespaces/a', 'localname')
365 get_empty_nodelist_from_elements_by_tagName_ns_helper(
366 doc, '*', 'splat')
367 get_empty_nodelist_from_elements_by_tagName_ns_helper(
368 doc, 'http://xml.python.org/namespaces/a', '*')
369
370 doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
371 get_empty_nodelist_from_elements_by_tagName_ns_helper(
372 doc, "http://xml.python.org/splat", "not-there")
373 get_empty_nodelist_from_elements_by_tagName_ns_helper(
374 doc, "*", "not-there")
375 get_empty_nodelist_from_elements_by_tagName_ns_helper(
376 doc, "http://somewhere.else.net/not-there", "e")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000377
378def testElementReprAndStr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000379 dom = Document()
380 el = dom.appendChild(dom.createElement("abc"))
381 string1 = repr(el)
382 string2 = str(el)
383 confirm(string1 == string2)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000384 dom.unlink()
385
386# commented out until Fredrick's fix is checked in
387def _testElementReprAndStrUnicode():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000388 dom = Document()
389 el = dom.appendChild(dom.createElement(u"abc"))
390 string1 = repr(el)
391 string2 = str(el)
392 confirm(string1 == string2)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000393 dom.unlink()
394
395# commented out until Fredrick's fix is checked in
396def _testElementReprAndStrUnicodeNS():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000397 dom = Document()
398 el = dom.appendChild(
399 dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
400 string1 = repr(el)
401 string2 = str(el)
402 confirm(string1 == string2)
403 confirm(string1.find("slash:abc") != -1)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000404 dom.unlink()
405
406def testAttributeRepr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000407 dom = Document()
408 el = dom.appendChild(dom.createElement(u"abc"))
409 node = el.setAttribute("abc", "def")
410 confirm(str(node) == repr(node))
Paul Prescod7993bcc2000-07-01 14:54:16 +0000411 dom.unlink()
412
413def testTextNodeRepr(): pass
414
Martin v. Löwis0a84a332000-10-06 22:42:55 +0000415def testWriteXML():
Martin v. Löwisfe28ca02001-02-06 01:16:48 +0000416 str = '<?xml version="1.0" ?>\n<a b="c"/>'
Martin v. Löwis0a84a332000-10-06 22:42:55 +0000417 dom = parseString(str)
418 domstr = dom.toxml()
419 dom.unlink()
420 confirm(str == domstr)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000421
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000422def testProcessingInstruction():
423 dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
424 pi = dom.documentElement.firstChild
425 confirm(pi.target == "mypi"
426 and pi.data == "data \t\n "
427 and pi.nodeName == "mypi"
428 and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
429 and pi.attributes is None
430 and not pi.hasChildNodes()
431 and len(pi.childNodes) == 0
432 and pi.firstChild is None
433 and pi.lastChild is None
434 and pi.localName is None
435 and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000436
437def testProcessingInstructionRepr(): pass
438
439def testTextRepr(): pass
440
441def testWriteText(): pass
442
443def testDocumentElement(): pass
444
Fred Drakea1bde802000-11-21 22:02:43 +0000445def testTooManyDocumentElements():
446 doc = parseString("<doc/>")
447 elem = doc.createElement("extra")
448 try:
449 doc.appendChild(elem)
Fred Drakec441f7b2002-07-19 22:16:41 +0000450 except xml.dom.HierarchyRequestErr:
451 pass
Fred Drakea1bde802000-11-21 22:02:43 +0000452 else:
453 print "Failed to catch expected exception when" \
454 " adding extra document element."
455 elem.unlink()
456 doc.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000457
458def testCreateElementNS(): pass
459
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000460def testCreateAttributeNS(): pass
Paul Prescod7993bcc2000-07-01 14:54:16 +0000461
462def testParse(): pass
463
464def testParseString(): pass
465
466def testComment(): pass
467
468def testAttrListItem(): pass
469
470def testAttrListItems(): pass
471
472def testAttrListItemNS(): pass
473
474def testAttrListKeys(): pass
475
476def testAttrListKeysNS(): pass
477
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000478def testRemoveNamedItem():
479 doc = parseString("<doc a=''/>")
480 e = doc.documentElement
481 attrs = e.attributes
482 a1 = e.getAttributeNode("a")
483 a2 = attrs.removeNamedItem("a")
484 confirm(a1.isSameNode(a2))
485 try:
486 attrs.removeNamedItem("a")
487 except xml.dom.NotFoundErr:
488 pass
489
490def testRemoveNamedItemNS():
491 doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
492 e = doc.documentElement
493 attrs = e.attributes
494 a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
495 a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
496 confirm(a1.isSameNode(a2))
497 try:
498 attrs.removeNamedItemNS("http://xml.python.org/", "b")
499 except xml.dom.NotFoundErr:
500 pass
501
Paul Prescod7993bcc2000-07-01 14:54:16 +0000502def testAttrListValues(): pass
503
504def testAttrListLength(): pass
505
506def testAttrList__getitem__(): pass
507
508def testAttrList__setitem__(): pass
509
510def testSetAttrValueandNodeValue(): pass
511
512def testParseElement(): pass
513
514def testParseAttributes(): pass
515
516def testParseElementNamespaces(): pass
517
518def testParseAttributeNamespaces(): pass
519
520def testParseProcessingInstructions(): pass
521
522def testChildNodes(): pass
523
524def testFirstChild(): pass
525
526def testHasChildNodes(): pass
527
Fred Drakea1bde802000-11-21 22:02:43 +0000528def testCloneElementShallow():
529 dom, clone = _setupCloneElement(0)
530 confirm(len(clone.childNodes) == 0
Fred Drake946f7b12001-09-28 20:31:50 +0000531 and clone.childNodes.length == 0
Fred Drakea1bde802000-11-21 22:02:43 +0000532 and clone.parentNode is None
533 and clone.toxml() == '<doc attr="value"/>'
534 , "testCloneElementShallow")
535 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000536
Fred Drakea1bde802000-11-21 22:02:43 +0000537def testCloneElementDeep():
538 dom, clone = _setupCloneElement(1)
539 confirm(len(clone.childNodes) == 1
Fred Drake946f7b12001-09-28 20:31:50 +0000540 and clone.childNodes.length == 1
Fred Drakea1bde802000-11-21 22:02:43 +0000541 and clone.parentNode is None
542 and clone.toxml() == '<doc attr="value"><foo/></doc>'
543 , "testCloneElementDeep")
544 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000545
Fred Drakea1bde802000-11-21 22:02:43 +0000546def _setupCloneElement(deep):
547 dom = parseString("<doc attr='value'><foo/></doc>")
548 root = dom.documentElement
549 clone = root.cloneNode(deep)
550 _testCloneElementCopiesAttributes(
551 root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
552 # mutilate the original so shared data is detected
553 root.tagName = root.nodeName = "MODIFIED"
554 root.setAttribute("attr", "NEW VALUE")
555 root.setAttribute("added", "VALUE")
556 return dom, clone
557
558def _testCloneElementCopiesAttributes(e1, e2, test):
559 attrs1 = e1.attributes
560 attrs2 = e2.attributes
561 keys1 = attrs1.keys()
562 keys2 = attrs2.keys()
563 keys1.sort()
564 keys2.sort()
565 confirm(keys1 == keys2, "clone of element has same attribute keys")
566 for i in range(len(keys1)):
567 a1 = attrs1.item(i)
568 a2 = attrs2.item(i)
569 confirm(a1 is not a2
570 and a1.value == a2.value
571 and a1.nodeValue == a2.nodeValue
572 and a1.namespaceURI == a2.namespaceURI
573 and a1.localName == a2.localName
574 , "clone of attribute node has proper attribute values")
575 confirm(a2.ownerElement is e2,
576 "clone of attribute node correctly owned")
Fredrik Lundhf7850422001-01-17 21:51:36 +0000577
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000578def testCloneDocumentShallow():
579 doc = parseString("<?xml version='1.0'?>\n"
580 "<!-- comment -->"
581 "<!DOCTYPE doc [\n"
582 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
583 "]>\n"
584 "<doc attr='value'/>")
585 doc2 = doc.cloneNode(0)
586 confirm(doc2 is None,
587 "testCloneDocumentShallow:"
588 " shallow cloning of documents makes no sense!")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000589
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000590def testCloneDocumentDeep():
591 doc = parseString("<?xml version='1.0'?>\n"
592 "<!-- comment -->"
593 "<!DOCTYPE doc [\n"
594 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
595 "]>\n"
596 "<doc attr='value'/>")
597 doc2 = doc.cloneNode(1)
598 confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
599 "testCloneDocumentDeep: document objects not distinct")
600 confirm(len(doc.childNodes) == len(doc2.childNodes),
601 "testCloneDocumentDeep: wrong number of Document children")
602 confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
603 "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
604 confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
605 "testCloneDocumentDeep: documentElement owner is not new document")
606 confirm(not doc.documentElement.isSameNode(doc2.documentElement),
607 "testCloneDocumentDeep: documentElement should not be shared")
608 if doc.doctype is not None:
609 # check the doctype iff the original DOM maintained it
610 confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
611 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
612 confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
613 confirm(not doc.doctype.isSameNode(doc2.doctype))
Paul Prescod7993bcc2000-07-01 14:54:16 +0000614
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000615def testCloneDocumentTypeDeepOk():
616 doctype = create_nonempty_doctype()
617 clone = doctype.cloneNode(1)
618 confirm(clone is not None
619 and clone.nodeName == doctype.nodeName
620 and clone.name == doctype.name
621 and clone.publicId == doctype.publicId
622 and clone.systemId == doctype.systemId
623 and len(clone.entities) == len(doctype.entities)
624 and clone.entities.item(len(clone.entities)) is None
625 and len(clone.notations) == len(doctype.notations)
626 and clone.notations.item(len(clone.notations)) is None
627 and len(clone.childNodes) == 0)
628 for i in range(len(doctype.entities)):
629 se = doctype.entities.item(i)
630 ce = clone.entities.item(i)
631 confirm((not se.isSameNode(ce))
632 and (not ce.isSameNode(se))
633 and ce.nodeName == se.nodeName
634 and ce.notationName == se.notationName
635 and ce.publicId == se.publicId
636 and ce.systemId == se.systemId
637 and ce.encoding == se.encoding
638 and ce.actualEncoding == se.actualEncoding
639 and ce.version == se.version)
640 for i in range(len(doctype.notations)):
641 sn = doctype.notations.item(i)
642 cn = clone.notations.item(i)
643 confirm((not sn.isSameNode(cn))
644 and (not cn.isSameNode(sn))
645 and cn.nodeName == sn.nodeName
646 and cn.publicId == sn.publicId
647 and cn.systemId == sn.systemId)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000648
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000649def testCloneDocumentTypeDeepNotOk():
650 doc = create_doc_with_doctype()
651 clone = doc.doctype.cloneNode(1)
652 confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000653
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000654def testCloneDocumentTypeShallowOk():
655 doctype = create_nonempty_doctype()
656 clone = doctype.cloneNode(0)
657 confirm(clone is not None
658 and clone.nodeName == doctype.nodeName
659 and clone.name == doctype.name
660 and clone.publicId == doctype.publicId
661 and clone.systemId == doctype.systemId
662 and len(clone.entities) == 0
663 and clone.entities.item(0) is None
664 and len(clone.notations) == 0
665 and clone.notations.item(0) is None
666 and len(clone.childNodes) == 0)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000667
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000668def testCloneDocumentTypeShallowNotOk():
669 doc = create_doc_with_doctype()
670 clone = doc.doctype.cloneNode(0)
671 confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000672
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000673def check_import_document(deep, testName):
674 doc1 = parseString("<doc/>")
675 doc2 = parseString("<doc/>")
676 try:
677 doc1.importNode(doc2, deep)
678 except xml.dom.NotSupportedErr:
679 pass
680 else:
681 raise Exception(testName +
682 ": expected NotSupportedErr when importing a document")
683
684def testImportDocumentShallow():
685 check_import_document(0, "testImportDocumentShallow")
686
687def testImportDocumentDeep():
688 check_import_document(1, "testImportDocumentDeep")
689
690# The tests of DocumentType importing use these helpers to construct
691# the documents to work with, since not all DOM builders actually
692# create the DocumentType nodes.
693
694def create_doc_without_doctype(doctype=None):
695 return getDOMImplementation().createDocument(None, "doc", doctype)
696
697def create_nonempty_doctype():
698 doctype = getDOMImplementation().createDocumentType("doc", None, None)
699 doctype.entities._seq = []
700 doctype.notations._seq = []
701 notation = xml.dom.minidom.Notation("my-notation", None,
702 "http://xml.python.org/notations/my")
703 doctype.notations._seq.append(notation)
704 entity = xml.dom.minidom.Entity("my-entity", None,
705 "http://xml.python.org/entities/my",
706 "my-notation")
707 entity.version = "1.0"
708 entity.encoding = "utf-8"
709 entity.actualEncoding = "us-ascii"
710 doctype.entities._seq.append(entity)
711 return doctype
712
713def create_doc_with_doctype():
714 doctype = create_nonempty_doctype()
715 doc = create_doc_without_doctype(doctype)
716 doctype.entities.item(0).ownerDocument = doc
717 doctype.notations.item(0).ownerDocument = doc
718 return doc
719
720def testImportDocumentTypeShallow():
721 src = create_doc_with_doctype()
722 target = create_doc_without_doctype()
723 try:
724 imported = target.importNode(src.doctype, 0)
725 except xml.dom.NotSupportedErr:
726 pass
727 else:
728 raise Exception(
729 "testImportDocumentTypeShallow: expected NotSupportedErr")
730
731def testImportDocumentTypeDeep():
732 src = create_doc_with_doctype()
733 target = create_doc_without_doctype()
734 try:
735 imported = target.importNode(src.doctype, 1)
736 except xml.dom.NotSupportedErr:
737 pass
738 else:
739 raise Exception(
740 "testImportDocumentTypeDeep: expected NotSupportedErr")
741
742# Testing attribute clones uses a helper, and should always be deep,
743# even if the argument to cloneNode is false.
744def check_clone_attribute(deep, testName):
745 doc = parseString("<doc attr='value'/>")
746 attr = doc.documentElement.getAttributeNode("attr")
747 assert attr is not None
748 clone = attr.cloneNode(deep)
749 confirm(not clone.isSameNode(attr))
750 confirm(not attr.isSameNode(clone))
751 confirm(clone.ownerElement is None,
752 testName + ": ownerElement should be None")
753 confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
754 testName + ": ownerDocument does not match")
755 confirm(clone.specified,
756 testName + ": cloned attribute must have specified == True")
757
758def testCloneAttributeShallow():
759 check_clone_attribute(0, "testCloneAttributeShallow")
760
761def testCloneAttributeDeep():
762 check_clone_attribute(1, "testCloneAttributeDeep")
763
764def check_clone_pi(deep, testName):
765 doc = parseString("<?target data?><doc/>")
766 pi = doc.firstChild
767 assert pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
768 clone = pi.cloneNode(deep)
769 confirm(clone.target == pi.target
770 and clone.data == pi.data)
771
772def testClonePIShallow():
773 check_clone_pi(0, "testClonePIShallow")
774
775def testClonePIDeep():
776 check_clone_pi(1, "testClonePIDeep")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000777
Fred Drakea1bde802000-11-21 22:02:43 +0000778def testNormalize():
779 doc = parseString("<doc/>")
780 root = doc.documentElement
781 root.appendChild(doc.createTextNode("first"))
782 root.appendChild(doc.createTextNode("second"))
Fred Drake946f7b12001-09-28 20:31:50 +0000783 confirm(len(root.childNodes) == 2
784 and root.childNodes.length == 2, "testNormalize -- preparation")
Fred Drakea1bde802000-11-21 22:02:43 +0000785 doc.normalize()
786 confirm(len(root.childNodes) == 1
Fred Drake946f7b12001-09-28 20:31:50 +0000787 and root.childNodes.length == 1
Fred Drakea1bde802000-11-21 22:02:43 +0000788 and root.firstChild is root.lastChild
789 and root.firstChild.data == "firstsecond"
790 , "testNormalize -- result")
791 doc.unlink()
792
Fred Drake3277da02000-12-14 18:20:22 +0000793 doc = parseString("<doc/>")
794 root = doc.documentElement
795 root.appendChild(doc.createTextNode(""))
796 doc.normalize()
Fred Drake946f7b12001-09-28 20:31:50 +0000797 confirm(len(root.childNodes) == 0
798 and root.childNodes.length == 0,
Fred Drake3277da02000-12-14 18:20:22 +0000799 "testNormalize -- single empty node removed")
800 doc.unlink()
801
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000802def testSiblings():
803 doc = parseString("<doc><?pi?>text?<elm/></doc>")
804 root = doc.documentElement
805 (pi, text, elm) = root.childNodes
Paul Prescod7993bcc2000-07-01 14:54:16 +0000806
Fred Drake004d5e62000-10-23 17:22:08 +0000807 confirm(pi.nextSibling is text and
808 pi.previousSibling is None and
809 text.nextSibling is elm and
810 text.previousSibling is pi and
811 elm.nextSibling is None and
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000812 elm.previousSibling is text, "testSiblings")
813
814 doc.unlink()
815
816def testParents():
817 doc = parseString("<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
818 root = doc.documentElement
819 elm1 = root.childNodes[0]
820 (elm2a, elm2b) = elm1.childNodes
821 elm3 = elm2b.childNodes[0]
822
823 confirm(root.parentNode is doc and
824 elm1.parentNode is root and
825 elm2a.parentNode is elm1 and
826 elm2b.parentNode is elm1 and
827 elm3.parentNode is elm2b, "testParents")
828
829 doc.unlink()
830
Fred Drake946f7b12001-09-28 20:31:50 +0000831def testNodeListItem():
832 doc = parseString("<doc><e/><e/></doc>")
833 children = doc.childNodes
834 docelem = children[0]
835 confirm(children[0] is children.item(0)
836 and children.item(1) is None
837 and docelem.childNodes.item(0) is docelem.childNodes[0]
838 and docelem.childNodes.item(1) is docelem.childNodes[1]
839 and docelem.childNodes.item(0).childNodes.item(0) is None,
840 "test NodeList.item()")
841 doc.unlink()
842
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000843def testSAX2DOM():
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000844 from xml.dom import pulldom
845
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000846 sax2dom = pulldom.SAX2DOM()
847 sax2dom.startDocument()
848 sax2dom.startElement("doc", {})
849 sax2dom.characters("text")
850 sax2dom.startElement("subelm", {})
851 sax2dom.characters("text")
852 sax2dom.endElement("subelm")
Fred Drake004d5e62000-10-23 17:22:08 +0000853 sax2dom.characters("text")
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000854 sax2dom.endElement("doc")
855 sax2dom.endDocument()
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000856
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000857 doc = sax2dom.document
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000858 root = doc.documentElement
859 (text1, elm1, text2) = root.childNodes
860 text3 = elm1.childNodes[0]
861
862 confirm(text1.previousSibling is None and
863 text1.nextSibling is elm1 and
864 elm1.previousSibling is text1 and
865 elm1.nextSibling is text2 and
866 text2.previousSibling is elm1 and
867 text2.nextSibling is None and
868 text3.previousSibling is None and
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000869 text3.nextSibling is None, "testSAX2DOM - siblings")
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000870
871 confirm(root.parentNode is doc and
872 text1.parentNode is root and
873 elm1.parentNode is root and
874 text2.parentNode is root and
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000875 text3.parentNode is elm1, "testSAX2DOM - parents")
Fred Drake004d5e62000-10-23 17:22:08 +0000876
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000877 doc.unlink()
878
Martin v. Löwis7d650ca2002-06-30 15:05:00 +0000879def testEncodings():
880 doc = parseString('<foo>&#x20ac;</foo>')
881 confirm(doc.toxml() == u'<?xml version="1.0" ?>\n<foo>\u20ac</foo>'
882 and doc.toxml('utf-8') == '<?xml version="1.0" encoding="utf-8"?>\n<foo>\xe2\x82\xac</foo>'
883 and doc.toxml('iso-8859-15') == '<?xml version="1.0" encoding="iso-8859-15"?>\n<foo>\xa4</foo>',
884 "testEncodings - encoding EURO SIGN")
885 doc.unlink()
886
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000887class UserDataHandler:
888 called = 0
889 def handle(self, operation, key, data, src, dst):
890 dst.setUserData(key, data + 1, self)
891 src.setUserData(key, None, None)
892 self.called = 1
893
894def testUserData():
895 dom = Document()
896 n = dom.createElement('e')
897 confirm(n.getUserData("foo") is None)
898 n.setUserData("foo", None, None)
899 confirm(n.getUserData("foo") is None)
900 n.setUserData("foo", 12, 12)
901 n.setUserData("bar", 13, 13)
902 confirm(n.getUserData("foo") == 12)
903 confirm(n.getUserData("bar") == 13)
904 n.setUserData("foo", None, None)
905 confirm(n.getUserData("foo") is None)
906 confirm(n.getUserData("bar") == 13)
907
908 handler = UserDataHandler()
909 n.setUserData("bar", 12, handler)
910 c = n.cloneNode(1)
911 confirm(handler.called
912 and n.getUserData("bar") is None
913 and c.getUserData("bar") == 13)
914 n.unlink()
915 c.unlink()
916 dom.unlink()
917
918def testRenameAttribute():
919 doc = parseString("<doc a='v'/>")
920 elem = doc.documentElement
921 attrmap = elem.attributes
922 attr = elem.attributes['a']
923
924 # Simple renaming
925 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
926 confirm(attr.name == "b"
927 and attr.nodeName == "b"
928 and attr.localName is None
929 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
930 and attr.prefix is None
931 and attr.value == "v"
932 and elem.getAttributeNode("a") is None
933 and elem.getAttributeNode("b").isSameNode(attr)
934 and attrmap["b"].isSameNode(attr)
935 and attr.ownerDocument.isSameNode(doc)
936 and attr.ownerElement.isSameNode(elem))
937
938 # Rename to have a namespace, no prefix
939 attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
940 confirm(attr.name == "c"
941 and attr.nodeName == "c"
942 and attr.localName == "c"
943 and attr.namespaceURI == "http://xml.python.org/ns"
944 and attr.prefix is None
945 and attr.value == "v"
946 and elem.getAttributeNode("a") is None
947 and elem.getAttributeNode("b") is None
948 and elem.getAttributeNode("c").isSameNode(attr)
949 and elem.getAttributeNodeNS(
950 "http://xml.python.org/ns", "c").isSameNode(attr)
951 and attrmap["c"].isSameNode(attr)
952 and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
953
954 # Rename to have a namespace, with prefix
955 attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
956 confirm(attr.name == "p:d"
957 and attr.nodeName == "p:d"
958 and attr.localName == "d"
959 and attr.namespaceURI == "http://xml.python.org/ns2"
960 and attr.prefix == "p"
961 and attr.value == "v"
962 and elem.getAttributeNode("a") is None
963 and elem.getAttributeNode("b") is None
964 and elem.getAttributeNode("c") is None
965 and elem.getAttributeNodeNS(
966 "http://xml.python.org/ns", "c") is None
967 and elem.getAttributeNode("p:d").isSameNode(attr)
968 and elem.getAttributeNodeNS(
969 "http://xml.python.org/ns2", "d").isSameNode(attr)
970 and attrmap["p:d"].isSameNode(attr)
971 and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
972
973 # Rename back to a simple non-NS node
974 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
975 confirm(attr.name == "e"
976 and attr.nodeName == "e"
977 and attr.localName is None
978 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
979 and attr.prefix is None
980 and attr.value == "v"
981 and elem.getAttributeNode("a") is None
982 and elem.getAttributeNode("b") is None
983 and elem.getAttributeNode("c") is None
984 and elem.getAttributeNode("p:d") is None
985 and elem.getAttributeNodeNS(
986 "http://xml.python.org/ns", "c") is None
987 and elem.getAttributeNode("e").isSameNode(attr)
988 and attrmap["e"].isSameNode(attr))
989
990 try:
991 doc.renameNode(attr, "http://xml.python.org/ns", "xmlns")
992 except xml.dom.NamespaceErr:
993 pass
994 else:
995 print "expected NamespaceErr"
996
997 checkRenameNodeSharedConstraints(doc, attr)
998 doc.unlink()
999
1000def testRenameElement():
1001 doc = parseString("<doc/>")
1002 elem = doc.documentElement
1003
1004 # Simple renaming
1005 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
1006 confirm(elem.tagName == "a"
1007 and elem.nodeName == "a"
1008 and elem.localName is None
1009 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1010 and elem.prefix is None
1011 and elem.ownerDocument.isSameNode(doc))
1012
1013 # Rename to have a namespace, no prefix
1014 elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
1015 confirm(elem.tagName == "b"
1016 and elem.nodeName == "b"
1017 and elem.localName == "b"
1018 and elem.namespaceURI == "http://xml.python.org/ns"
1019 and elem.prefix is None
1020 and elem.ownerDocument.isSameNode(doc))
1021
1022 # Rename to have a namespace, with prefix
1023 elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
1024 confirm(elem.tagName == "p:c"
1025 and elem.nodeName == "p:c"
1026 and elem.localName == "c"
1027 and elem.namespaceURI == "http://xml.python.org/ns2"
1028 and elem.prefix == "p"
1029 and elem.ownerDocument.isSameNode(doc))
1030
1031 # Rename back to a simple non-NS node
1032 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
1033 confirm(elem.tagName == "d"
1034 and elem.nodeName == "d"
1035 and elem.localName is None
1036 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1037 and elem.prefix is None
1038 and elem.ownerDocument.isSameNode(doc))
1039
1040 checkRenameNodeSharedConstraints(doc, elem)
1041 doc.unlink()
1042
1043def checkRenameNodeSharedConstraints(doc, node):
1044 # Make sure illegal NS usage is detected:
1045 try:
1046 doc.renameNode(node, "http://xml.python.org/ns", "xmlns:foo")
1047 except xml.dom.NamespaceErr:
1048 pass
1049 else:
1050 print "expected NamespaceErr"
1051
1052 doc2 = parseString("<doc/>")
1053 try:
1054 doc2.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo")
1055 except xml.dom.WrongDocumentErr:
1056 pass
1057 else:
1058 print "expected WrongDocumentErr"
1059
1060def testRenameOther():
1061 # We have to create a comment node explicitly since not all DOM
1062 # builders used with minidom add comments to the DOM.
1063 doc = xml.dom.minidom.getDOMImplementation().createDocument(
1064 xml.dom.EMPTY_NAMESPACE, "e", None)
1065 node = doc.createComment("comment")
1066 try:
1067 doc.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo")
1068 except xml.dom.NotSupportedErr:
1069 pass
1070 else:
1071 print "expected NotSupportedErr when renaming comment node"
1072 doc.unlink()
1073
1074def checkWholeText(node, s):
1075 t = node.wholeText
1076 confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
1077
1078def testWholeText():
1079 doc = parseString("<doc>a</doc>")
1080 elem = doc.documentElement
1081 text = elem.childNodes[0]
1082 assert text.nodeType == Node.TEXT_NODE
1083
1084 checkWholeText(text, "a")
1085 elem.appendChild(doc.createTextNode("b"))
1086 checkWholeText(text, "ab")
1087 elem.insertBefore(doc.createCDATASection("c"), text)
1088 checkWholeText(text, "cab")
1089
1090 # make sure we don't cross other nodes
1091 splitter = doc.createComment("comment")
1092 elem.appendChild(splitter)
1093 text2 = doc.createTextNode("d")
1094 elem.appendChild(text2)
1095 checkWholeText(text, "cab")
1096 checkWholeText(text2, "d")
1097
1098 x = doc.createElement("x")
1099 elem.replaceChild(x, splitter)
1100 splitter = x
1101 checkWholeText(text, "cab")
1102 checkWholeText(text2, "d")
1103
1104 x = doc.createProcessingInstruction("y", "z")
1105 elem.replaceChild(x, splitter)
1106 splitter = x
1107 checkWholeText(text, "cab")
1108 checkWholeText(text2, "d")
1109
1110 elem.removeChild(splitter)
1111 checkWholeText(text, "cabd")
1112 checkWholeText(text2, "cabd")
1113
1114def testReplaceWholeText():
1115 def setup():
1116 doc = parseString("<doc>a<e/>d</doc>")
1117 elem = doc.documentElement
1118 text1 = elem.firstChild
1119 text2 = elem.lastChild
1120 splitter = text1.nextSibling
1121 elem.insertBefore(doc.createTextNode("b"), splitter)
1122 elem.insertBefore(doc.createCDATASection("c"), text1)
1123 return doc, elem, text1, splitter, text2
1124
1125 doc, elem, text1, splitter, text2 = setup()
1126 text = text1.replaceWholeText("new content")
1127 checkWholeText(text, "new content")
1128 checkWholeText(text2, "d")
1129 confirm(len(elem.childNodes) == 3)
1130
1131 doc, elem, text1, splitter, text2 = setup()
1132 text = text2.replaceWholeText("new content")
1133 checkWholeText(text, "new content")
1134 checkWholeText(text1, "cab")
1135 confirm(len(elem.childNodes) == 5)
1136
1137 doc, elem, text1, splitter, text2 = setup()
1138 text = text1.replaceWholeText("")
1139 checkWholeText(text2, "d")
1140 confirm(text is None
1141 and len(elem.childNodes) == 2)
1142
1143def testSchemaType():
1144 doc = parseString(
1145 "<!DOCTYPE doc [\n"
1146 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
1147 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
1148 " <!ATTLIST doc id ID #IMPLIED \n"
1149 " ref IDREF #IMPLIED \n"
1150 " refs IDREFS #IMPLIED \n"
1151 " enum (a|b) #IMPLIED \n"
1152 " ent ENTITY #IMPLIED \n"
1153 " ents ENTITIES #IMPLIED \n"
1154 " nm NMTOKEN #IMPLIED \n"
1155 " nms NMTOKENS #IMPLIED \n"
1156 " text CDATA #IMPLIED \n"
1157 " >\n"
1158 "]><doc id='name' notid='name' text='splat!' enum='b'"
1159 " ref='name' refs='name name' ent='e1' ents='e1 e2'"
1160 " nm='123' nms='123 abc' />")
1161 elem = doc.documentElement
1162 # We don't want to rely on any specific loader at this point, so
1163 # just make sure we can get to all the names, and that the
1164 # DTD-based namespace is right. The names can vary by loader
1165 # since each supports a different level of DTD information.
1166 t = elem.schemaType
1167 confirm(t.name is None
1168 and t.namespace == xml.dom.EMPTY_NAMESPACE)
1169 names = "id notid text enum ref refs ent ents nm nms".split()
1170 for name in names:
1171 a = elem.getAttributeNode(name)
1172 t = a.schemaType
1173 confirm(hasattr(t, "name")
1174 and t.namespace == xml.dom.EMPTY_NAMESPACE)
1175
1176def testSetIdAttribute():
1177 doc = parseString("<doc a1='v' a2='w'/>")
1178 e = doc.documentElement
1179 a1 = e.getAttributeNode("a1")
1180 a2 = e.getAttributeNode("a2")
1181 confirm(doc.getElementById("v") is None
1182 and not a1.isId
1183 and not a2.isId)
1184 e.setIdAttribute("a1")
1185 confirm(e.isSameNode(doc.getElementById("v"))
1186 and a1.isId
1187 and not a2.isId)
1188 e.setIdAttribute("a2")
1189 confirm(e.isSameNode(doc.getElementById("v"))
1190 and e.isSameNode(doc.getElementById("w"))
1191 and a1.isId
1192 and a2.isId)
1193 # replace the a1 node; the new node should *not* be an ID
1194 a3 = doc.createAttribute("a1")
1195 a3.value = "v"
1196 e.setAttributeNode(a3)
1197 confirm(doc.getElementById("v") is None
1198 and e.isSameNode(doc.getElementById("w"))
1199 and not a1.isId
1200 and a2.isId
1201 and not a3.isId)
1202 # renaming an attribute should not affect it's ID-ness:
1203 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1204 confirm(e.isSameNode(doc.getElementById("w"))
1205 and a2.isId)
1206
1207def testSetIdAttributeNS():
1208 NS1 = "http://xml.python.org/ns1"
1209 NS2 = "http://xml.python.org/ns2"
1210 doc = parseString("<doc"
1211 " xmlns:ns1='" + NS1 + "'"
1212 " xmlns:ns2='" + NS2 + "'"
1213 " ns1:a1='v' ns2:a2='w'/>")
1214 e = doc.documentElement
1215 a1 = e.getAttributeNodeNS(NS1, "a1")
1216 a2 = e.getAttributeNodeNS(NS2, "a2")
1217 confirm(doc.getElementById("v") is None
1218 and not a1.isId
1219 and not a2.isId)
1220 e.setIdAttributeNS(NS1, "a1")
1221 confirm(e.isSameNode(doc.getElementById("v"))
1222 and a1.isId
1223 and not a2.isId)
1224 e.setIdAttributeNS(NS2, "a2")
1225 confirm(e.isSameNode(doc.getElementById("v"))
1226 and e.isSameNode(doc.getElementById("w"))
1227 and a1.isId
1228 and a2.isId)
1229 # replace the a1 node; the new node should *not* be an ID
1230 a3 = doc.createAttributeNS(NS1, "a1")
1231 a3.value = "v"
1232 e.setAttributeNode(a3)
1233 confirm(e.isSameNode(doc.getElementById("w")))
1234 confirm(not a1.isId)
1235 confirm(a2.isId)
1236 confirm(not a3.isId)
1237 confirm(doc.getElementById("v") is None)
1238 # renaming an attribute should not affect it's ID-ness:
1239 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1240 confirm(e.isSameNode(doc.getElementById("w"))
1241 and a2.isId)
1242
1243def testSetIdAttributeNode():
1244 NS1 = "http://xml.python.org/ns1"
1245 NS2 = "http://xml.python.org/ns2"
1246 doc = parseString("<doc"
1247 " xmlns:ns1='" + NS1 + "'"
1248 " xmlns:ns2='" + NS2 + "'"
1249 " ns1:a1='v' ns2:a2='w'/>")
1250 e = doc.documentElement
1251 a1 = e.getAttributeNodeNS(NS1, "a1")
1252 a2 = e.getAttributeNodeNS(NS2, "a2")
1253 confirm(doc.getElementById("v") is None
1254 and not a1.isId
1255 and not a2.isId)
1256 e.setIdAttributeNode(a1)
1257 confirm(e.isSameNode(doc.getElementById("v"))
1258 and a1.isId
1259 and not a2.isId)
1260 e.setIdAttributeNode(a2)
1261 confirm(e.isSameNode(doc.getElementById("v"))
1262 and e.isSameNode(doc.getElementById("w"))
1263 and a1.isId
1264 and a2.isId)
1265 # replace the a1 node; the new node should *not* be an ID
1266 a3 = doc.createAttributeNS(NS1, "a1")
1267 a3.value = "v"
1268 e.setAttributeNode(a3)
1269 confirm(e.isSameNode(doc.getElementById("w")))
1270 confirm(not a1.isId)
1271 confirm(a2.isId)
1272 confirm(not a3.isId)
1273 confirm(doc.getElementById("v") is None)
1274 # renaming an attribute should not affect it's ID-ness:
1275 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1276 confirm(e.isSameNode(doc.getElementById("w"))
1277 and a2.isId)
1278
1279def testPickledDocument():
1280 doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
1281 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
1282 " 'http://xml.python.org/system' [\n"
1283 " <!ELEMENT e EMPTY>\n"
1284 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
1285 "]><doc attr='value'> text\n"
1286 "<?pi sample?> <!-- comment --> <e/> </doc>")
1287 s = pickle.dumps(doc)
1288 doc2 = pickle.loads(s)
1289 stack = [(doc, doc2)]
1290 while stack:
1291 n1, n2 = stack.pop()
1292 confirm(n1.nodeType == n2.nodeType
1293 and len(n1.childNodes) == len(n2.childNodes)
1294 and n1.nodeName == n2.nodeName
1295 and not n1.isSameNode(n2)
1296 and not n2.isSameNode(n1))
1297 if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
1298 len(n1.entities)
1299 len(n2.entities)
1300 len(n1.notations)
1301 len(n2.notations)
1302 confirm(len(n1.entities) == len(n2.entities)
1303 and len(n1.notations) == len(n2.notations))
1304 for i in range(len(n1.notations)):
1305 no1 = n1.notations.item(i)
1306 no2 = n1.notations.item(i)
1307 confirm(no1.name == no2.name
1308 and no1.publicId == no2.publicId
1309 and no1.systemId == no2.systemId)
1310 statck.append((no1, no2))
1311 for i in range(len(n1.entities)):
1312 e1 = n1.entities.item(i)
1313 e2 = n2.entities.item(i)
1314 confirm(e1.notationName == e2.notationName
1315 and e1.publicId == e2.publicId
1316 and e1.systemId == e2.systemId)
1317 stack.append((e1, e2))
1318 if n1.nodeType != Node.DOCUMENT_NODE:
1319 confirm(n1.ownerDocument.isSameNode(doc)
1320 and n2.ownerDocument.isSameNode(doc2))
1321 for i in range(len(n1.childNodes)):
1322 stack.append((n1.childNodes[i], n2.childNodes[i]))
1323
1324
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +00001325# --- MAIN PROGRAM
Fred Drake004d5e62000-10-23 17:22:08 +00001326
Jeremy Hylton3b0c6002000-10-12 17:31:36 +00001327names = globals().keys()
Paul Prescod7993bcc2000-07-01 14:54:16 +00001328names.sort()
Paul Prescod10d27662000-09-18 19:07:26 +00001329
Fred Drakeacfb3f62001-02-01 18:11:29 +00001330failed = []
Paul Prescod10d27662000-09-18 19:07:26 +00001331
Fred Drake6dd7d072002-09-12 17:03:02 +00001332try:
1333 Node.allnodes
1334except AttributeError:
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +00001335 # We don't actually have the minidom from the standard library,
Fred Drake6dd7d072002-09-12 17:03:02 +00001336 # but are picking up the PyXML version from site-packages.
1337 def check_allnodes():
1338 pass
1339else:
1340 def check_allnodes():
1341 confirm(len(Node.allnodes) == 0,
1342 "assertion: len(Node.allnodes) == 0")
1343 if len(Node.allnodes):
1344 print "Garbage left over:"
1345 if verbose:
1346 print Node.allnodes.items()[0:10]
1347 else:
1348 # Don't print specific nodes if repeatable results
1349 # are needed
1350 print len(Node.allnodes)
1351 Node.allnodes = {}
1352
Paul Prescod7993bcc2000-07-01 14:54:16 +00001353for name in names:
Jeremy Hylton3b0c6002000-10-12 17:31:36 +00001354 if name.startswith("test"):
1355 func = globals()[name]
Paul Prescod7993bcc2000-07-01 14:54:16 +00001356 try:
1357 func()
Fred Drake6dd7d072002-09-12 17:03:02 +00001358 check_allnodes()
Fred Drakeacfb3f62001-02-01 18:11:29 +00001359 except:
1360 failed.append(name)
Paul Prescod7993bcc2000-07-01 14:54:16 +00001361 print "Test Failed: ", name
Fred Drake1703cf62000-12-15 21:31:59 +00001362 sys.stdout.flush()
Jeremy Hylton3b0c6002000-10-12 17:31:36 +00001363 traceback.print_exception(*sys.exc_info())
Fred Drakeacfb3f62001-02-01 18:11:29 +00001364 print `sys.exc_info()[1]`
Jeremy Hylton3b0c6002000-10-12 17:31:36 +00001365 Node.allnodes = {}
Paul Prescod10d27662000-09-18 19:07:26 +00001366
Fred Drakeacfb3f62001-02-01 18:11:29 +00001367if failed:
1368 print "\n\n\n**** Check for failures in these tests:"
1369 for name in failed:
1370 print " " + name