Fix the availability statement for the spawn*() functions to reflect the
[python/dscho.git] / Lib / test / test_minidom.py
blob4483fc5022bbf8e316537984110037f318b198e2
1 # test for xml.dom.minidom
3 from xml.dom.minidom import parse, Node, Document, parseString
4 from xml.dom import HierarchyRequestErr
5 import xml.parsers.expat
7 import os
8 import sys
9 import traceback
10 from test_support import verbose
12 if __name__ == "__main__":
13 base = sys.argv[0]
14 else:
15 base = __file__
16 tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml")
17 del base
19 def confirm(test, testname = "Test"):
20 if test:
21 print "Passed " + testname
22 else:
23 print "Failed " + testname
24 raise Exception
26 Node._debug = 1
28 def testParseFromFile():
29 from StringIO import StringIO
30 dom = parse(StringIO(open(tstfile).read()))
31 dom.unlink()
32 confirm(isinstance(dom,Document))
34 def testGetElementsByTagName():
35 dom = parse(tstfile)
36 confirm(dom.getElementsByTagName("LI") == \
37 dom.documentElement.getElementsByTagName("LI"))
38 dom.unlink()
40 def testInsertBefore():
41 dom = parseString("<doc><foo/></doc>")
42 root = dom.documentElement
43 elem = root.childNodes[0]
44 nelem = dom.createElement("element")
45 root.insertBefore(nelem, elem)
46 confirm(len(root.childNodes) == 2
47 and root.childNodes.length == 2
48 and root.childNodes[0] is nelem
49 and root.childNodes.item(0) is nelem
50 and root.childNodes[1] is elem
51 and root.childNodes.item(1) is elem
52 and root.firstChild is nelem
53 and root.lastChild is elem
54 and root.toxml() == "<doc><element/><foo/></doc>"
55 , "testInsertBefore -- node properly placed in tree")
56 nelem = dom.createElement("element")
57 root.insertBefore(nelem, None)
58 confirm(len(root.childNodes) == 3
59 and root.childNodes.length == 3
60 and root.childNodes[1] is elem
61 and root.childNodes.item(1) is elem
62 and root.childNodes[2] is nelem
63 and root.childNodes.item(2) is nelem
64 and root.lastChild is nelem
65 and nelem.previousSibling is elem
66 and root.toxml() == "<doc><element/><foo/><element/></doc>"
67 , "testInsertBefore -- node properly placed in tree")
68 nelem2 = dom.createElement("bar")
69 root.insertBefore(nelem2, nelem)
70 confirm(len(root.childNodes) == 4
71 and root.childNodes.length == 4
72 and root.childNodes[2] is nelem2
73 and root.childNodes.item(2) is nelem2
74 and root.childNodes[3] is nelem
75 and root.childNodes.item(3) is nelem
76 and nelem2.nextSibling is nelem
77 and nelem.previousSibling is nelem2
78 and root.toxml() == "<doc><element/><foo/><bar/><element/></doc>"
79 , "testInsertBefore -- node properly placed in tree")
80 dom.unlink()
82 def _create_fragment_test_nodes():
83 dom = parseString("<doc/>")
84 orig = dom.createTextNode("original")
85 c1 = dom.createTextNode("foo")
86 c2 = dom.createTextNode("bar")
87 c3 = dom.createTextNode("bat")
88 dom.documentElement.appendChild(orig)
89 frag = dom.createDocumentFragment()
90 frag.appendChild(c1)
91 frag.appendChild(c2)
92 frag.appendChild(c3)
93 return dom, orig, c1, c2, c3, frag
95 def testInsertBeforeFragment():
96 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
97 dom.documentElement.insertBefore(frag, None)
98 confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
99 "insertBefore(<fragment>, None)")
100 frag.unlink()
101 dom.unlink()
103 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
104 dom.documentElement.insertBefore(frag, orig)
105 confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig),
106 "insertBefore(<fragment>, orig)")
107 frag.unlink()
108 dom.unlink()
110 def testAppendChild():
111 dom = parse(tstfile)
112 dom.documentElement.appendChild(dom.createComment(u"Hello"))
113 confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
114 confirm(dom.documentElement.childNodes[-1].data == "Hello")
115 dom.unlink()
117 def testAppendChildFragment():
118 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
119 dom.documentElement.appendChild(frag)
120 confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3),
121 "appendChild(<fragment>)")
122 frag.unlink()
123 dom.unlink()
125 def testReplaceChildFragment():
126 dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes()
127 dom.documentElement.replaceChild(frag, orig)
128 orig.unlink()
129 confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
130 "replaceChild(<fragment>)")
131 frag.unlink()
132 dom.unlink()
134 def testLegalChildren():
135 dom = Document()
136 elem = dom.createElement('element')
137 text = dom.createTextNode('text')
139 try: dom.appendChild(text)
140 except HierarchyRequestErr: pass
141 else:
142 print "dom.appendChild didn't raise HierarchyRequestErr"
144 dom.appendChild(elem)
145 try: dom.insertBefore(text, elem)
146 except HierarchyRequestErr: pass
147 else:
148 print "dom.appendChild didn't raise HierarchyRequestErr"
150 try: dom.replaceChild(text, elem)
151 except HierarchyRequestErr: pass
152 else:
153 print "dom.appendChild didn't raise HierarchyRequestErr"
155 nodemap = elem.attributes
156 try: nodemap.setNamedItem(text)
157 except HierarchyRequestErr: pass
158 else:
159 print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr"
161 try: nodemap.setNamedItemNS(text)
162 except HierarchyRequestErr: pass
163 else:
164 print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr"
166 elem.appendChild(text)
167 dom.unlink()
169 def testNamedNodeMapSetItem():
170 dom = Document()
171 elem = dom.createElement('element')
172 attrs = elem.attributes
173 attrs["foo"] = "bar"
174 a = attrs.item(0)
175 confirm(a.ownerDocument is dom,
176 "NamedNodeMap.__setitem__() sets ownerDocument")
177 confirm(a.ownerElement is elem,
178 "NamedNodeMap.__setitem__() sets ownerElement")
179 confirm(a.value == "bar",
180 "NamedNodeMap.__setitem__() sets value")
181 confirm(a.nodeValue == "bar",
182 "NamedNodeMap.__setitem__() sets nodeValue")
183 elem.unlink()
184 dom.unlink()
186 def testNonZero():
187 dom = parse(tstfile)
188 confirm(dom)# should not be zero
189 dom.appendChild(dom.createComment("foo"))
190 confirm(not dom.childNodes[-1].childNodes)
191 dom.unlink()
193 def testUnlink():
194 dom = parse(tstfile)
195 dom.unlink()
197 def testElement():
198 dom = Document()
199 dom.appendChild(dom.createElement("abc"))
200 confirm(dom.documentElement)
201 dom.unlink()
203 def testAAA():
204 dom = parseString("<abc/>")
205 el = dom.documentElement
206 el.setAttribute("spam", "jam2")
207 confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
208 a = el.getAttributeNode("spam")
209 confirm(a.ownerDocument is dom,
210 "setAttribute() sets ownerDocument")
211 confirm(a.ownerElement is dom.documentElement,
212 "setAttribute() sets ownerElement")
213 dom.unlink()
215 def testAAB():
216 dom = parseString("<abc/>")
217 el = dom.documentElement
218 el.setAttribute("spam", "jam")
219 el.setAttribute("spam", "jam2")
220 confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
221 dom.unlink()
223 def testAddAttr():
224 dom = Document()
225 child = dom.appendChild(dom.createElement("abc"))
227 child.setAttribute("def", "ghi")
228 confirm(child.getAttribute("def") == "ghi")
229 confirm(child.attributes["def"].value == "ghi")
231 child.setAttribute("jkl", "mno")
232 confirm(child.getAttribute("jkl") == "mno")
233 confirm(child.attributes["jkl"].value == "mno")
235 confirm(len(child.attributes) == 2)
237 child.setAttribute("def", "newval")
238 confirm(child.getAttribute("def") == "newval")
239 confirm(child.attributes["def"].value == "newval")
241 confirm(len(child.attributes) == 2)
242 dom.unlink()
244 def testDeleteAttr():
245 dom = Document()
246 child = dom.appendChild(dom.createElement("abc"))
248 confirm(len(child.attributes) == 0)
249 child.setAttribute("def", "ghi")
250 confirm(len(child.attributes) == 1)
251 del child.attributes["def"]
252 confirm(len(child.attributes) == 0)
253 dom.unlink()
255 def testRemoveAttr():
256 dom = Document()
257 child = dom.appendChild(dom.createElement("abc"))
259 child.setAttribute("def", "ghi")
260 confirm(len(child.attributes) == 1)
261 child.removeAttribute("def")
262 confirm(len(child.attributes) == 0)
264 dom.unlink()
266 def testRemoveAttrNS():
267 dom = Document()
268 child = dom.appendChild(
269 dom.createElementNS("http://www.python.org", "python:abc"))
270 child.setAttributeNS("http://www.w3.org", "xmlns:python",
271 "http://www.python.org")
272 child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
273 confirm(len(child.attributes) == 2)
274 child.removeAttributeNS("http://www.python.org", "abcattr")
275 confirm(len(child.attributes) == 1)
277 dom.unlink()
279 def testRemoveAttributeNode():
280 dom = Document()
281 child = dom.appendChild(dom.createElement("foo"))
282 child.setAttribute("spam", "jam")
283 confirm(len(child.attributes) == 1)
284 node = child.getAttributeNode("spam")
285 child.removeAttributeNode(node)
286 confirm(len(child.attributes) == 0)
288 dom.unlink()
290 def testChangeAttr():
291 dom = parseString("<abc/>")
292 el = dom.documentElement
293 el.setAttribute("spam", "jam")
294 confirm(len(el.attributes) == 1)
295 el.setAttribute("spam", "bam")
296 confirm(len(el.attributes) == 1)
297 el.attributes["spam"] = "ham"
298 confirm(len(el.attributes) == 1)
299 el.setAttribute("spam2", "bam")
300 confirm(len(el.attributes) == 2)
301 el.attributes[ "spam2"] = "bam2"
302 confirm(len(el.attributes) == 2)
303 dom.unlink()
305 def testGetAttrList():
306 pass
308 def testGetAttrValues(): pass
310 def testGetAttrLength(): pass
312 def testGetAttribute(): pass
314 def testGetAttributeNS(): pass
316 def testGetAttributeNode(): pass
318 def testGetElementsByTagNameNS():
319 d="""<foo xmlns:minidom="http://pyxml.sf.net/minidom">
320 <minidom:myelem/>
321 </foo>"""
322 dom = parseString(d)
323 elem = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom","myelem")
324 confirm(len(elem) == 1)
325 dom.unlink()
327 def testGetEmptyNodeListFromElementsByTagNameNS(): pass
329 def testElementReprAndStr():
330 dom = Document()
331 el = dom.appendChild(dom.createElement("abc"))
332 string1 = repr(el)
333 string2 = str(el)
334 confirm(string1 == string2)
335 dom.unlink()
337 # commented out until Fredrick's fix is checked in
338 def _testElementReprAndStrUnicode():
339 dom = Document()
340 el = dom.appendChild(dom.createElement(u"abc"))
341 string1 = repr(el)
342 string2 = str(el)
343 confirm(string1 == string2)
344 dom.unlink()
346 # commented out until Fredrick's fix is checked in
347 def _testElementReprAndStrUnicodeNS():
348 dom = Document()
349 el = dom.appendChild(
350 dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
351 string1 = repr(el)
352 string2 = str(el)
353 confirm(string1 == string2)
354 confirm(string1.find("slash:abc") != -1)
355 dom.unlink()
356 confirm(len(Node.allnodes) == 0)
358 def testAttributeRepr():
359 dom = Document()
360 el = dom.appendChild(dom.createElement(u"abc"))
361 node = el.setAttribute("abc", "def")
362 confirm(str(node) == repr(node))
363 dom.unlink()
364 confirm(len(Node.allnodes) == 0)
366 def testTextNodeRepr(): pass
368 def testWriteXML():
369 str = '<?xml version="1.0" ?>\n<a b="c"/>'
370 dom = parseString(str)
371 domstr = dom.toxml()
372 dom.unlink()
373 confirm(str == domstr)
374 confirm(len(Node.allnodes) == 0)
376 def testProcessingInstruction(): pass
378 def testProcessingInstructionRepr(): pass
380 def testTextRepr(): pass
382 def testWriteText(): pass
384 def testDocumentElement(): pass
386 def testTooManyDocumentElements():
387 doc = parseString("<doc/>")
388 elem = doc.createElement("extra")
389 try:
390 doc.appendChild(elem)
391 except HierarchyRequestErr:
392 print "Caught expected exception when adding extra document element."
393 else:
394 print "Failed to catch expected exception when" \
395 " adding extra document element."
396 elem.unlink()
397 doc.unlink()
399 def testCreateElementNS(): pass
401 def testCreateAttributeNS(): pass
403 def testParse(): pass
405 def testParseString(): pass
407 def testComment(): pass
409 def testAttrListItem(): pass
411 def testAttrListItems(): pass
413 def testAttrListItemNS(): pass
415 def testAttrListKeys(): pass
417 def testAttrListKeysNS(): pass
419 def testAttrListValues(): pass
421 def testAttrListLength(): pass
423 def testAttrList__getitem__(): pass
425 def testAttrList__setitem__(): pass
427 def testSetAttrValueandNodeValue(): pass
429 def testParseElement(): pass
431 def testParseAttributes(): pass
433 def testParseElementNamespaces(): pass
435 def testParseAttributeNamespaces(): pass
437 def testParseProcessingInstructions(): pass
439 def testChildNodes(): pass
441 def testFirstChild(): pass
443 def testHasChildNodes(): pass
445 def testCloneElementShallow():
446 dom, clone = _setupCloneElement(0)
447 confirm(len(clone.childNodes) == 0
448 and clone.childNodes.length == 0
449 and clone.parentNode is None
450 and clone.toxml() == '<doc attr="value"/>'
451 , "testCloneElementShallow")
452 dom.unlink()
454 def testCloneElementDeep():
455 dom, clone = _setupCloneElement(1)
456 confirm(len(clone.childNodes) == 1
457 and clone.childNodes.length == 1
458 and clone.parentNode is None
459 and clone.toxml() == '<doc attr="value"><foo/></doc>'
460 , "testCloneElementDeep")
461 dom.unlink()
463 def _setupCloneElement(deep):
464 dom = parseString("<doc attr='value'><foo/></doc>")
465 root = dom.documentElement
466 clone = root.cloneNode(deep)
467 _testCloneElementCopiesAttributes(
468 root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
469 # mutilate the original so shared data is detected
470 root.tagName = root.nodeName = "MODIFIED"
471 root.setAttribute("attr", "NEW VALUE")
472 root.setAttribute("added", "VALUE")
473 return dom, clone
475 def _testCloneElementCopiesAttributes(e1, e2, test):
476 attrs1 = e1.attributes
477 attrs2 = e2.attributes
478 keys1 = attrs1.keys()
479 keys2 = attrs2.keys()
480 keys1.sort()
481 keys2.sort()
482 confirm(keys1 == keys2, "clone of element has same attribute keys")
483 for i in range(len(keys1)):
484 a1 = attrs1.item(i)
485 a2 = attrs2.item(i)
486 confirm(a1 is not a2
487 and a1.value == a2.value
488 and a1.nodeValue == a2.nodeValue
489 and a1.namespaceURI == a2.namespaceURI
490 and a1.localName == a2.localName
491 , "clone of attribute node has proper attribute values")
492 confirm(a2.ownerElement is e2,
493 "clone of attribute node correctly owned")
496 def testCloneDocumentShallow(): pass
498 def testCloneDocumentDeep(): pass
500 def testCloneAttributeShallow(): pass
502 def testCloneAttributeDeep(): pass
504 def testClonePIShallow(): pass
506 def testClonePIDeep(): pass
508 def testNormalize():
509 doc = parseString("<doc/>")
510 root = doc.documentElement
511 root.appendChild(doc.createTextNode("first"))
512 root.appendChild(doc.createTextNode("second"))
513 confirm(len(root.childNodes) == 2
514 and root.childNodes.length == 2, "testNormalize -- preparation")
515 doc.normalize()
516 confirm(len(root.childNodes) == 1
517 and root.childNodes.length == 1
518 and root.firstChild is root.lastChild
519 and root.firstChild.data == "firstsecond"
520 , "testNormalize -- result")
521 doc.unlink()
523 doc = parseString("<doc/>")
524 root = doc.documentElement
525 root.appendChild(doc.createTextNode(""))
526 doc.normalize()
527 confirm(len(root.childNodes) == 0
528 and root.childNodes.length == 0,
529 "testNormalize -- single empty node removed")
530 doc.unlink()
532 def testSiblings():
533 doc = parseString("<doc><?pi?>text?<elm/></doc>")
534 root = doc.documentElement
535 (pi, text, elm) = root.childNodes
537 confirm(pi.nextSibling is text and
538 pi.previousSibling is None and
539 text.nextSibling is elm and
540 text.previousSibling is pi and
541 elm.nextSibling is None and
542 elm.previousSibling is text, "testSiblings")
544 doc.unlink()
546 def testParents():
547 doc = parseString("<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
548 root = doc.documentElement
549 elm1 = root.childNodes[0]
550 (elm2a, elm2b) = elm1.childNodes
551 elm3 = elm2b.childNodes[0]
553 confirm(root.parentNode is doc and
554 elm1.parentNode is root and
555 elm2a.parentNode is elm1 and
556 elm2b.parentNode is elm1 and
557 elm3.parentNode is elm2b, "testParents")
559 doc.unlink()
561 def testNodeListItem():
562 doc = parseString("<doc><e/><e/></doc>")
563 children = doc.childNodes
564 docelem = children[0]
565 confirm(children[0] is children.item(0)
566 and children.item(1) is None
567 and docelem.childNodes.item(0) is docelem.childNodes[0]
568 and docelem.childNodes.item(1) is docelem.childNodes[1]
569 and docelem.childNodes.item(0).childNodes.item(0) is None,
570 "test NodeList.item()")
571 doc.unlink()
573 def testSAX2DOM():
574 from xml.dom import pulldom
576 sax2dom = pulldom.SAX2DOM()
577 sax2dom.startDocument()
578 sax2dom.startElement("doc", {})
579 sax2dom.characters("text")
580 sax2dom.startElement("subelm", {})
581 sax2dom.characters("text")
582 sax2dom.endElement("subelm")
583 sax2dom.characters("text")
584 sax2dom.endElement("doc")
585 sax2dom.endDocument()
587 doc = sax2dom.document
588 root = doc.documentElement
589 (text1, elm1, text2) = root.childNodes
590 text3 = elm1.childNodes[0]
592 confirm(text1.previousSibling is None and
593 text1.nextSibling is elm1 and
594 elm1.previousSibling is text1 and
595 elm1.nextSibling is text2 and
596 text2.previousSibling is elm1 and
597 text2.nextSibling is None and
598 text3.previousSibling is None and
599 text3.nextSibling is None, "testSAX2DOM - siblings")
601 confirm(root.parentNode is doc and
602 text1.parentNode is root and
603 elm1.parentNode is root and
604 text2.parentNode is root and
605 text3.parentNode is elm1, "testSAX2DOM - parents")
607 doc.unlink()
609 # --- MAIN PROGRAM
611 names = globals().keys()
612 names.sort()
614 failed = []
616 for name in names:
617 if name.startswith("test"):
618 func = globals()[name]
619 try:
620 func()
621 print "Test Succeeded", name
622 confirm(len(Node.allnodes) == 0,
623 "assertion: len(Node.allnodes) == 0")
624 if len(Node.allnodes):
625 print "Garbage left over:"
626 if verbose:
627 print Node.allnodes.items()[0:10]
628 else:
629 # Don't print specific nodes if repeatable results
630 # are needed
631 print len(Node.allnodes)
632 Node.allnodes = {}
633 except:
634 failed.append(name)
635 print "Test Failed: ", name
636 sys.stdout.flush()
637 traceback.print_exception(*sys.exc_info())
638 print `sys.exc_info()[1]`
639 Node.allnodes = {}
641 if failed:
642 print "\n\n\n**** Check for failures in these tests:"
643 for name in failed:
644 print " " + name
645 print
646 else:
647 print "All tests succeeded"
649 Node.debug = None # Delete debug output collected in a StringIO object
650 Node._debug = 0 # And reset debug mode