1 # test for xmlcore.dom.minidom
7 from StringIO
import StringIO
8 from test
.test_support
import verbose
11 import xmlcore
.dom
.minidom
12 import xmlcore
.parsers
.expat
14 from xmlcore
.dom
.minidom
import parse
, Node
, Document
, parseString
15 from xmlcore
.dom
.minidom
import getDOMImplementation
18 if __name__
== "__main__":
22 tstfile
= os
.path
.join(os
.path
.dirname(base
), "test"+os
.extsep
+"xml")
25 def confirm(test
, testname
= "Test"):
27 print "Failed " + testname
30 def testParseFromFile():
31 dom
= parse(StringIO(open(tstfile
).read()))
33 confirm(isinstance(dom
,Document
))
35 def testGetElementsByTagName():
37 confirm(dom
.getElementsByTagName("LI") == \
38 dom
.documentElement
.getElementsByTagName("LI"))
41 def testInsertBefore():
42 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
48 and root
.childNodes
.length
== 2
49 and root
.childNodes
[0] is nelem
50 and root
.childNodes
.item(0) is nelem
51 and root
.childNodes
[1] is elem
52 and root
.childNodes
.item(1) is elem
53 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
60 and root
.childNodes
.length
== 3
61 and root
.childNodes
[1] is elem
62 and root
.childNodes
.item(1) is elem
63 and root
.childNodes
[2] is nelem
64 and root
.childNodes
.item(2) is nelem
65 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
72 and root
.childNodes
.length
== 4
73 and root
.childNodes
[2] is nelem2
74 and root
.childNodes
.item(2) is nelem2
75 and root
.childNodes
[3] is nelem
76 and root
.childNodes
.item(3) is nelem
77 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")
83 def _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()
94 return dom
, orig
, c1
, c2
, c3
, frag
96 def 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)")
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)")
111 def testAppendChild():
113 dom
.documentElement
.appendChild(dom
.createComment(u
"Hello"))
114 confirm(dom
.documentElement
.childNodes
[-1].nodeName
== "#comment")
115 confirm(dom
.documentElement
.childNodes
[-1].data
== "Hello")
118 def 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>)")
126 def testReplaceChildFragment():
127 dom
, orig
, c1
, c2
, c3
, frag
= _create_fragment_test_nodes()
128 dom
.documentElement
.replaceChild(frag
, orig
)
130 confirm(tuple(dom
.documentElement
.childNodes
) == (c1
, c2
, c3
),
131 "replaceChild(<fragment>)")
135 def testLegalChildren():
137 elem
= dom
.createElement('element')
138 text
= dom
.createTextNode('text')
140 try: dom
.appendChild(text
)
141 except xmlcore
.dom
.HierarchyRequestErr
: pass
143 print "dom.appendChild didn't raise HierarchyRequestErr"
145 dom
.appendChild(elem
)
146 try: dom
.insertBefore(text
, elem
)
147 except xmlcore
.dom
.HierarchyRequestErr
: pass
149 print "dom.appendChild didn't raise HierarchyRequestErr"
151 try: dom
.replaceChild(text
, elem
)
152 except xmlcore
.dom
.HierarchyRequestErr
: pass
154 print "dom.appendChild didn't raise HierarchyRequestErr"
156 nodemap
= elem
.attributes
157 try: nodemap
.setNamedItem(text
)
158 except xmlcore
.dom
.HierarchyRequestErr
: pass
160 print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr"
162 try: nodemap
.setNamedItemNS(text
)
163 except xmlcore
.dom
.HierarchyRequestErr
: pass
165 print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr"
167 elem
.appendChild(text
)
170 def testNamedNodeMapSetItem():
172 elem
= dom
.createElement('element')
173 attrs
= elem
.attributes
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")
189 confirm(dom
)# should not be zero
190 dom
.appendChild(dom
.createComment("foo"))
191 confirm(not dom
.childNodes
[-1].childNodes
)
200 dom
.appendChild(dom
.createElement("abc"))
201 confirm(dom
.documentElement
)
205 dom
= parseString("<abc/>")
206 el
= dom
.documentElement
207 el
.setAttribute("spam", "jam2")
208 confirm(el
.toxml() == '<abc spam="jam2"/>', "testAAA")
209 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")
217 dom
= parseString("<abc/>")
218 el
= dom
.documentElement
219 el
.setAttribute("spam", "jam")
220 el
.setAttribute("spam", "jam2")
221 confirm(el
.toxml() == '<abc spam="jam2"/>', "testAAB")
226 child
= dom
.appendChild(dom
.createElement("abc"))
228 child
.setAttribute("def", "ghi")
229 confirm(child
.getAttribute("def") == "ghi")
230 confirm(child
.attributes
["def"].value
== "ghi")
232 child
.setAttribute("jkl", "mno")
233 confirm(child
.getAttribute("jkl") == "mno")
234 confirm(child
.attributes
["jkl"].value
== "mno")
236 confirm(len(child
.attributes
) == 2)
238 child
.setAttribute("def", "newval")
239 confirm(child
.getAttribute("def") == "newval")
240 confirm(child
.attributes
["def"].value
== "newval")
242 confirm(len(child
.attributes
) == 2)
245 def testDeleteAttr():
247 child
= dom
.appendChild(dom
.createElement("abc"))
249 confirm(len(child
.attributes
) == 0)
250 child
.setAttribute("def", "ghi")
251 confirm(len(child
.attributes
) == 1)
252 del child
.attributes
["def"]
253 confirm(len(child
.attributes
) == 0)
256 def testRemoveAttr():
258 child
= dom
.appendChild(dom
.createElement("abc"))
260 child
.setAttribute("def", "ghi")
261 confirm(len(child
.attributes
) == 1)
262 child
.removeAttribute("def")
263 confirm(len(child
.attributes
) == 0)
267 def testRemoveAttrNS():
269 child
= dom
.appendChild(
270 dom
.createElementNS("http://www.python.org", "python:abc"))
271 child
.setAttributeNS("http://www.w3.org", "xmlns:python",
272 "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)
280 def testRemoveAttributeNode():
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
)
287 confirm(len(child
.attributes
) == 0
288 and child
.getAttributeNode("spam") is None)
292 def testChangeAttr():
293 dom
= parseString("<abc/>")
294 el
= dom
.documentElement
295 el
.setAttribute("spam", "jam")
296 confirm(len(el
.attributes
) == 1)
297 el
.setAttribute("spam", "bam")
298 # 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
)
306 el
.attributes
["spam"] = "ham"
307 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
)
312 el
.setAttribute("spam2", "bam")
313 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")
330 def testGetAttrList():
333 def testGetAttrValues(): pass
335 def testGetAttrLength(): pass
337 def testGetAttribute(): pass
339 def testGetAttributeNS(): pass
341 def testGetAttributeNode(): pass
343 def testGetElementsByTagNameNS():
344 d
="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
348 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")
357 def get_empty_nodelist_from_elements_by_tagName_ns_helper(doc
, nsuri
, lname
):
358 nodelist
= doc
.getElementsByTagNameNS(nsuri
, lname
)
359 confirm(len(nodelist
) == 0)
361 def 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(
367 get_empty_nodelist_from_elements_by_tagName_ns_helper(
368 doc
, 'http://xml.python.org/namespaces/a', '*')
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")
378 def testElementReprAndStr():
380 el
= dom
.appendChild(dom
.createElement("abc"))
383 confirm(string1
== string2
)
386 # commented out until Fredrick's fix is checked in
387 def _testElementReprAndStrUnicode():
389 el
= dom
.appendChild(dom
.createElement(u
"abc"))
392 confirm(string1
== string2
)
395 # commented out until Fredrick's fix is checked in
396 def _testElementReprAndStrUnicodeNS():
398 el
= dom
.appendChild(
399 dom
.createElementNS(u
"http://www.slashdot.org", u
"slash:abc"))
402 confirm(string1
== string2
)
403 confirm(string1
.find("slash:abc") != -1)
406 def testAttributeRepr():
408 el
= dom
.appendChild(dom
.createElement(u
"abc"))
409 node
= el
.setAttribute("abc", "def")
410 confirm(str(node
) == repr(node
))
413 def testTextNodeRepr(): pass
416 str = '<?xml version="1.0" ?><a b="c"/>'
417 dom
= parseString(str)
420 confirm(str == domstr
)
422 def testAltNewline():
423 str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
424 dom
= parseString(str)
425 domstr
= dom
.toprettyxml(newl
="\r\n")
427 confirm(domstr
== str.replace("\n", "\r\n"))
429 def testProcessingInstruction():
430 dom
= parseString('<e><?mypi \t\n data \t\n ?></e>')
431 pi
= dom
.documentElement
.firstChild
432 confirm(pi
.target
== "mypi"
433 and pi
.data
== "data \t\n "
434 and pi
.nodeName
== "mypi"
435 and pi
.nodeType
== Node
.PROCESSING_INSTRUCTION_NODE
436 and pi
.attributes
is None
437 and not pi
.hasChildNodes()
438 and len(pi
.childNodes
) == 0
439 and pi
.firstChild
is None
440 and pi
.lastChild
is None
441 and pi
.localName
is None
442 and pi
.namespaceURI
== xmlcore
.dom
.EMPTY_NAMESPACE
)
444 def testProcessingInstructionRepr(): pass
446 def testTextRepr(): pass
448 def testWriteText(): pass
450 def testDocumentElement(): pass
452 def testTooManyDocumentElements():
453 doc
= parseString("<doc/>")
454 elem
= doc
.createElement("extra")
456 doc
.appendChild(elem
)
457 except xmlcore
.dom
.HierarchyRequestErr
:
460 print "Failed to catch expected exception when" \
461 " adding extra document element."
465 def testCreateElementNS(): pass
467 def testCreateAttributeNS(): pass
469 def testParse(): pass
471 def testParseString(): pass
473 def testComment(): pass
475 def testAttrListItem(): pass
477 def testAttrListItems(): pass
479 def testAttrListItemNS(): pass
481 def testAttrListKeys(): pass
483 def testAttrListKeysNS(): pass
485 def testRemoveNamedItem():
486 doc
= parseString("<doc a=''/>")
487 e
= doc
.documentElement
489 a1
= e
.getAttributeNode("a")
490 a2
= attrs
.removeNamedItem("a")
491 confirm(a1
.isSameNode(a2
))
493 attrs
.removeNamedItem("a")
494 except xmlcore
.dom
.NotFoundErr
:
497 def testRemoveNamedItemNS():
498 doc
= parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
499 e
= doc
.documentElement
501 a1
= e
.getAttributeNodeNS("http://xml.python.org/", "b")
502 a2
= attrs
.removeNamedItemNS("http://xml.python.org/", "b")
503 confirm(a1
.isSameNode(a2
))
505 attrs
.removeNamedItemNS("http://xml.python.org/", "b")
506 except xmlcore
.dom
.NotFoundErr
:
509 def testAttrListValues(): pass
511 def testAttrListLength(): pass
513 def testAttrList__getitem__(): pass
515 def testAttrList__setitem__(): pass
517 def testSetAttrValueandNodeValue(): pass
519 def testParseElement(): pass
521 def testParseAttributes(): pass
523 def testParseElementNamespaces(): pass
525 def testParseAttributeNamespaces(): pass
527 def testParseProcessingInstructions(): pass
529 def testChildNodes(): pass
531 def testFirstChild(): pass
533 def testHasChildNodes(): pass
535 def testCloneElementShallow():
536 dom
, clone
= _setupCloneElement(0)
537 confirm(len(clone
.childNodes
) == 0
538 and clone
.childNodes
.length
== 0
539 and clone
.parentNode
is None
540 and clone
.toxml() == '<doc attr="value"/>'
541 , "testCloneElementShallow")
544 def testCloneElementDeep():
545 dom
, clone
= _setupCloneElement(1)
546 confirm(len(clone
.childNodes
) == 1
547 and clone
.childNodes
.length
== 1
548 and clone
.parentNode
is None
549 and clone
.toxml() == '<doc attr="value"><foo/></doc>'
550 , "testCloneElementDeep")
553 def _setupCloneElement(deep
):
554 dom
= parseString("<doc attr='value'><foo/></doc>")
555 root
= dom
.documentElement
556 clone
= root
.cloneNode(deep
)
557 _testCloneElementCopiesAttributes(
558 root
, clone
, "testCloneElement" + (deep
and "Deep" or "Shallow"))
559 # mutilate the original so shared data is detected
560 root
.tagName
= root
.nodeName
= "MODIFIED"
561 root
.setAttribute("attr", "NEW VALUE")
562 root
.setAttribute("added", "VALUE")
565 def _testCloneElementCopiesAttributes(e1
, e2
, test
):
566 attrs1
= e1
.attributes
567 attrs2
= e2
.attributes
568 keys1
= attrs1
.keys()
569 keys2
= attrs2
.keys()
572 confirm(keys1
== keys2
, "clone of element has same attribute keys")
573 for i
in range(len(keys1
)):
577 and a1
.value
== a2
.value
578 and a1
.nodeValue
== a2
.nodeValue
579 and a1
.namespaceURI
== a2
.namespaceURI
580 and a1
.localName
== a2
.localName
581 , "clone of attribute node has proper attribute values")
582 confirm(a2
.ownerElement
is e2
,
583 "clone of attribute node correctly owned")
585 def testCloneDocumentShallow():
586 doc
= parseString("<?xml version='1.0'?>\n"
589 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
591 "<doc attr='value'/>")
592 doc2
= doc
.cloneNode(0)
593 confirm(doc2
is None,
594 "testCloneDocumentShallow:"
595 " shallow cloning of documents makes no sense!")
597 def testCloneDocumentDeep():
598 doc
= parseString("<?xml version='1.0'?>\n"
601 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
603 "<doc attr='value'/>")
604 doc2
= doc
.cloneNode(1)
605 confirm(not (doc
.isSameNode(doc2
) or doc2
.isSameNode(doc
)),
606 "testCloneDocumentDeep: document objects not distinct")
607 confirm(len(doc
.childNodes
) == len(doc2
.childNodes
),
608 "testCloneDocumentDeep: wrong number of Document children")
609 confirm(doc2
.documentElement
.nodeType
== Node
.ELEMENT_NODE
,
610 "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
611 confirm(doc2
.documentElement
.ownerDocument
.isSameNode(doc2
),
612 "testCloneDocumentDeep: documentElement owner is not new document")
613 confirm(not doc
.documentElement
.isSameNode(doc2
.documentElement
),
614 "testCloneDocumentDeep: documentElement should not be shared")
615 if doc
.doctype
is not None:
616 # check the doctype iff the original DOM maintained it
617 confirm(doc2
.doctype
.nodeType
== Node
.DOCUMENT_TYPE_NODE
,
618 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
619 confirm(doc2
.doctype
.ownerDocument
.isSameNode(doc2
))
620 confirm(not doc
.doctype
.isSameNode(doc2
.doctype
))
622 def testCloneDocumentTypeDeepOk():
623 doctype
= create_nonempty_doctype()
624 clone
= doctype
.cloneNode(1)
625 confirm(clone
is not None
626 and clone
.nodeName
== doctype
.nodeName
627 and clone
.name
== doctype
.name
628 and clone
.publicId
== doctype
.publicId
629 and clone
.systemId
== doctype
.systemId
630 and len(clone
.entities
) == len(doctype
.entities
)
631 and clone
.entities
.item(len(clone
.entities
)) is None
632 and len(clone
.notations
) == len(doctype
.notations
)
633 and clone
.notations
.item(len(clone
.notations
)) is None
634 and len(clone
.childNodes
) == 0)
635 for i
in range(len(doctype
.entities
)):
636 se
= doctype
.entities
.item(i
)
637 ce
= clone
.entities
.item(i
)
638 confirm((not se
.isSameNode(ce
))
639 and (not ce
.isSameNode(se
))
640 and ce
.nodeName
== se
.nodeName
641 and ce
.notationName
== se
.notationName
642 and ce
.publicId
== se
.publicId
643 and ce
.systemId
== se
.systemId
644 and ce
.encoding
== se
.encoding
645 and ce
.actualEncoding
== se
.actualEncoding
646 and ce
.version
== se
.version
)
647 for i
in range(len(doctype
.notations
)):
648 sn
= doctype
.notations
.item(i
)
649 cn
= clone
.notations
.item(i
)
650 confirm((not sn
.isSameNode(cn
))
651 and (not cn
.isSameNode(sn
))
652 and cn
.nodeName
== sn
.nodeName
653 and cn
.publicId
== sn
.publicId
654 and cn
.systemId
== sn
.systemId
)
656 def testCloneDocumentTypeDeepNotOk():
657 doc
= create_doc_with_doctype()
658 clone
= doc
.doctype
.cloneNode(1)
659 confirm(clone
is None, "testCloneDocumentTypeDeepNotOk")
661 def testCloneDocumentTypeShallowOk():
662 doctype
= create_nonempty_doctype()
663 clone
= doctype
.cloneNode(0)
664 confirm(clone
is not None
665 and clone
.nodeName
== doctype
.nodeName
666 and clone
.name
== doctype
.name
667 and clone
.publicId
== doctype
.publicId
668 and clone
.systemId
== doctype
.systemId
669 and len(clone
.entities
) == 0
670 and clone
.entities
.item(0) is None
671 and len(clone
.notations
) == 0
672 and clone
.notations
.item(0) is None
673 and len(clone
.childNodes
) == 0)
675 def testCloneDocumentTypeShallowNotOk():
676 doc
= create_doc_with_doctype()
677 clone
= doc
.doctype
.cloneNode(0)
678 confirm(clone
is None, "testCloneDocumentTypeShallowNotOk")
680 def check_import_document(deep
, testName
):
681 doc1
= parseString("<doc/>")
682 doc2
= parseString("<doc/>")
684 doc1
.importNode(doc2
, deep
)
685 except xmlcore
.dom
.NotSupportedErr
:
688 raise Exception(testName
+
689 ": expected NotSupportedErr when importing a document")
691 def testImportDocumentShallow():
692 check_import_document(0, "testImportDocumentShallow")
694 def testImportDocumentDeep():
695 check_import_document(1, "testImportDocumentDeep")
697 # The tests of DocumentType importing use these helpers to construct
698 # the documents to work with, since not all DOM builders actually
699 # create the DocumentType nodes.
701 def create_doc_without_doctype(doctype
=None):
702 return getDOMImplementation().createDocument(None, "doc", doctype
)
704 def create_nonempty_doctype():
705 doctype
= getDOMImplementation().createDocumentType("doc", None, None)
706 doctype
.entities
._seq
= []
707 doctype
.notations
._seq
= []
708 notation
= xmlcore
.dom
.minidom
.Notation(
710 "http://xml.python.org/notations/my")
711 doctype
.notations
._seq
.append(notation
)
712 entity
= xmlcore
.dom
.minidom
.Entity(
714 "http://xml.python.org/entities/my",
716 entity
.version
= "1.0"
717 entity
.encoding
= "utf-8"
718 entity
.actualEncoding
= "us-ascii"
719 doctype
.entities
._seq
.append(entity
)
722 def create_doc_with_doctype():
723 doctype
= create_nonempty_doctype()
724 doc
= create_doc_without_doctype(doctype
)
725 doctype
.entities
.item(0).ownerDocument
= doc
726 doctype
.notations
.item(0).ownerDocument
= doc
729 def testImportDocumentTypeShallow():
730 src
= create_doc_with_doctype()
731 target
= create_doc_without_doctype()
733 imported
= target
.importNode(src
.doctype
, 0)
734 except xmlcore
.dom
.NotSupportedErr
:
738 "testImportDocumentTypeShallow: expected NotSupportedErr")
740 def testImportDocumentTypeDeep():
741 src
= create_doc_with_doctype()
742 target
= create_doc_without_doctype()
744 imported
= target
.importNode(src
.doctype
, 1)
745 except xmlcore
.dom
.NotSupportedErr
:
749 "testImportDocumentTypeDeep: expected NotSupportedErr")
751 # Testing attribute clones uses a helper, and should always be deep,
752 # even if the argument to cloneNode is false.
753 def check_clone_attribute(deep
, testName
):
754 doc
= parseString("<doc attr='value'/>")
755 attr
= doc
.documentElement
.getAttributeNode("attr")
756 assert attr
is not None
757 clone
= attr
.cloneNode(deep
)
758 confirm(not clone
.isSameNode(attr
))
759 confirm(not attr
.isSameNode(clone
))
760 confirm(clone
.ownerElement
is None,
761 testName
+ ": ownerElement should be None")
762 confirm(clone
.ownerDocument
.isSameNode(attr
.ownerDocument
),
763 testName
+ ": ownerDocument does not match")
764 confirm(clone
.specified
,
765 testName
+ ": cloned attribute must have specified == True")
767 def testCloneAttributeShallow():
768 check_clone_attribute(0, "testCloneAttributeShallow")
770 def testCloneAttributeDeep():
771 check_clone_attribute(1, "testCloneAttributeDeep")
773 def check_clone_pi(deep
, testName
):
774 doc
= parseString("<?target data?><doc/>")
776 assert pi
.nodeType
== Node
.PROCESSING_INSTRUCTION_NODE
777 clone
= pi
.cloneNode(deep
)
778 confirm(clone
.target
== pi
.target
779 and clone
.data
== pi
.data
)
781 def testClonePIShallow():
782 check_clone_pi(0, "testClonePIShallow")
784 def testClonePIDeep():
785 check_clone_pi(1, "testClonePIDeep")
788 doc
= parseString("<doc/>")
789 root
= doc
.documentElement
790 root
.appendChild(doc
.createTextNode("first"))
791 root
.appendChild(doc
.createTextNode("second"))
792 confirm(len(root
.childNodes
) == 2
793 and root
.childNodes
.length
== 2, "testNormalize -- preparation")
795 confirm(len(root
.childNodes
) == 1
796 and root
.childNodes
.length
== 1
797 and root
.firstChild
is root
.lastChild
798 and root
.firstChild
.data
== "firstsecond"
799 , "testNormalize -- result")
802 doc
= parseString("<doc/>")
803 root
= doc
.documentElement
804 root
.appendChild(doc
.createTextNode(""))
806 confirm(len(root
.childNodes
) == 0
807 and root
.childNodes
.length
== 0,
808 "testNormalize -- single empty node removed")
812 doc
= parseString("<doc><?pi?>text?<elm/></doc>")
813 root
= doc
.documentElement
814 (pi
, text
, elm
) = root
.childNodes
816 confirm(pi
.nextSibling
is text
and
817 pi
.previousSibling
is None and
818 text
.nextSibling
is elm
and
819 text
.previousSibling
is pi
and
820 elm
.nextSibling
is None and
821 elm
.previousSibling
is text
, "testSiblings")
826 doc
= parseString("<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
827 root
= doc
.documentElement
828 elm1
= root
.childNodes
[0]
829 (elm2a
, elm2b
) = elm1
.childNodes
830 elm3
= elm2b
.childNodes
[0]
832 confirm(root
.parentNode
is doc
and
833 elm1
.parentNode
is root
and
834 elm2a
.parentNode
is elm1
and
835 elm2b
.parentNode
is elm1
and
836 elm3
.parentNode
is elm2b
, "testParents")
840 def testNodeListItem():
841 doc
= parseString("<doc><e/><e/></doc>")
842 children
= doc
.childNodes
843 docelem
= children
[0]
844 confirm(children
[0] is children
.item(0)
845 and children
.item(1) is None
846 and docelem
.childNodes
.item(0) is docelem
.childNodes
[0]
847 and docelem
.childNodes
.item(1) is docelem
.childNodes
[1]
848 and docelem
.childNodes
.item(0).childNodes
.item(0) is None,
849 "test NodeList.item()")
853 from xmlcore
.dom
import pulldom
855 sax2dom
= pulldom
.SAX2DOM()
856 sax2dom
.startDocument()
857 sax2dom
.startElement("doc", {})
858 sax2dom
.characters("text")
859 sax2dom
.startElement("subelm", {})
860 sax2dom
.characters("text")
861 sax2dom
.endElement("subelm")
862 sax2dom
.characters("text")
863 sax2dom
.endElement("doc")
864 sax2dom
.endDocument()
866 doc
= sax2dom
.document
867 root
= doc
.documentElement
868 (text1
, elm1
, text2
) = root
.childNodes
869 text3
= elm1
.childNodes
[0]
871 confirm(text1
.previousSibling
is None and
872 text1
.nextSibling
is elm1
and
873 elm1
.previousSibling
is text1
and
874 elm1
.nextSibling
is text2
and
875 text2
.previousSibling
is elm1
and
876 text2
.nextSibling
is None and
877 text3
.previousSibling
is None and
878 text3
.nextSibling
is None, "testSAX2DOM - siblings")
880 confirm(root
.parentNode
is doc
and
881 text1
.parentNode
is root
and
882 elm1
.parentNode
is root
and
883 text2
.parentNode
is root
and
884 text3
.parentNode
is elm1
, "testSAX2DOM - parents")
889 doc
= parseString('<foo>€</foo>')
890 confirm(doc
.toxml() == u
'<?xml version="1.0" ?><foo>\u20ac</foo>'
891 and doc
.toxml('utf-8') == '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
892 and doc
.toxml('iso-8859-15') == '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
893 "testEncodings - encoding EURO SIGN")
895 # Verify that character decoding errors throw exceptions instead of crashing
897 doc
= parseString('<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
898 except UnicodeDecodeError:
901 print 'parsing with bad encoding should raise a UnicodeDecodeError'
905 class UserDataHandler
:
907 def handle(self
, operation
, key
, data
, src
, dst
):
908 dst
.setUserData(key
, data
+ 1, self
)
909 src
.setUserData(key
, None, None)
914 n
= dom
.createElement('e')
915 confirm(n
.getUserData("foo") is None)
916 n
.setUserData("foo", None, None)
917 confirm(n
.getUserData("foo") is None)
918 n
.setUserData("foo", 12, 12)
919 n
.setUserData("bar", 13, 13)
920 confirm(n
.getUserData("foo") == 12)
921 confirm(n
.getUserData("bar") == 13)
922 n
.setUserData("foo", None, None)
923 confirm(n
.getUserData("foo") is None)
924 confirm(n
.getUserData("bar") == 13)
926 handler
= UserDataHandler()
927 n
.setUserData("bar", 12, handler
)
929 confirm(handler
.called
930 and n
.getUserData("bar") is None
931 and c
.getUserData("bar") == 13)
936 def testRenameAttribute():
937 doc
= parseString("<doc a='v'/>")
938 elem
= doc
.documentElement
939 attrmap
= elem
.attributes
940 attr
= elem
.attributes
['a']
943 attr
= doc
.renameNode(attr
, xmlcore
.dom
.EMPTY_NAMESPACE
, "b")
944 confirm(attr
.name
== "b"
945 and attr
.nodeName
== "b"
946 and attr
.localName
is None
947 and attr
.namespaceURI
== xmlcore
.dom
.EMPTY_NAMESPACE
948 and attr
.prefix
is None
949 and attr
.value
== "v"
950 and elem
.getAttributeNode("a") is None
951 and elem
.getAttributeNode("b").isSameNode(attr
)
952 and attrmap
["b"].isSameNode(attr
)
953 and attr
.ownerDocument
.isSameNode(doc
)
954 and attr
.ownerElement
.isSameNode(elem
))
956 # Rename to have a namespace, no prefix
957 attr
= doc
.renameNode(attr
, "http://xml.python.org/ns", "c")
958 confirm(attr
.name
== "c"
959 and attr
.nodeName
== "c"
960 and attr
.localName
== "c"
961 and attr
.namespaceURI
== "http://xml.python.org/ns"
962 and attr
.prefix
is None
963 and attr
.value
== "v"
964 and elem
.getAttributeNode("a") is None
965 and elem
.getAttributeNode("b") is None
966 and elem
.getAttributeNode("c").isSameNode(attr
)
967 and elem
.getAttributeNodeNS(
968 "http://xml.python.org/ns", "c").isSameNode(attr
)
969 and attrmap
["c"].isSameNode(attr
)
970 and attrmap
[("http://xml.python.org/ns", "c")].isSameNode(attr
))
972 # Rename to have a namespace, with prefix
973 attr
= doc
.renameNode(attr
, "http://xml.python.org/ns2", "p:d")
974 confirm(attr
.name
== "p:d"
975 and attr
.nodeName
== "p:d"
976 and attr
.localName
== "d"
977 and attr
.namespaceURI
== "http://xml.python.org/ns2"
978 and attr
.prefix
== "p"
979 and attr
.value
== "v"
980 and elem
.getAttributeNode("a") is None
981 and elem
.getAttributeNode("b") is None
982 and elem
.getAttributeNode("c") is None
983 and elem
.getAttributeNodeNS(
984 "http://xml.python.org/ns", "c") is None
985 and elem
.getAttributeNode("p:d").isSameNode(attr
)
986 and elem
.getAttributeNodeNS(
987 "http://xml.python.org/ns2", "d").isSameNode(attr
)
988 and attrmap
["p:d"].isSameNode(attr
)
989 and attrmap
[("http://xml.python.org/ns2", "d")].isSameNode(attr
))
991 # Rename back to a simple non-NS node
992 attr
= doc
.renameNode(attr
, xmlcore
.dom
.EMPTY_NAMESPACE
, "e")
993 confirm(attr
.name
== "e"
994 and attr
.nodeName
== "e"
995 and attr
.localName
is None
996 and attr
.namespaceURI
== xmlcore
.dom
.EMPTY_NAMESPACE
997 and attr
.prefix
is None
998 and attr
.value
== "v"
999 and elem
.getAttributeNode("a") is None
1000 and elem
.getAttributeNode("b") is None
1001 and elem
.getAttributeNode("c") is None
1002 and elem
.getAttributeNode("p:d") is None
1003 and elem
.getAttributeNodeNS(
1004 "http://xml.python.org/ns", "c") is None
1005 and elem
.getAttributeNode("e").isSameNode(attr
)
1006 and attrmap
["e"].isSameNode(attr
))
1009 doc
.renameNode(attr
, "http://xml.python.org/ns", "xmlns")
1010 except xmlcore
.dom
.NamespaceErr
:
1013 print "expected NamespaceErr"
1015 checkRenameNodeSharedConstraints(doc
, attr
)
1018 def testRenameElement():
1019 doc
= parseString("<doc/>")
1020 elem
= doc
.documentElement
1023 elem
= doc
.renameNode(elem
, xmlcore
.dom
.EMPTY_NAMESPACE
, "a")
1024 confirm(elem
.tagName
== "a"
1025 and elem
.nodeName
== "a"
1026 and elem
.localName
is None
1027 and elem
.namespaceURI
== xmlcore
.dom
.EMPTY_NAMESPACE
1028 and elem
.prefix
is None
1029 and elem
.ownerDocument
.isSameNode(doc
))
1031 # Rename to have a namespace, no prefix
1032 elem
= doc
.renameNode(elem
, "http://xml.python.org/ns", "b")
1033 confirm(elem
.tagName
== "b"
1034 and elem
.nodeName
== "b"
1035 and elem
.localName
== "b"
1036 and elem
.namespaceURI
== "http://xml.python.org/ns"
1037 and elem
.prefix
is None
1038 and elem
.ownerDocument
.isSameNode(doc
))
1040 # Rename to have a namespace, with prefix
1041 elem
= doc
.renameNode(elem
, "http://xml.python.org/ns2", "p:c")
1042 confirm(elem
.tagName
== "p:c"
1043 and elem
.nodeName
== "p:c"
1044 and elem
.localName
== "c"
1045 and elem
.namespaceURI
== "http://xml.python.org/ns2"
1046 and elem
.prefix
== "p"
1047 and elem
.ownerDocument
.isSameNode(doc
))
1049 # Rename back to a simple non-NS node
1050 elem
= doc
.renameNode(elem
, xmlcore
.dom
.EMPTY_NAMESPACE
, "d")
1051 confirm(elem
.tagName
== "d"
1052 and elem
.nodeName
== "d"
1053 and elem
.localName
is None
1054 and elem
.namespaceURI
== xmlcore
.dom
.EMPTY_NAMESPACE
1055 and elem
.prefix
is None
1056 and elem
.ownerDocument
.isSameNode(doc
))
1058 checkRenameNodeSharedConstraints(doc
, elem
)
1061 def checkRenameNodeSharedConstraints(doc
, node
):
1062 # Make sure illegal NS usage is detected:
1064 doc
.renameNode(node
, "http://xml.python.org/ns", "xmlns:foo")
1065 except xmlcore
.dom
.NamespaceErr
:
1068 print "expected NamespaceErr"
1070 doc2
= parseString("<doc/>")
1072 doc2
.renameNode(node
, xmlcore
.dom
.EMPTY_NAMESPACE
, "foo")
1073 except xmlcore
.dom
.WrongDocumentErr
:
1076 print "expected WrongDocumentErr"
1078 def testRenameOther():
1079 # We have to create a comment node explicitly since not all DOM
1080 # builders used with minidom add comments to the DOM.
1081 doc
= xmlcore
.dom
.minidom
.getDOMImplementation().createDocument(
1082 xmlcore
.dom
.EMPTY_NAMESPACE
, "e", None)
1083 node
= doc
.createComment("comment")
1085 doc
.renameNode(node
, xmlcore
.dom
.EMPTY_NAMESPACE
, "foo")
1086 except xmlcore
.dom
.NotSupportedErr
:
1089 print "expected NotSupportedErr when renaming comment node"
1092 def checkWholeText(node
, s
):
1094 confirm(t
== s
, "looking for %s, found %s" % (repr(s
), repr(t
)))
1096 def testWholeText():
1097 doc
= parseString("<doc>a</doc>")
1098 elem
= doc
.documentElement
1099 text
= elem
.childNodes
[0]
1100 assert text
.nodeType
== Node
.TEXT_NODE
1102 checkWholeText(text
, "a")
1103 elem
.appendChild(doc
.createTextNode("b"))
1104 checkWholeText(text
, "ab")
1105 elem
.insertBefore(doc
.createCDATASection("c"), text
)
1106 checkWholeText(text
, "cab")
1108 # make sure we don't cross other nodes
1109 splitter
= doc
.createComment("comment")
1110 elem
.appendChild(splitter
)
1111 text2
= doc
.createTextNode("d")
1112 elem
.appendChild(text2
)
1113 checkWholeText(text
, "cab")
1114 checkWholeText(text2
, "d")
1116 x
= doc
.createElement("x")
1117 elem
.replaceChild(x
, splitter
)
1119 checkWholeText(text
, "cab")
1120 checkWholeText(text2
, "d")
1122 x
= doc
.createProcessingInstruction("y", "z")
1123 elem
.replaceChild(x
, splitter
)
1125 checkWholeText(text
, "cab")
1126 checkWholeText(text2
, "d")
1128 elem
.removeChild(splitter
)
1129 checkWholeText(text
, "cabd")
1130 checkWholeText(text2
, "cabd")
1132 def testPatch1094164 ():
1133 doc
= parseString("<doc><e/></doc>")
1134 elem
= doc
.documentElement
1136 confirm(e
.parentNode
is elem
, "Before replaceChild()")
1137 # Check that replacing a child with itself leaves the tree unchanged
1138 elem
.replaceChild(e
, e
)
1139 confirm(e
.parentNode
is elem
, "After replaceChild()")
1143 def testReplaceWholeText():
1145 doc
= parseString("<doc>a<e/>d</doc>")
1146 elem
= doc
.documentElement
1147 text1
= elem
.firstChild
1148 text2
= elem
.lastChild
1149 splitter
= text1
.nextSibling
1150 elem
.insertBefore(doc
.createTextNode("b"), splitter
)
1151 elem
.insertBefore(doc
.createCDATASection("c"), text1
)
1152 return doc
, elem
, text1
, splitter
, text2
1154 doc
, elem
, text1
, splitter
, text2
= setup()
1155 text
= text1
.replaceWholeText("new content")
1156 checkWholeText(text
, "new content")
1157 checkWholeText(text2
, "d")
1158 confirm(len(elem
.childNodes
) == 3)
1160 doc
, elem
, text1
, splitter
, text2
= setup()
1161 text
= text2
.replaceWholeText("new content")
1162 checkWholeText(text
, "new content")
1163 checkWholeText(text1
, "cab")
1164 confirm(len(elem
.childNodes
) == 5)
1166 doc
, elem
, text1
, splitter
, text2
= setup()
1167 text
= text1
.replaceWholeText("")
1168 checkWholeText(text2
, "d")
1169 confirm(text
is None
1170 and len(elem
.childNodes
) == 2)
1172 def testSchemaType():
1175 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
1176 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
1177 " <!ATTLIST doc id ID #IMPLIED \n"
1178 " ref IDREF #IMPLIED \n"
1179 " refs IDREFS #IMPLIED \n"
1180 " enum (a|b) #IMPLIED \n"
1181 " ent ENTITY #IMPLIED \n"
1182 " ents ENTITIES #IMPLIED \n"
1183 " nm NMTOKEN #IMPLIED \n"
1184 " nms NMTOKENS #IMPLIED \n"
1185 " text CDATA #IMPLIED \n"
1187 "]><doc id='name' notid='name' text='splat!' enum='b'"
1188 " ref='name' refs='name name' ent='e1' ents='e1 e2'"
1189 " nm='123' nms='123 abc' />")
1190 elem
= doc
.documentElement
1191 # We don't want to rely on any specific loader at this point, so
1192 # just make sure we can get to all the names, and that the
1193 # DTD-based namespace is right. The names can vary by loader
1194 # since each supports a different level of DTD information.
1196 confirm(t
.name
is None
1197 and t
.namespace
== xmlcore
.dom
.EMPTY_NAMESPACE
)
1198 names
= "id notid text enum ref refs ent ents nm nms".split()
1200 a
= elem
.getAttributeNode(name
)
1202 confirm(hasattr(t
, "name")
1203 and t
.namespace
== xmlcore
.dom
.EMPTY_NAMESPACE
)
1205 def testSetIdAttribute():
1206 doc
= parseString("<doc a1='v' a2='w'/>")
1207 e
= doc
.documentElement
1208 a1
= e
.getAttributeNode("a1")
1209 a2
= e
.getAttributeNode("a2")
1210 confirm(doc
.getElementById("v") is None
1213 e
.setIdAttribute("a1")
1214 confirm(e
.isSameNode(doc
.getElementById("v"))
1217 e
.setIdAttribute("a2")
1218 confirm(e
.isSameNode(doc
.getElementById("v"))
1219 and e
.isSameNode(doc
.getElementById("w"))
1222 # replace the a1 node; the new node should *not* be an ID
1223 a3
= doc
.createAttribute("a1")
1225 e
.setAttributeNode(a3
)
1226 confirm(doc
.getElementById("v") is None
1227 and e
.isSameNode(doc
.getElementById("w"))
1231 # renaming an attribute should not affect its ID-ness:
1232 doc
.renameNode(a2
, xmlcore
.dom
.EMPTY_NAMESPACE
, "an")
1233 confirm(e
.isSameNode(doc
.getElementById("w"))
1236 def testSetIdAttributeNS():
1237 NS1
= "http://xml.python.org/ns1"
1238 NS2
= "http://xml.python.org/ns2"
1239 doc
= parseString("<doc"
1240 " xmlns:ns1='" + NS1
+ "'"
1241 " xmlns:ns2='" + NS2
+ "'"
1242 " ns1:a1='v' ns2:a2='w'/>")
1243 e
= doc
.documentElement
1244 a1
= e
.getAttributeNodeNS(NS1
, "a1")
1245 a2
= e
.getAttributeNodeNS(NS2
, "a2")
1246 confirm(doc
.getElementById("v") is None
1249 e
.setIdAttributeNS(NS1
, "a1")
1250 confirm(e
.isSameNode(doc
.getElementById("v"))
1253 e
.setIdAttributeNS(NS2
, "a2")
1254 confirm(e
.isSameNode(doc
.getElementById("v"))
1255 and e
.isSameNode(doc
.getElementById("w"))
1258 # replace the a1 node; the new node should *not* be an ID
1259 a3
= doc
.createAttributeNS(NS1
, "a1")
1261 e
.setAttributeNode(a3
)
1262 confirm(e
.isSameNode(doc
.getElementById("w")))
1263 confirm(not a1
.isId
)
1265 confirm(not a3
.isId
)
1266 confirm(doc
.getElementById("v") is None)
1267 # renaming an attribute should not affect its ID-ness:
1268 doc
.renameNode(a2
, xmlcore
.dom
.EMPTY_NAMESPACE
, "an")
1269 confirm(e
.isSameNode(doc
.getElementById("w"))
1272 def testSetIdAttributeNode():
1273 NS1
= "http://xml.python.org/ns1"
1274 NS2
= "http://xml.python.org/ns2"
1275 doc
= parseString("<doc"
1276 " xmlns:ns1='" + NS1
+ "'"
1277 " xmlns:ns2='" + NS2
+ "'"
1278 " ns1:a1='v' ns2:a2='w'/>")
1279 e
= doc
.documentElement
1280 a1
= e
.getAttributeNodeNS(NS1
, "a1")
1281 a2
= e
.getAttributeNodeNS(NS2
, "a2")
1282 confirm(doc
.getElementById("v") is None
1285 e
.setIdAttributeNode(a1
)
1286 confirm(e
.isSameNode(doc
.getElementById("v"))
1289 e
.setIdAttributeNode(a2
)
1290 confirm(e
.isSameNode(doc
.getElementById("v"))
1291 and e
.isSameNode(doc
.getElementById("w"))
1294 # replace the a1 node; the new node should *not* be an ID
1295 a3
= doc
.createAttributeNS(NS1
, "a1")
1297 e
.setAttributeNode(a3
)
1298 confirm(e
.isSameNode(doc
.getElementById("w")))
1299 confirm(not a1
.isId
)
1301 confirm(not a3
.isId
)
1302 confirm(doc
.getElementById("v") is None)
1303 # renaming an attribute should not affect its ID-ness:
1304 doc
.renameNode(a2
, xmlcore
.dom
.EMPTY_NAMESPACE
, "an")
1305 confirm(e
.isSameNode(doc
.getElementById("w"))
1308 def testPickledDocument():
1309 doc
= parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
1310 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
1311 " 'http://xml.python.org/system' [\n"
1312 " <!ELEMENT e EMPTY>\n"
1313 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
1314 "]><doc attr='value'> text\n"
1315 "<?pi sample?> <!-- comment --> <e/> </doc>")
1316 s
= pickle
.dumps(doc
)
1317 doc2
= pickle
.loads(s
)
1318 stack
= [(doc
, doc2
)]
1320 n1
, n2
= stack
.pop()
1321 confirm(n1
.nodeType
== n2
.nodeType
1322 and len(n1
.childNodes
) == len(n2
.childNodes
)
1323 and n1
.nodeName
== n2
.nodeName
1324 and not n1
.isSameNode(n2
)
1325 and not n2
.isSameNode(n1
))
1326 if n1
.nodeType
== Node
.DOCUMENT_TYPE_NODE
:
1331 confirm(len(n1
.entities
) == len(n2
.entities
)
1332 and len(n1
.notations
) == len(n2
.notations
))
1333 for i
in range(len(n1
.notations
)):
1334 no1
= n1
.notations
.item(i
)
1335 no2
= n1
.notations
.item(i
)
1336 confirm(no1
.name
== no2
.name
1337 and no1
.publicId
== no2
.publicId
1338 and no1
.systemId
== no2
.systemId
)
1339 statck
.append((no1
, no2
))
1340 for i
in range(len(n1
.entities
)):
1341 e1
= n1
.entities
.item(i
)
1342 e2
= n2
.entities
.item(i
)
1343 confirm(e1
.notationName
== e2
.notationName
1344 and e1
.publicId
== e2
.publicId
1345 and e1
.systemId
== e2
.systemId
)
1346 stack
.append((e1
, e2
))
1347 if n1
.nodeType
!= Node
.DOCUMENT_NODE
:
1348 confirm(n1
.ownerDocument
.isSameNode(doc
)
1349 and n2
.ownerDocument
.isSameNode(doc2
))
1350 for i
in range(len(n1
.childNodes
)):
1351 stack
.append((n1
.childNodes
[i
], n2
.childNodes
[i
]))
1356 names
= globals().keys()
1363 except AttributeError:
1364 # We don't actually have the minidom from the standard library,
1365 # but are picking up the PyXML version from site-packages.
1366 def check_allnodes():
1369 def check_allnodes():
1370 confirm(len(Node
.allnodes
) == 0,
1371 "assertion: len(Node.allnodes) == 0")
1372 if len(Node
.allnodes
):
1373 print "Garbage left over:"
1375 print Node
.allnodes
.items()[0:10]
1377 # Don't print specific nodes if repeatable results
1379 print len(Node
.allnodes
)
1383 if name
.startswith("test"):
1384 func
= globals()[name
]
1390 print "Test Failed: ", name
1392 traceback
.print_exception(*sys
.exc_info())
1393 print repr(sys
.exc_info()[1])
1397 print "\n\n\n**** Check for failures in these tests:"