blob: c39c61647238a6b012c506a97dbdb19b58fb8bbc [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
5import traceback
Fred Drakec441f7b2002-07-19 22:16:41 +00006
Barry Warsaw04f357c2002-07-23 19:04:11 +00007from test.test_support import verbose
Fred Drake17647f52000-07-03 16:37:42 +00008
Fred Drakec441f7b2002-07-19 22:16:41 +00009import xml.dom
10import xml.parsers.expat
11
12from xml.dom.minidom import parse, Node, Document, parseString
13
Fred Drake17647f52000-07-03 16:37:42 +000014if __name__ == "__main__":
15 base = sys.argv[0]
16else:
17 base = __file__
Guido van Rossume2ae77b2001-10-24 20:42:55 +000018tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml")
Fred Drake17647f52000-07-03 16:37:42 +000019del base
Paul Prescod7993bcc2000-07-01 14:54:16 +000020
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000021def confirm(test, testname = "Test"):
Fred Drakec441f7b2002-07-19 22:16:41 +000022 if not test:
Paul Prescod10d27662000-09-18 19:07:26 +000023 print "Failed " + testname
24 raise Exception
25
Paul Prescod10d27662000-09-18 19:07:26 +000026def testParseFromFile():
27 from StringIO import StringIO
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000028 dom = parse(StringIO(open(tstfile).read()))
Paul Prescod4c799192000-09-19 19:33:02 +000029 dom.unlink()
Martin v. Löwis89c528b2000-09-19 16:22:10 +000030 confirm(isinstance(dom,Document))
Paul Prescod10d27662000-09-18 19:07:26 +000031
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000032def testGetElementsByTagName():
33 dom = parse(tstfile)
34 confirm(dom.getElementsByTagName("LI") == \
35 dom.documentElement.getElementsByTagName("LI"))
Paul Prescod7993bcc2000-07-01 14:54:16 +000036 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +000037
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000038def testInsertBefore():
Fred Drakea1bde802000-11-21 22:02:43 +000039 dom = parseString("<doc><foo/></doc>")
40 root = dom.documentElement
41 elem = root.childNodes[0]
42 nelem = dom.createElement("element")
43 root.insertBefore(nelem, elem)
44 confirm(len(root.childNodes) == 2
Fred Drake946f7b12001-09-28 20:31:50 +000045 and root.childNodes.length == 2
Fred Drakea1bde802000-11-21 22:02:43 +000046 and root.childNodes[0] is nelem
Fred Drake946f7b12001-09-28 20:31:50 +000047 and root.childNodes.item(0) is nelem
Fred Drakea1bde802000-11-21 22:02:43 +000048 and root.childNodes[1] is elem
Fred Drake946f7b12001-09-28 20:31:50 +000049 and root.childNodes.item(1) is elem
Fred Drakea1bde802000-11-21 22:02:43 +000050 and root.firstChild is nelem
51 and root.lastChild is elem
52 and root.toxml() == "<doc><element/><foo/></doc>"
53 , "testInsertBefore -- node properly placed in tree")
54 nelem = dom.createElement("element")
55 root.insertBefore(nelem, None)
56 confirm(len(root.childNodes) == 3
Fred Drake946f7b12001-09-28 20:31:50 +000057 and root.childNodes.length == 3
Fred Drakea1bde802000-11-21 22:02:43 +000058 and root.childNodes[1] is elem
Fred Drake946f7b12001-09-28 20:31:50 +000059 and root.childNodes.item(1) is elem
Fred Drakea1bde802000-11-21 22:02:43 +000060 and root.childNodes[2] is nelem
Fred Drake946f7b12001-09-28 20:31:50 +000061 and root.childNodes.item(2) is nelem
Fred Drakea1bde802000-11-21 22:02:43 +000062 and root.lastChild is nelem
63 and nelem.previousSibling is elem
64 and root.toxml() == "<doc><element/><foo/><element/></doc>"
65 , "testInsertBefore -- node properly placed in tree")
66 nelem2 = dom.createElement("bar")
67 root.insertBefore(nelem2, nelem)
68 confirm(len(root.childNodes) == 4
Fred Drake946f7b12001-09-28 20:31:50 +000069 and root.childNodes.length == 4
Fred Drakea1bde802000-11-21 22:02:43 +000070 and root.childNodes[2] is nelem2
Fred Drake946f7b12001-09-28 20:31:50 +000071 and root.childNodes.item(2) is nelem2
Fred Drakea1bde802000-11-21 22:02:43 +000072 and root.childNodes[3] is nelem
Fred Drake946f7b12001-09-28 20:31:50 +000073 and root.childNodes.item(3) is nelem
Fred Drakea1bde802000-11-21 22:02:43 +000074 and nelem2.nextSibling is nelem
75 and nelem.previousSibling is nelem2
76 and root.toxml() == "<doc><element/><foo/><bar/><element/></doc>"
77 , "testInsertBefore -- node properly placed in tree")
Paul Prescod7993bcc2000-07-01 14:54:16 +000078 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +000079
Fred Drakee50959a2001-12-06 04:32:18 +000080def _create_fragment_test_nodes():
81 dom = parseString("<doc/>")
82 orig = dom.createTextNode("original")
83 c1 = dom.createTextNode("foo")
84 c2 = dom.createTextNode("bar")
85 c3 = dom.createTextNode("bat")
86 dom.documentElement.appendChild(orig)
87 frag = dom.createDocumentFragment()
88 frag.appendChild(c1)
89 frag.appendChild(c2)
90 frag.appendChild(c3)
91 return dom, orig, c1, c2, c3, frag
92
93def testInsertBeforeFragment():
94 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
95 dom.documentElement.insertBefore(frag, None)
96 confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
97 "insertBefore(<fragment>, None)")
98 frag.unlink()
99 dom.unlink()
100 #
101 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
102 dom.documentElement.insertBefore(frag, orig)
103 confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig),
104 "insertBefore(<fragment>, orig)")
105 frag.unlink()
106 dom.unlink()
107
Paul Prescod7993bcc2000-07-01 14:54:16 +0000108def testAppendChild():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000109 dom = parse(tstfile)
110 dom.documentElement.appendChild(dom.createComment(u"Hello"))
111 confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
112 confirm(dom.documentElement.childNodes[-1].data == "Hello")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000113 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000114
Fred Drakee50959a2001-12-06 04:32:18 +0000115def testAppendChildFragment():
116 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
117 dom.documentElement.appendChild(frag)
118 confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
119 "appendChild(<fragment>)")
120 frag.unlink()
121 dom.unlink()
122
123def testReplaceChildFragment():
124 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
125 dom.documentElement.replaceChild(frag, orig)
126 orig.unlink()
127 confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
128 "replaceChild(<fragment>)")
129 frag.unlink()
130 dom.unlink()
131
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000132def testLegalChildren():
133 dom = Document()
134 elem = dom.createElement('element')
135 text = dom.createTextNode('text')
Fredrik Lundhf7850422001-01-17 21:51:36 +0000136
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000137 try: dom.appendChild(text)
Fred Drakec441f7b2002-07-19 22:16:41 +0000138 except xml.dom.HierarchyRequestErr: pass
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000139 else:
140 print "dom.appendChild didn't raise HierarchyRequestErr"
141
142 dom.appendChild(elem)
143 try: dom.insertBefore(text, elem)
Fred Drakec441f7b2002-07-19 22:16:41 +0000144 except xml.dom.HierarchyRequestErr: pass
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000145 else:
146 print "dom.appendChild didn't raise HierarchyRequestErr"
147
148 try: dom.replaceChild(text, elem)
Fred Drakec441f7b2002-07-19 22:16:41 +0000149 except xml.dom.HierarchyRequestErr: pass
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000150 else:
151 print "dom.appendChild didn't raise HierarchyRequestErr"
152
Tim Peters0009c4e2001-02-21 07:29:48 +0000153 nodemap = elem.attributes
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000154 try: nodemap.setNamedItem(text)
Fred Drakec441f7b2002-07-19 22:16:41 +0000155 except xml.dom.HierarchyRequestErr: pass
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000156 else:
157 print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr"
158
159 try: nodemap.setNamedItemNS(text)
Fred Drakec441f7b2002-07-19 22:16:41 +0000160 except xml.dom.HierarchyRequestErr: pass
Andrew M. Kuchlingbc8f72c2001-02-21 01:30:26 +0000161 else:
162 print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr"
163
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000164 elem.appendChild(text)
Fredrik Lundhf7850422001-01-17 21:51:36 +0000165 dom.unlink()
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000166
Fred Drake2998a552001-12-06 18:27:48 +0000167def testNamedNodeMapSetItem():
168 dom = Document()
169 elem = dom.createElement('element')
170 attrs = elem.attributes
171 attrs["foo"] = "bar"
172 a = attrs.item(0)
173 confirm(a.ownerDocument is dom,
174 "NamedNodeMap.__setitem__() sets ownerDocument")
175 confirm(a.ownerElement is elem,
176 "NamedNodeMap.__setitem__() sets ownerElement")
177 confirm(a.value == "bar",
178 "NamedNodeMap.__setitem__() sets value")
179 confirm(a.nodeValue == "bar",
180 "NamedNodeMap.__setitem__() sets nodeValue")
181 elem.unlink()
182 dom.unlink()
183
Paul Prescod7993bcc2000-07-01 14:54:16 +0000184def testNonZero():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000185 dom = parse(tstfile)
186 confirm(dom)# should not be zero
187 dom.appendChild(dom.createComment("foo"))
188 confirm(not dom.childNodes[-1].childNodes)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000189 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000190
191def testUnlink():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000192 dom = parse(tstfile)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000193 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000194
195def testElement():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000196 dom = Document()
197 dom.appendChild(dom.createElement("abc"))
198 confirm(dom.documentElement)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000199 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000200
201def testAAA():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000202 dom = parseString("<abc/>")
203 el = dom.documentElement
204 el.setAttribute("spam", "jam2")
Fred Drakea1bde802000-11-21 22:02:43 +0000205 confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
Fred Drake2998a552001-12-06 18:27:48 +0000206 a = el.getAttributeNode("spam")
207 confirm(a.ownerDocument is dom,
208 "setAttribute() sets ownerDocument")
209 confirm(a.ownerElement is dom.documentElement,
210 "setAttribute() sets ownerElement")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000211 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000212
213def testAAB():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000214 dom = parseString("<abc/>")
215 el = dom.documentElement
216 el.setAttribute("spam", "jam")
217 el.setAttribute("spam", "jam2")
Fred Drakea1bde802000-11-21 22:02:43 +0000218 confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000219 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000220
221def testAddAttr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000222 dom = Document()
223 child = dom.appendChild(dom.createElement("abc"))
Paul Prescod7993bcc2000-07-01 14:54:16 +0000224
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000225 child.setAttribute("def", "ghi")
226 confirm(child.getAttribute("def") == "ghi")
227 confirm(child.attributes["def"].value == "ghi")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000228
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000229 child.setAttribute("jkl", "mno")
230 confirm(child.getAttribute("jkl") == "mno")
231 confirm(child.attributes["jkl"].value == "mno")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000232
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000233 confirm(len(child.attributes) == 2)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000234
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000235 child.setAttribute("def", "newval")
236 confirm(child.getAttribute("def") == "newval")
237 confirm(child.attributes["def"].value == "newval")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000238
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000239 confirm(len(child.attributes) == 2)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000240 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000241
242def testDeleteAttr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000243 dom = Document()
244 child = dom.appendChild(dom.createElement("abc"))
Paul Prescod7993bcc2000-07-01 14:54:16 +0000245
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000246 confirm(len(child.attributes) == 0)
247 child.setAttribute("def", "ghi")
248 confirm(len(child.attributes) == 1)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000249 del child.attributes["def"]
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000250 confirm(len(child.attributes) == 0)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000251 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000252
253def testRemoveAttr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000254 dom = Document()
255 child = dom.appendChild(dom.createElement("abc"))
Paul Prescod7993bcc2000-07-01 14:54:16 +0000256
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000257 child.setAttribute("def", "ghi")
258 confirm(len(child.attributes) == 1)
259 child.removeAttribute("def")
260 confirm(len(child.attributes) == 0)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000261
262 dom.unlink()
263
264def testRemoveAttrNS():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000265 dom = Document()
266 child = dom.appendChild(
267 dom.createElementNS("http://www.python.org", "python:abc"))
Fred Drake004d5e62000-10-23 17:22:08 +0000268 child.setAttributeNS("http://www.w3.org", "xmlns:python",
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000269 "http://www.python.org")
270 child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
271 confirm(len(child.attributes) == 2)
272 child.removeAttributeNS("http://www.python.org", "abcattr")
273 confirm(len(child.attributes) == 1)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000274
275 dom.unlink()
Fred Drake004d5e62000-10-23 17:22:08 +0000276
Paul Prescod7993bcc2000-07-01 14:54:16 +0000277def testRemoveAttributeNode():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000278 dom = Document()
279 child = dom.appendChild(dom.createElement("foo"))
280 child.setAttribute("spam", "jam")
281 confirm(len(child.attributes) == 1)
282 node = child.getAttributeNode("spam")
283 child.removeAttributeNode(node)
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000284 confirm(len(child.attributes) == 0
285 and child.getAttributeNode("spam") is None)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000286
287 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000288
289def testChangeAttr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000290 dom = parseString("<abc/>")
291 el = dom.documentElement
292 el.setAttribute("spam", "jam")
293 confirm(len(el.attributes) == 1)
294 el.setAttribute("spam", "bam")
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000295 # Set this attribute to be an ID and make sure that doesn't change
296 # when changing the value:
297 el.setIdAttribute("spam")
298 confirm(len(el.attributes) == 1
299 and el.attributes["spam"].value == "bam"
300 and el.attributes["spam"].nodeValue == "bam"
301 and el.getAttribute("spam") == "bam"
302 and el.getAttributeNode("spam").isId)
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000303 el.attributes["spam"] = "ham"
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000304 confirm(len(el.attributes) == 1
305 and el.attributes["spam"].value == "ham"
306 and el.attributes["spam"].nodeValue == "ham"
307 and el.getAttribute("spam") == "ham"
308 and el.attributes["spam"].isId)
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000309 el.setAttribute("spam2", "bam")
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000310 confirm(len(el.attributes) == 2
311 and el.attributes["spam"].value == "ham"
312 and el.attributes["spam"].nodeValue == "ham"
313 and el.getAttribute("spam") == "ham"
314 and el.attributes["spam2"].value == "bam"
315 and el.attributes["spam2"].nodeValue == "bam"
316 and el.getAttribute("spam2") == "bam")
317 el.attributes["spam2"] = "bam2"
318 confirm(len(el.attributes) == 2
319 and el.attributes["spam"].value == "ham"
320 and el.attributes["spam"].nodeValue == "ham"
321 and el.getAttribute("spam") == "ham"
322 and el.attributes["spam2"].value == "bam2"
323 and el.attributes["spam2"].nodeValue == "bam2"
324 and el.getAttribute("spam2") == "bam2")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000325 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000326
327def testGetAttrList():
328 pass
329
330def testGetAttrValues(): pass
331
332def testGetAttrLength(): pass
333
334def testGetAttribute(): pass
335
336def testGetAttributeNS(): pass
337
338def testGetAttributeNode(): pass
339
Martin v. Löwis351c3d02001-06-03 14:27:02 +0000340def testGetElementsByTagNameNS():
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000341 d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
Martin v. Löwis351c3d02001-06-03 14:27:02 +0000342 <minidom:myelem/>
343 </foo>"""
344 dom = parseString(d)
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000345 elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", "myelem")
346 confirm(len(elems) == 1
347 and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"
348 and elems[0].localName == "myelem"
349 and elems[0].prefix == "minidom"
350 and elems[0].tagName == "minidom:myelem"
351 and elems[0].nodeName == "minidom:myelem")
Martin v. Löwis351c3d02001-06-03 14:27:02 +0000352 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000353
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000354def get_empty_nodelist_from_elements_by_tagName_ns_helper(doc, nsuri, lname):
355 nodelist = doc.getElementsByTagNameNS(nsuri, lname)
356 confirm(len(nodelist) == 0)
357
358def testGetEmptyNodeListFromElementsByTagNameNS():
359 doc = parseString('<doc/>')
360 get_empty_nodelist_from_elements_by_tagName_ns_helper(
361 doc, 'http://xml.python.org/namespaces/a', 'localname')
362 get_empty_nodelist_from_elements_by_tagName_ns_helper(
363 doc, '*', 'splat')
364 get_empty_nodelist_from_elements_by_tagName_ns_helper(
365 doc, 'http://xml.python.org/namespaces/a', '*')
366
367 doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
368 get_empty_nodelist_from_elements_by_tagName_ns_helper(
369 doc, "http://xml.python.org/splat", "not-there")
370 get_empty_nodelist_from_elements_by_tagName_ns_helper(
371 doc, "*", "not-there")
372 get_empty_nodelist_from_elements_by_tagName_ns_helper(
373 doc, "http://somewhere.else.net/not-there", "e")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000374
375def testElementReprAndStr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000376 dom = Document()
377 el = dom.appendChild(dom.createElement("abc"))
378 string1 = repr(el)
379 string2 = str(el)
380 confirm(string1 == string2)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000381 dom.unlink()
382
383# commented out until Fredrick's fix is checked in
384def _testElementReprAndStrUnicode():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000385 dom = Document()
386 el = dom.appendChild(dom.createElement(u"abc"))
387 string1 = repr(el)
388 string2 = str(el)
389 confirm(string1 == string2)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000390 dom.unlink()
391
392# commented out until Fredrick's fix is checked in
393def _testElementReprAndStrUnicodeNS():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000394 dom = Document()
395 el = dom.appendChild(
396 dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
397 string1 = repr(el)
398 string2 = str(el)
399 confirm(string1 == string2)
400 confirm(string1.find("slash:abc") != -1)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000401 dom.unlink()
402
403def testAttributeRepr():
Jeremy Hylton3b0c6002000-10-12 17:31:36 +0000404 dom = Document()
405 el = dom.appendChild(dom.createElement(u"abc"))
406 node = el.setAttribute("abc", "def")
407 confirm(str(node) == repr(node))
Paul Prescod7993bcc2000-07-01 14:54:16 +0000408 dom.unlink()
409
410def testTextNodeRepr(): pass
411
Martin v. Löwis0a84a332000-10-06 22:42:55 +0000412def testWriteXML():
Martin v. Löwisfe28ca02001-02-06 01:16:48 +0000413 str = '<?xml version="1.0" ?>\n<a b="c"/>'
Martin v. Löwis0a84a332000-10-06 22:42:55 +0000414 dom = parseString(str)
415 domstr = dom.toxml()
416 dom.unlink()
417 confirm(str == domstr)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000418
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000419def testProcessingInstruction():
420 dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
421 pi = dom.documentElement.firstChild
422 confirm(pi.target == "mypi"
423 and pi.data == "data \t\n "
424 and pi.nodeName == "mypi"
425 and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
426 and pi.attributes is None
427 and not pi.hasChildNodes()
428 and len(pi.childNodes) == 0
429 and pi.firstChild is None
430 and pi.lastChild is None
431 and pi.localName is None
432 and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000433
434def testProcessingInstructionRepr(): pass
435
436def testTextRepr(): pass
437
438def testWriteText(): pass
439
440def testDocumentElement(): pass
441
Fred Drakea1bde802000-11-21 22:02:43 +0000442def testTooManyDocumentElements():
443 doc = parseString("<doc/>")
444 elem = doc.createElement("extra")
445 try:
446 doc.appendChild(elem)
Fred Drakec441f7b2002-07-19 22:16:41 +0000447 except xml.dom.HierarchyRequestErr:
448 pass
Fred Drakea1bde802000-11-21 22:02:43 +0000449 else:
450 print "Failed to catch expected exception when" \
451 " adding extra document element."
452 elem.unlink()
453 doc.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000454
455def testCreateElementNS(): pass
456
Andrew M. Kuchlingad4a5582000-12-31 04:03:27 +0000457def testCreateAttributeNS(): pass
Paul Prescod7993bcc2000-07-01 14:54:16 +0000458
459def testParse(): pass
460
461def testParseString(): pass
462
463def testComment(): pass
464
465def testAttrListItem(): pass
466
467def testAttrListItems(): pass
468
469def testAttrListItemNS(): pass
470
471def testAttrListKeys(): pass
472
473def testAttrListKeysNS(): pass
474
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000475def testRemoveNamedItem():
476 doc = parseString("<doc a=''/>")
477 e = doc.documentElement
478 attrs = e.attributes
479 a1 = e.getAttributeNode("a")
480 a2 = attrs.removeNamedItem("a")
481 confirm(a1.isSameNode(a2))
482 try:
483 attrs.removeNamedItem("a")
484 except xml.dom.NotFoundErr:
485 pass
486
487def testRemoveNamedItemNS():
488 doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
489 e = doc.documentElement
490 attrs = e.attributes
491 a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
492 a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
493 confirm(a1.isSameNode(a2))
494 try:
495 attrs.removeNamedItemNS("http://xml.python.org/", "b")
496 except xml.dom.NotFoundErr:
497 pass
498
Paul Prescod7993bcc2000-07-01 14:54:16 +0000499def testAttrListValues(): pass
500
501def testAttrListLength(): pass
502
503def testAttrList__getitem__(): pass
504
505def testAttrList__setitem__(): pass
506
507def testSetAttrValueandNodeValue(): pass
508
509def testParseElement(): pass
510
511def testParseAttributes(): pass
512
513def testParseElementNamespaces(): pass
514
515def testParseAttributeNamespaces(): pass
516
517def testParseProcessingInstructions(): pass
518
519def testChildNodes(): pass
520
521def testFirstChild(): pass
522
523def testHasChildNodes(): pass
524
Fred Drakea1bde802000-11-21 22:02:43 +0000525def testCloneElementShallow():
526 dom, clone = _setupCloneElement(0)
527 confirm(len(clone.childNodes) == 0
Fred Drake946f7b12001-09-28 20:31:50 +0000528 and clone.childNodes.length == 0
Fred Drakea1bde802000-11-21 22:02:43 +0000529 and clone.parentNode is None
530 and clone.toxml() == '<doc attr="value"/>'
531 , "testCloneElementShallow")
532 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000533
Fred Drakea1bde802000-11-21 22:02:43 +0000534def testCloneElementDeep():
535 dom, clone = _setupCloneElement(1)
536 confirm(len(clone.childNodes) == 1
Fred Drake946f7b12001-09-28 20:31:50 +0000537 and clone.childNodes.length == 1
Fred Drakea1bde802000-11-21 22:02:43 +0000538 and clone.parentNode is None
539 and clone.toxml() == '<doc attr="value"><foo/></doc>'
540 , "testCloneElementDeep")
541 dom.unlink()
Paul Prescod7993bcc2000-07-01 14:54:16 +0000542
Fred Drakea1bde802000-11-21 22:02:43 +0000543def _setupCloneElement(deep):
544 dom = parseString("<doc attr='value'><foo/></doc>")
545 root = dom.documentElement
546 clone = root.cloneNode(deep)
547 _testCloneElementCopiesAttributes(
548 root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
549 # mutilate the original so shared data is detected
550 root.tagName = root.nodeName = "MODIFIED"
551 root.setAttribute("attr", "NEW VALUE")
552 root.setAttribute("added", "VALUE")
553 return dom, clone
554
555def _testCloneElementCopiesAttributes(e1, e2, test):
556 attrs1 = e1.attributes
557 attrs2 = e2.attributes
558 keys1 = attrs1.keys()
559 keys2 = attrs2.keys()
560 keys1.sort()
561 keys2.sort()
562 confirm(keys1 == keys2, "clone of element has same attribute keys")
563 for i in range(len(keys1)):
564 a1 = attrs1.item(i)
565 a2 = attrs2.item(i)
566 confirm(a1 is not a2
567 and a1.value == a2.value
568 and a1.nodeValue == a2.nodeValue
569 and a1.namespaceURI == a2.namespaceURI
570 and a1.localName == a2.localName
571 , "clone of attribute node has proper attribute values")
572 confirm(a2.ownerElement is e2,
573 "clone of attribute node correctly owned")
Fredrik Lundhf7850422001-01-17 21:51:36 +0000574
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000575def testCloneDocumentShallow():
576 doc = parseString("<?xml version='1.0'?>\n"
577 "<!-- comment -->"
578 "<!DOCTYPE doc [\n"
579 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
580 "]>\n"
581 "<doc attr='value'/>")
582 doc2 = doc.cloneNode(0)
583 confirm(doc2 is None,
584 "testCloneDocumentShallow:"
585 " shallow cloning of documents makes no sense!")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000586
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000587def testCloneDocumentDeep():
588 doc = parseString("<?xml version='1.0'?>\n"
589 "<!-- comment -->"
590 "<!DOCTYPE doc [\n"
591 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
592 "]>\n"
593 "<doc attr='value'/>")
594 doc2 = doc.cloneNode(1)
595 confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
596 "testCloneDocumentDeep: document objects not distinct")
597 confirm(len(doc.childNodes) == len(doc2.childNodes),
598 "testCloneDocumentDeep: wrong number of Document children")
599 confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
600 "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
601 confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
602 "testCloneDocumentDeep: documentElement owner is not new document")
603 confirm(not doc.documentElement.isSameNode(doc2.documentElement),
604 "testCloneDocumentDeep: documentElement should not be shared")
605 if doc.doctype is not None:
606 # check the doctype iff the original DOM maintained it
607 confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
608 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
609 confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
610 confirm(not doc.doctype.isSameNode(doc2.doctype))
Paul Prescod7993bcc2000-07-01 14:54:16 +0000611
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000612def testCloneDocumentTypeDeepOk():
613 doctype = create_nonempty_doctype()
614 clone = doctype.cloneNode(1)
615 confirm(clone is not None
616 and clone.nodeName == doctype.nodeName
617 and clone.name == doctype.name
618 and clone.publicId == doctype.publicId
619 and clone.systemId == doctype.systemId
620 and len(clone.entities) == len(doctype.entities)
621 and clone.entities.item(len(clone.entities)) is None
622 and len(clone.notations) == len(doctype.notations)
623 and clone.notations.item(len(clone.notations)) is None
624 and len(clone.childNodes) == 0)
625 for i in range(len(doctype.entities)):
626 se = doctype.entities.item(i)
627 ce = clone.entities.item(i)
628 confirm((not se.isSameNode(ce))
629 and (not ce.isSameNode(se))
630 and ce.nodeName == se.nodeName
631 and ce.notationName == se.notationName
632 and ce.publicId == se.publicId
633 and ce.systemId == se.systemId
634 and ce.encoding == se.encoding
635 and ce.actualEncoding == se.actualEncoding
636 and ce.version == se.version)
637 for i in range(len(doctype.notations)):
638 sn = doctype.notations.item(i)
639 cn = clone.notations.item(i)
640 confirm((not sn.isSameNode(cn))
641 and (not cn.isSameNode(sn))
642 and cn.nodeName == sn.nodeName
643 and cn.publicId == sn.publicId
644 and cn.systemId == sn.systemId)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000645
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000646def testCloneDocumentTypeDeepNotOk():
647 doc = create_doc_with_doctype()
648 clone = doc.doctype.cloneNode(1)
649 confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000650
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000651def testCloneDocumentTypeShallowOk():
652 doctype = create_nonempty_doctype()
653 clone = doctype.cloneNode(0)
654 confirm(clone is not None
655 and clone.nodeName == doctype.nodeName
656 and clone.name == doctype.name
657 and clone.publicId == doctype.publicId
658 and clone.systemId == doctype.systemId
659 and len(clone.entities) == 0
660 and clone.entities.item(0) is None
661 and len(clone.notations) == 0
662 and clone.notations.item(0) is None
663 and len(clone.childNodes) == 0)
Paul Prescod7993bcc2000-07-01 14:54:16 +0000664
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000665def testCloneDocumentTypeShallowNotOk():
666 doc = create_doc_with_doctype()
667 clone = doc.doctype.cloneNode(0)
668 confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000669
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000670def check_import_document(deep, testName):
671 doc1 = parseString("<doc/>")
672 doc2 = parseString("<doc/>")
673 try:
674 doc1.importNode(doc2, deep)
675 except xml.dom.NotSupportedErr:
676 pass
677 else:
678 raise Exception(testName +
679 ": expected NotSupportedErr when importing a document")
680
681def testImportDocumentShallow():
682 check_import_document(0, "testImportDocumentShallow")
683
684def testImportDocumentDeep():
685 check_import_document(1, "testImportDocumentDeep")
686
687# The tests of DocumentType importing use these helpers to construct
688# the documents to work with, since not all DOM builders actually
689# create the DocumentType nodes.
690
691def create_doc_without_doctype(doctype=None):
692 return getDOMImplementation().createDocument(None, "doc", doctype)
693
694def create_nonempty_doctype():
695 doctype = getDOMImplementation().createDocumentType("doc", None, None)
696 doctype.entities._seq = []
697 doctype.notations._seq = []
698 notation = xml.dom.minidom.Notation("my-notation", None,
699 "http://xml.python.org/notations/my")
700 doctype.notations._seq.append(notation)
701 entity = xml.dom.minidom.Entity("my-entity", None,
702 "http://xml.python.org/entities/my",
703 "my-notation")
704 entity.version = "1.0"
705 entity.encoding = "utf-8"
706 entity.actualEncoding = "us-ascii"
707 doctype.entities._seq.append(entity)
708 return doctype
709
710def create_doc_with_doctype():
711 doctype = create_nonempty_doctype()
712 doc = create_doc_without_doctype(doctype)
713 doctype.entities.item(0).ownerDocument = doc
714 doctype.notations.item(0).ownerDocument = doc
715 return doc
716
717def testImportDocumentTypeShallow():
718 src = create_doc_with_doctype()
719 target = create_doc_without_doctype()
720 try:
721 imported = target.importNode(src.doctype, 0)
722 except xml.dom.NotSupportedErr:
723 pass
724 else:
725 raise Exception(
726 "testImportDocumentTypeShallow: expected NotSupportedErr")
727
728def testImportDocumentTypeDeep():
729 src = create_doc_with_doctype()
730 target = create_doc_without_doctype()
731 try:
732 imported = target.importNode(src.doctype, 1)
733 except xml.dom.NotSupportedErr:
734 pass
735 else:
736 raise Exception(
737 "testImportDocumentTypeDeep: expected NotSupportedErr")
738
739# Testing attribute clones uses a helper, and should always be deep,
740# even if the argument to cloneNode is false.
741def check_clone_attribute(deep, testName):
742 doc = parseString("<doc attr='value'/>")
743 attr = doc.documentElement.getAttributeNode("attr")
744 assert attr is not None
745 clone = attr.cloneNode(deep)
746 confirm(not clone.isSameNode(attr))
747 confirm(not attr.isSameNode(clone))
748 confirm(clone.ownerElement is None,
749 testName + ": ownerElement should be None")
750 confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
751 testName + ": ownerDocument does not match")
752 confirm(clone.specified,
753 testName + ": cloned attribute must have specified == True")
754
755def testCloneAttributeShallow():
756 check_clone_attribute(0, "testCloneAttributeShallow")
757
758def testCloneAttributeDeep():
759 check_clone_attribute(1, "testCloneAttributeDeep")
760
761def check_clone_pi(deep, testName):
762 doc = parseString("<?target data?><doc/>")
763 pi = doc.firstChild
764 assert pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
765 clone = pi.cloneNode(deep)
766 confirm(clone.target == pi.target
767 and clone.data == pi.data)
768
769def testClonePIShallow():
770 check_clone_pi(0, "testClonePIShallow")
771
772def testClonePIDeep():
773 check_clone_pi(1, "testClonePIDeep")
Paul Prescod7993bcc2000-07-01 14:54:16 +0000774
Fred Drakea1bde802000-11-21 22:02:43 +0000775def testNormalize():
776 doc = parseString("<doc/>")
777 root = doc.documentElement
778 root.appendChild(doc.createTextNode("first"))
779 root.appendChild(doc.createTextNode("second"))
Fred Drake946f7b12001-09-28 20:31:50 +0000780 confirm(len(root.childNodes) == 2
781 and root.childNodes.length == 2, "testNormalize -- preparation")
Fred Drakea1bde802000-11-21 22:02:43 +0000782 doc.normalize()
783 confirm(len(root.childNodes) == 1
Fred Drake946f7b12001-09-28 20:31:50 +0000784 and root.childNodes.length == 1
Fred Drakea1bde802000-11-21 22:02:43 +0000785 and root.firstChild is root.lastChild
786 and root.firstChild.data == "firstsecond"
787 , "testNormalize -- result")
788 doc.unlink()
789
Fred Drake3277da02000-12-14 18:20:22 +0000790 doc = parseString("<doc/>")
791 root = doc.documentElement
792 root.appendChild(doc.createTextNode(""))
793 doc.normalize()
Fred Drake946f7b12001-09-28 20:31:50 +0000794 confirm(len(root.childNodes) == 0
795 and root.childNodes.length == 0,
Fred Drake3277da02000-12-14 18:20:22 +0000796 "testNormalize -- single empty node removed")
797 doc.unlink()
798
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000799def testSiblings():
800 doc = parseString("<doc><?pi?>text?<elm/></doc>")
801 root = doc.documentElement
802 (pi, text, elm) = root.childNodes
Paul Prescod7993bcc2000-07-01 14:54:16 +0000803
Fred Drake004d5e62000-10-23 17:22:08 +0000804 confirm(pi.nextSibling is text and
805 pi.previousSibling is None and
806 text.nextSibling is elm and
807 text.previousSibling is pi and
808 elm.nextSibling is None and
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000809 elm.previousSibling is text, "testSiblings")
810
811 doc.unlink()
812
813def testParents():
814 doc = parseString("<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
815 root = doc.documentElement
816 elm1 = root.childNodes[0]
817 (elm2a, elm2b) = elm1.childNodes
818 elm3 = elm2b.childNodes[0]
819
820 confirm(root.parentNode is doc and
821 elm1.parentNode is root and
822 elm2a.parentNode is elm1 and
823 elm2b.parentNode is elm1 and
824 elm3.parentNode is elm2b, "testParents")
825
826 doc.unlink()
827
Fred Drake946f7b12001-09-28 20:31:50 +0000828def testNodeListItem():
829 doc = parseString("<doc><e/><e/></doc>")
830 children = doc.childNodes
831 docelem = children[0]
832 confirm(children[0] is children.item(0)
833 and children.item(1) is None
834 and docelem.childNodes.item(0) is docelem.childNodes[0]
835 and docelem.childNodes.item(1) is docelem.childNodes[1]
836 and docelem.childNodes.item(0).childNodes.item(0) is None,
837 "test NodeList.item()")
838 doc.unlink()
839
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000840def testSAX2DOM():
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000841 from xml.dom import pulldom
842
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000843 sax2dom = pulldom.SAX2DOM()
844 sax2dom.startDocument()
845 sax2dom.startElement("doc", {})
846 sax2dom.characters("text")
847 sax2dom.startElement("subelm", {})
848 sax2dom.characters("text")
849 sax2dom.endElement("subelm")
Fred Drake004d5e62000-10-23 17:22:08 +0000850 sax2dom.characters("text")
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000851 sax2dom.endElement("doc")
852 sax2dom.endDocument()
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000853
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000854 doc = sax2dom.document
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000855 root = doc.documentElement
856 (text1, elm1, text2) = root.childNodes
857 text3 = elm1.childNodes[0]
858
859 confirm(text1.previousSibling is None and
860 text1.nextSibling is elm1 and
861 elm1.previousSibling is text1 and
862 elm1.nextSibling is text2 and
863 text2.previousSibling is elm1 and
864 text2.nextSibling is None and
865 text3.previousSibling is None and
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000866 text3.nextSibling is None, "testSAX2DOM - siblings")
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000867
868 confirm(root.parentNode is doc and
869 text1.parentNode is root and
870 elm1.parentNode is root and
871 text2.parentNode is root and
Lars Gustäbel5bad5a42000-10-13 20:54:10 +0000872 text3.parentNode is elm1, "testSAX2DOM - parents")
Fred Drake004d5e62000-10-23 17:22:08 +0000873
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +0000874 doc.unlink()
875
Martin v. Löwis7d650ca2002-06-30 15:05:00 +0000876def testEncodings():
877 doc = parseString('<foo>&#x20ac;</foo>')
878 confirm(doc.toxml() == u'<?xml version="1.0" ?>\n<foo>\u20ac</foo>'
879 and doc.toxml('utf-8') == '<?xml version="1.0" encoding="utf-8"?>\n<foo>\xe2\x82\xac</foo>'
880 and doc.toxml('iso-8859-15') == '<?xml version="1.0" encoding="iso-8859-15"?>\n<foo>\xa4</foo>',
881 "testEncodings - encoding EURO SIGN")
882 doc.unlink()
883
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +0000884class UserDataHandler:
885 called = 0
886 def handle(self, operation, key, data, src, dst):
887 dst.setUserData(key, data + 1, self)
888 src.setUserData(key, None, None)
889 self.called = 1
890
891def testUserData():
892 dom = Document()
893 n = dom.createElement('e')
894 confirm(n.getUserData("foo") is None)
895 n.setUserData("foo", None, None)
896 confirm(n.getUserData("foo") is None)
897 n.setUserData("foo", 12, 12)
898 n.setUserData("bar", 13, 13)
899 confirm(n.getUserData("foo") == 12)
900 confirm(n.getUserData("bar") == 13)
901 n.setUserData("foo", None, None)
902 confirm(n.getUserData("foo") is None)
903 confirm(n.getUserData("bar") == 13)
904
905 handler = UserDataHandler()
906 n.setUserData("bar", 12, handler)
907 c = n.cloneNode(1)
908 confirm(handler.called
909 and n.getUserData("bar") is None
910 and c.getUserData("bar") == 13)
911 n.unlink()
912 c.unlink()
913 dom.unlink()
914
915def testRenameAttribute():
916 doc = parseString("<doc a='v'/>")
917 elem = doc.documentElement
918 attrmap = elem.attributes
919 attr = elem.attributes['a']
920
921 # Simple renaming
922 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
923 confirm(attr.name == "b"
924 and attr.nodeName == "b"
925 and attr.localName is None
926 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
927 and attr.prefix is None
928 and attr.value == "v"
929 and elem.getAttributeNode("a") is None
930 and elem.getAttributeNode("b").isSameNode(attr)
931 and attrmap["b"].isSameNode(attr)
932 and attr.ownerDocument.isSameNode(doc)
933 and attr.ownerElement.isSameNode(elem))
934
935 # Rename to have a namespace, no prefix
936 attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
937 confirm(attr.name == "c"
938 and attr.nodeName == "c"
939 and attr.localName == "c"
940 and attr.namespaceURI == "http://xml.python.org/ns"
941 and attr.prefix is None
942 and attr.value == "v"
943 and elem.getAttributeNode("a") is None
944 and elem.getAttributeNode("b") is None
945 and elem.getAttributeNode("c").isSameNode(attr)
946 and elem.getAttributeNodeNS(
947 "http://xml.python.org/ns", "c").isSameNode(attr)
948 and attrmap["c"].isSameNode(attr)
949 and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
950
951 # Rename to have a namespace, with prefix
952 attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
953 confirm(attr.name == "p:d"
954 and attr.nodeName == "p:d"
955 and attr.localName == "d"
956 and attr.namespaceURI == "http://xml.python.org/ns2"
957 and attr.prefix == "p"
958 and attr.value == "v"
959 and elem.getAttributeNode("a") is None
960 and elem.getAttributeNode("b") is None
961 and elem.getAttributeNode("c") is None
962 and elem.getAttributeNodeNS(
963 "http://xml.python.org/ns", "c") is None
964 and elem.getAttributeNode("p:d").isSameNode(attr)
965 and elem.getAttributeNodeNS(
966 "http://xml.python.org/ns2", "d").isSameNode(attr)
967 and attrmap["p:d"].isSameNode(attr)
968 and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
969
970 # Rename back to a simple non-NS node
971 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
972 confirm(attr.name == "e"
973 and attr.nodeName == "e"
974 and attr.localName is None
975 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
976 and attr.prefix is None
977 and attr.value == "v"
978 and elem.getAttributeNode("a") is None
979 and elem.getAttributeNode("b") is None
980 and elem.getAttributeNode("c") is None
981 and elem.getAttributeNode("p:d") is None
982 and elem.getAttributeNodeNS(
983 "http://xml.python.org/ns", "c") is None
984 and elem.getAttributeNode("e").isSameNode(attr)
985 and attrmap["e"].isSameNode(attr))
986
987 try:
988 doc.renameNode(attr, "http://xml.python.org/ns", "xmlns")
989 except xml.dom.NamespaceErr:
990 pass
991 else:
992 print "expected NamespaceErr"
993
994 checkRenameNodeSharedConstraints(doc, attr)
995 doc.unlink()
996
997def testRenameElement():
998 doc = parseString("<doc/>")
999 elem = doc.documentElement
1000
1001 # Simple renaming
1002 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
1003 confirm(elem.tagName == "a"
1004 and elem.nodeName == "a"
1005 and elem.localName is None
1006 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1007 and elem.prefix is None
1008 and elem.ownerDocument.isSameNode(doc))
1009
1010 # Rename to have a namespace, no prefix
1011 elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
1012 confirm(elem.tagName == "b"
1013 and elem.nodeName == "b"
1014 and elem.localName == "b"
1015 and elem.namespaceURI == "http://xml.python.org/ns"
1016 and elem.prefix is None
1017 and elem.ownerDocument.isSameNode(doc))
1018
1019 # Rename to have a namespace, with prefix
1020 elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
1021 confirm(elem.tagName == "p:c"
1022 and elem.nodeName == "p:c"
1023 and elem.localName == "c"
1024 and elem.namespaceURI == "http://xml.python.org/ns2"
1025 and elem.prefix == "p"
1026 and elem.ownerDocument.isSameNode(doc))
1027
1028 # Rename back to a simple non-NS node
1029 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
1030 confirm(elem.tagName == "d"
1031 and elem.nodeName == "d"
1032 and elem.localName is None
1033 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1034 and elem.prefix is None
1035 and elem.ownerDocument.isSameNode(doc))
1036
1037 checkRenameNodeSharedConstraints(doc, elem)
1038 doc.unlink()
1039
1040def checkRenameNodeSharedConstraints(doc, node):
1041 # Make sure illegal NS usage is detected:
1042 try:
1043 doc.renameNode(node, "http://xml.python.org/ns", "xmlns:foo")
1044 except xml.dom.NamespaceErr:
1045 pass
1046 else:
1047 print "expected NamespaceErr"
1048
1049 doc2 = parseString("<doc/>")
1050 try:
1051 doc2.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo")
1052 except xml.dom.WrongDocumentErr:
1053 pass
1054 else:
1055 print "expected WrongDocumentErr"
1056
1057def testRenameOther():
1058 # We have to create a comment node explicitly since not all DOM
1059 # builders used with minidom add comments to the DOM.
1060 doc = xml.dom.minidom.getDOMImplementation().createDocument(
1061 xml.dom.EMPTY_NAMESPACE, "e", None)
1062 node = doc.createComment("comment")
1063 try:
1064 doc.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo")
1065 except xml.dom.NotSupportedErr:
1066 pass
1067 else:
1068 print "expected NotSupportedErr when renaming comment node"
1069 doc.unlink()
1070
1071def checkWholeText(node, s):
1072 t = node.wholeText
1073 confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
1074
1075def testWholeText():
1076 doc = parseString("<doc>a</doc>")
1077 elem = doc.documentElement
1078 text = elem.childNodes[0]
1079 assert text.nodeType == Node.TEXT_NODE
1080
1081 checkWholeText(text, "a")
1082 elem.appendChild(doc.createTextNode("b"))
1083 checkWholeText(text, "ab")
1084 elem.insertBefore(doc.createCDATASection("c"), text)
1085 checkWholeText(text, "cab")
1086
1087 # make sure we don't cross other nodes
1088 splitter = doc.createComment("comment")
1089 elem.appendChild(splitter)
1090 text2 = doc.createTextNode("d")
1091 elem.appendChild(text2)
1092 checkWholeText(text, "cab")
1093 checkWholeText(text2, "d")
1094
1095 x = doc.createElement("x")
1096 elem.replaceChild(x, splitter)
1097 splitter = x
1098 checkWholeText(text, "cab")
1099 checkWholeText(text2, "d")
1100
1101 x = doc.createProcessingInstruction("y", "z")
1102 elem.replaceChild(x, splitter)
1103 splitter = x
1104 checkWholeText(text, "cab")
1105 checkWholeText(text2, "d")
1106
1107 elem.removeChild(splitter)
1108 checkWholeText(text, "cabd")
1109 checkWholeText(text2, "cabd")
1110
1111def testReplaceWholeText():
1112 def setup():
1113 doc = parseString("<doc>a<e/>d</doc>")
1114 elem = doc.documentElement
1115 text1 = elem.firstChild
1116 text2 = elem.lastChild
1117 splitter = text1.nextSibling
1118 elem.insertBefore(doc.createTextNode("b"), splitter)
1119 elem.insertBefore(doc.createCDATASection("c"), text1)
1120 return doc, elem, text1, splitter, text2
1121
1122 doc, elem, text1, splitter, text2 = setup()
1123 text = text1.replaceWholeText("new content")
1124 checkWholeText(text, "new content")
1125 checkWholeText(text2, "d")
1126 confirm(len(elem.childNodes) == 3)
1127
1128 doc, elem, text1, splitter, text2 = setup()
1129 text = text2.replaceWholeText("new content")
1130 checkWholeText(text, "new content")
1131 checkWholeText(text1, "cab")
1132 confirm(len(elem.childNodes) == 5)
1133
1134 doc, elem, text1, splitter, text2 = setup()
1135 text = text1.replaceWholeText("")
1136 checkWholeText(text2, "d")
1137 confirm(text is None
1138 and len(elem.childNodes) == 2)
1139
1140def testSchemaType():
1141 doc = parseString(
1142 "<!DOCTYPE doc [\n"
1143 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
1144 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
1145 " <!ATTLIST doc id ID #IMPLIED \n"
1146 " ref IDREF #IMPLIED \n"
1147 " refs IDREFS #IMPLIED \n"
1148 " enum (a|b) #IMPLIED \n"
1149 " ent ENTITY #IMPLIED \n"
1150 " ents ENTITIES #IMPLIED \n"
1151 " nm NMTOKEN #IMPLIED \n"
1152 " nms NMTOKENS #IMPLIED \n"
1153 " text CDATA #IMPLIED \n"
1154 " >\n"
1155 "]><doc id='name' notid='name' text='splat!' enum='b'"
1156 " ref='name' refs='name name' ent='e1' ents='e1 e2'"
1157 " nm='123' nms='123 abc' />")
1158 elem = doc.documentElement
1159 # We don't want to rely on any specific loader at this point, so
1160 # just make sure we can get to all the names, and that the
1161 # DTD-based namespace is right. The names can vary by loader
1162 # since each supports a different level of DTD information.
1163 t = elem.schemaType
1164 confirm(t.name is None
1165 and t.namespace == xml.dom.EMPTY_NAMESPACE)
1166 names = "id notid text enum ref refs ent ents nm nms".split()
1167 for name in names:
1168 a = elem.getAttributeNode(name)
1169 t = a.schemaType
1170 confirm(hasattr(t, "name")
1171 and t.namespace == xml.dom.EMPTY_NAMESPACE)
1172
1173def testSetIdAttribute():
1174 doc = parseString("<doc a1='v' a2='w'/>")
1175 e = doc.documentElement
1176 a1 = e.getAttributeNode("a1")
1177 a2 = e.getAttributeNode("a2")
1178 confirm(doc.getElementById("v") is None
1179 and not a1.isId
1180 and not a2.isId)
1181 e.setIdAttribute("a1")
1182 confirm(e.isSameNode(doc.getElementById("v"))
1183 and a1.isId
1184 and not a2.isId)
1185 e.setIdAttribute("a2")
1186 confirm(e.isSameNode(doc.getElementById("v"))
1187 and e.isSameNode(doc.getElementById("w"))
1188 and a1.isId
1189 and a2.isId)
1190 # replace the a1 node; the new node should *not* be an ID
1191 a3 = doc.createAttribute("a1")
1192 a3.value = "v"
1193 e.setAttributeNode(a3)
1194 confirm(doc.getElementById("v") is None
1195 and e.isSameNode(doc.getElementById("w"))
1196 and not a1.isId
1197 and a2.isId
1198 and not a3.isId)
1199 # renaming an attribute should not affect it's ID-ness:
1200 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1201 confirm(e.isSameNode(doc.getElementById("w"))
1202 and a2.isId)
1203
1204def testSetIdAttributeNS():
1205 NS1 = "http://xml.python.org/ns1"
1206 NS2 = "http://xml.python.org/ns2"
1207 doc = parseString("<doc"
1208 " xmlns:ns1='" + NS1 + "'"
1209 " xmlns:ns2='" + NS2 + "'"
1210 " ns1:a1='v' ns2:a2='w'/>")
1211 e = doc.documentElement
1212 a1 = e.getAttributeNodeNS(NS1, "a1")
1213 a2 = e.getAttributeNodeNS(NS2, "a2")
1214 confirm(doc.getElementById("v") is None
1215 and not a1.isId
1216 and not a2.isId)
1217 e.setIdAttributeNS(NS1, "a1")
1218 confirm(e.isSameNode(doc.getElementById("v"))
1219 and a1.isId
1220 and not a2.isId)
1221 e.setIdAttributeNS(NS2, "a2")
1222 confirm(e.isSameNode(doc.getElementById("v"))
1223 and e.isSameNode(doc.getElementById("w"))
1224 and a1.isId
1225 and a2.isId)
1226 # replace the a1 node; the new node should *not* be an ID
1227 a3 = doc.createAttributeNS(NS1, "a1")
1228 a3.value = "v"
1229 e.setAttributeNode(a3)
1230 confirm(e.isSameNode(doc.getElementById("w")))
1231 confirm(not a1.isId)
1232 confirm(a2.isId)
1233 confirm(not a3.isId)
1234 confirm(doc.getElementById("v") is None)
1235 # renaming an attribute should not affect it's ID-ness:
1236 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1237 confirm(e.isSameNode(doc.getElementById("w"))
1238 and a2.isId)
1239
1240def testSetIdAttributeNode():
1241 NS1 = "http://xml.python.org/ns1"
1242 NS2 = "http://xml.python.org/ns2"
1243 doc = parseString("<doc"
1244 " xmlns:ns1='" + NS1 + "'"
1245 " xmlns:ns2='" + NS2 + "'"
1246 " ns1:a1='v' ns2:a2='w'/>")
1247 e = doc.documentElement
1248 a1 = e.getAttributeNodeNS(NS1, "a1")
1249 a2 = e.getAttributeNodeNS(NS2, "a2")
1250 confirm(doc.getElementById("v") is None
1251 and not a1.isId
1252 and not a2.isId)
1253 e.setIdAttributeNode(a1)
1254 confirm(e.isSameNode(doc.getElementById("v"))
1255 and a1.isId
1256 and not a2.isId)
1257 e.setIdAttributeNode(a2)
1258 confirm(e.isSameNode(doc.getElementById("v"))
1259 and e.isSameNode(doc.getElementById("w"))
1260 and a1.isId
1261 and a2.isId)
1262 # replace the a1 node; the new node should *not* be an ID
1263 a3 = doc.createAttributeNS(NS1, "a1")
1264 a3.value = "v"
1265 e.setAttributeNode(a3)
1266 confirm(e.isSameNode(doc.getElementById("w")))
1267 confirm(not a1.isId)
1268 confirm(a2.isId)
1269 confirm(not a3.isId)
1270 confirm(doc.getElementById("v") is None)
1271 # renaming an attribute should not affect it's ID-ness:
1272 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1273 confirm(e.isSameNode(doc.getElementById("w"))
1274 and a2.isId)
1275
1276def testPickledDocument():
1277 doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
1278 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
1279 " 'http://xml.python.org/system' [\n"
1280 " <!ELEMENT e EMPTY>\n"
1281 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
1282 "]><doc attr='value'> text\n"
1283 "<?pi sample?> <!-- comment --> <e/> </doc>")
1284 s = pickle.dumps(doc)
1285 doc2 = pickle.loads(s)
1286 stack = [(doc, doc2)]
1287 while stack:
1288 n1, n2 = stack.pop()
1289 confirm(n1.nodeType == n2.nodeType
1290 and len(n1.childNodes) == len(n2.childNodes)
1291 and n1.nodeName == n2.nodeName
1292 and not n1.isSameNode(n2)
1293 and not n2.isSameNode(n1))
1294 if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
1295 len(n1.entities)
1296 len(n2.entities)
1297 len(n1.notations)
1298 len(n2.notations)
1299 confirm(len(n1.entities) == len(n2.entities)
1300 and len(n1.notations) == len(n2.notations))
1301 for i in range(len(n1.notations)):
1302 no1 = n1.notations.item(i)
1303 no2 = n1.notations.item(i)
1304 confirm(no1.name == no2.name
1305 and no1.publicId == no2.publicId
1306 and no1.systemId == no2.systemId)
1307 statck.append((no1, no2))
1308 for i in range(len(n1.entities)):
1309 e1 = n1.entities.item(i)
1310 e2 = n2.entities.item(i)
1311 confirm(e1.notationName == e2.notationName
1312 and e1.publicId == e2.publicId
1313 and e1.systemId == e2.systemId)
1314 stack.append((e1, e2))
1315 if n1.nodeType != Node.DOCUMENT_NODE:
1316 confirm(n1.ownerDocument.isSameNode(doc)
1317 and n2.ownerDocument.isSameNode(doc2))
1318 for i in range(len(n1.childNodes)):
1319 stack.append((n1.childNodes[i], n2.childNodes[i]))
1320
1321
Lars Gustäbelf27f5ab2000-10-11 22:36:00 +00001322# --- MAIN PROGRAM
Fred Drake004d5e62000-10-23 17:22:08 +00001323
Jeremy Hylton3b0c6002000-10-12 17:31:36 +00001324names = globals().keys()
Paul Prescod7993bcc2000-07-01 14:54:16 +00001325names.sort()
Paul Prescod10d27662000-09-18 19:07:26 +00001326
Fred Drakeacfb3f62001-02-01 18:11:29 +00001327failed = []
Paul Prescod10d27662000-09-18 19:07:26 +00001328
Fred Drake6dd7d072002-09-12 17:03:02 +00001329try:
1330 Node.allnodes
1331except AttributeError:
1332 # We don't actually have the minidom from teh standard library,
1333 # but are picking up the PyXML version from site-packages.
1334 def check_allnodes():
1335 pass
1336else:
1337 def check_allnodes():
1338 confirm(len(Node.allnodes) == 0,
1339 "assertion: len(Node.allnodes) == 0")
1340 if len(Node.allnodes):
1341 print "Garbage left over:"
1342 if verbose:
1343 print Node.allnodes.items()[0:10]
1344 else:
1345 # Don't print specific nodes if repeatable results
1346 # are needed
1347 print len(Node.allnodes)
1348 Node.allnodes = {}
1349
Paul Prescod7993bcc2000-07-01 14:54:16 +00001350for name in names:
Jeremy Hylton3b0c6002000-10-12 17:31:36 +00001351 if name.startswith("test"):
1352 func = globals()[name]
Paul Prescod7993bcc2000-07-01 14:54:16 +00001353 try:
1354 func()
Fred Drake6dd7d072002-09-12 17:03:02 +00001355 check_allnodes()
Fred Drakeacfb3f62001-02-01 18:11:29 +00001356 except:
1357 failed.append(name)
Paul Prescod7993bcc2000-07-01 14:54:16 +00001358 print "Test Failed: ", name
Fred Drake1703cf62000-12-15 21:31:59 +00001359 sys.stdout.flush()
Jeremy Hylton3b0c6002000-10-12 17:31:36 +00001360 traceback.print_exception(*sys.exc_info())
Fred Drakeacfb3f62001-02-01 18:11:29 +00001361 print `sys.exc_info()[1]`
Jeremy Hylton3b0c6002000-10-12 17:31:36 +00001362 Node.allnodes = {}
Paul Prescod10d27662000-09-18 19:07:26 +00001363
Fred Drakeacfb3f62001-02-01 18:11:29 +00001364if failed:
1365 print "\n\n\n**** Check for failures in these tests:"
1366 for name in failed:
1367 print " " + name