1 # test for xml.dom.minidom
6 from test
.support
import verbose
, run_unittest
10 import xml
.dom
.minidom
11 import xml
.parsers
.expat
13 from xml
.dom
.minidom
import parse
, Node
, Document
, parseString
14 from xml
.dom
.minidom
import getDOMImplementation
17 if __name__
== "__main__":
21 tstfile
= os
.path
.join(os
.path
.dirname(base
), "test.xml")
24 # The tests of DocumentType importing use these helpers to construct
25 # the documents to work with, since not all DOM builders actually
26 # create the DocumentType nodes.
27 def create_doc_without_doctype(doctype
=None):
28 return getDOMImplementation().createDocument(None, "doc", doctype
)
30 def create_nonempty_doctype():
31 doctype
= getDOMImplementation().createDocumentType("doc", None, None)
32 doctype
.entities
._seq
= []
33 doctype
.notations
._seq
= []
34 notation
= xml
.dom
.minidom
.Notation("my-notation", None,
35 "http://xml.python.org/notations/my")
36 doctype
.notations
._seq
.append(notation
)
37 entity
= xml
.dom
.minidom
.Entity("my-entity", None,
38 "http://xml.python.org/entities/my",
40 entity
.version
= "1.0"
41 entity
.encoding
= "utf-8"
42 entity
.actualEncoding
= "us-ascii"
43 doctype
.entities
._seq
.append(entity
)
46 def create_doc_with_doctype():
47 doctype
= create_nonempty_doctype()
48 doc
= create_doc_without_doctype(doctype
)
49 doctype
.entities
.item(0).ownerDocument
= doc
50 doctype
.notations
.item(0).ownerDocument
= doc
53 class MinidomTest(unittest
.TestCase
):
57 except AttributeError:
58 # We don't actually have the minidom from the standard library,
59 # but are picking up the PyXML version from site-packages.
62 self
.confirm(len(Node
.allnodes
) == 0,
63 "assertion: len(Node.allnodes) == 0")
64 if len(Node
.allnodes
):
65 print("Garbage left over:")
67 print(list(Node
.allnodes
.items())[0:10])
69 # Don't print specific nodes if repeatable results
71 print(len(Node
.allnodes
))
74 def confirm(self
, test
, testname
= "Test"):
75 self
.assertTrue(test
, testname
)
77 def checkWholeText(self
, node
, s
):
79 self
.confirm(t
== s
, "looking for %s, found %s" % (repr(s
), repr(t
)))
81 def testParseFromFile(self
):
82 dom
= parse(open(tstfile
))
84 self
.confirm(isinstance(dom
, Document
))
86 def testGetElementsByTagName(self
):
88 self
.confirm(dom
.getElementsByTagName("LI") == \
89 dom
.documentElement
.getElementsByTagName("LI"))
92 def testInsertBefore(self
):
93 dom
= parseString("<doc><foo/></doc>")
94 root
= dom
.documentElement
95 elem
= root
.childNodes
[0]
96 nelem
= dom
.createElement("element")
97 root
.insertBefore(nelem
, elem
)
98 self
.confirm(len(root
.childNodes
) == 2
99 and root
.childNodes
.length
== 2
100 and root
.childNodes
[0] is nelem
101 and root
.childNodes
.item(0) is nelem
102 and root
.childNodes
[1] is elem
103 and root
.childNodes
.item(1) is elem
104 and root
.firstChild
is nelem
105 and root
.lastChild
is elem
106 and root
.toxml() == "<doc><element/><foo/></doc>"
107 , "testInsertBefore -- node properly placed in tree")
108 nelem
= dom
.createElement("element")
109 root
.insertBefore(nelem
, None)
110 self
.confirm(len(root
.childNodes
) == 3
111 and root
.childNodes
.length
== 3
112 and root
.childNodes
[1] is elem
113 and root
.childNodes
.item(1) is elem
114 and root
.childNodes
[2] is nelem
115 and root
.childNodes
.item(2) is nelem
116 and root
.lastChild
is nelem
117 and nelem
.previousSibling
is elem
118 and root
.toxml() == "<doc><element/><foo/><element/></doc>"
119 , "testInsertBefore -- node properly placed in tree")
120 nelem2
= dom
.createElement("bar")
121 root
.insertBefore(nelem2
, nelem
)
122 self
.confirm(len(root
.childNodes
) == 4
123 and root
.childNodes
.length
== 4
124 and root
.childNodes
[2] is nelem2
125 and root
.childNodes
.item(2) is nelem2
126 and root
.childNodes
[3] is nelem
127 and root
.childNodes
.item(3) is nelem
128 and nelem2
.nextSibling
is nelem
129 and nelem
.previousSibling
is nelem2
131 "<doc><element/><foo/><bar/><element/></doc>"
132 , "testInsertBefore -- node properly placed in tree")
135 def _create_fragment_test_nodes(self
):
136 dom
= parseString("<doc/>")
137 orig
= dom
.createTextNode("original")
138 c1
= dom
.createTextNode("foo")
139 c2
= dom
.createTextNode("bar")
140 c3
= dom
.createTextNode("bat")
141 dom
.documentElement
.appendChild(orig
)
142 frag
= dom
.createDocumentFragment()
146 return dom
, orig
, c1
, c2
, c3
, frag
148 def testInsertBeforeFragment(self
):
149 dom
, orig
, c1
, c2
, c3
, frag
= self
._create
_fragment
_test
_nodes
()
150 dom
.documentElement
.insertBefore(frag
, None)
151 self
.confirm(tuple(dom
.documentElement
.childNodes
) ==
153 "insertBefore(<fragment>, None)")
157 dom
, orig
, c1
, c2
, c3
, frag
= self
._create
_fragment
_test
_nodes
()
158 dom
.documentElement
.insertBefore(frag
, orig
)
159 self
.confirm(tuple(dom
.documentElement
.childNodes
) ==
161 "insertBefore(<fragment>, orig)")
165 def testAppendChild(self
):
167 dom
.documentElement
.appendChild(dom
.createComment("Hello"))
168 self
.confirm(dom
.documentElement
.childNodes
[-1].nodeName
== "#comment")
169 self
.confirm(dom
.documentElement
.childNodes
[-1].data
== "Hello")
172 def testAppendChildFragment(self
):
173 dom
, orig
, c1
, c2
, c3
, frag
= self
._create
_fragment
_test
_nodes
()
174 dom
.documentElement
.appendChild(frag
)
175 self
.confirm(tuple(dom
.documentElement
.childNodes
) ==
177 "appendChild(<fragment>)")
181 def testReplaceChildFragment(self
):
182 dom
, orig
, c1
, c2
, c3
, frag
= self
._create
_fragment
_test
_nodes
()
183 dom
.documentElement
.replaceChild(frag
, orig
)
185 self
.confirm(tuple(dom
.documentElement
.childNodes
) == (c1
, c2
, c3
),
186 "replaceChild(<fragment>)")
190 def testLegalChildren(self
):
192 elem
= dom
.createElement('element')
193 text
= dom
.createTextNode('text')
194 self
.assertRaises(xml
.dom
.HierarchyRequestErr
, dom
.appendChild
, text
)
196 dom
.appendChild(elem
)
197 self
.assertRaises(xml
.dom
.HierarchyRequestErr
, dom
.insertBefore
, text
,
199 self
.assertRaises(xml
.dom
.HierarchyRequestErr
, dom
.replaceChild
, text
,
202 nodemap
= elem
.attributes
203 self
.assertRaises(xml
.dom
.HierarchyRequestErr
, nodemap
.setNamedItem
,
205 self
.assertRaises(xml
.dom
.HierarchyRequestErr
, nodemap
.setNamedItemNS
,
208 elem
.appendChild(text
)
211 def testNamedNodeMapSetItem(self
):
213 elem
= dom
.createElement('element')
214 attrs
= elem
.attributes
217 self
.confirm(a
.ownerDocument
is dom
,
218 "NamedNodeMap.__setitem__() sets ownerDocument")
219 self
.confirm(a
.ownerElement
is elem
,
220 "NamedNodeMap.__setitem__() sets ownerElement")
221 self
.confirm(a
.value
== "bar",
222 "NamedNodeMap.__setitem__() sets value")
223 self
.confirm(a
.nodeValue
== "bar",
224 "NamedNodeMap.__setitem__() sets nodeValue")
228 def testNonZero(self
):
230 self
.confirm(dom
)# should not be zero
231 dom
.appendChild(dom
.createComment("foo"))
232 self
.confirm(not dom
.childNodes
[-1].childNodes
)
235 def testUnlink(self
):
239 def testElement(self
):
241 dom
.appendChild(dom
.createElement("abc"))
242 self
.confirm(dom
.documentElement
)
246 dom
= parseString("<abc/>")
247 el
= dom
.documentElement
248 el
.setAttribute("spam", "jam2")
249 self
.confirm(el
.toxml() == '<abc spam="jam2"/>', "testAAA")
250 a
= el
.getAttributeNode("spam")
251 self
.confirm(a
.ownerDocument
is dom
,
252 "setAttribute() sets ownerDocument")
253 self
.confirm(a
.ownerElement
is dom
.documentElement
,
254 "setAttribute() sets ownerElement")
258 dom
= parseString("<abc/>")
259 el
= dom
.documentElement
260 el
.setAttribute("spam", "jam")
261 el
.setAttribute("spam", "jam2")
262 self
.confirm(el
.toxml() == '<abc spam="jam2"/>', "testAAB")
265 def testAddAttr(self
):
267 child
= dom
.appendChild(dom
.createElement("abc"))
269 child
.setAttribute("def", "ghi")
270 self
.confirm(child
.getAttribute("def") == "ghi")
271 self
.confirm(child
.attributes
["def"].value
== "ghi")
273 child
.setAttribute("jkl", "mno")
274 self
.confirm(child
.getAttribute("jkl") == "mno")
275 self
.confirm(child
.attributes
["jkl"].value
== "mno")
277 self
.confirm(len(child
.attributes
) == 2)
279 child
.setAttribute("def", "newval")
280 self
.confirm(child
.getAttribute("def") == "newval")
281 self
.confirm(child
.attributes
["def"].value
== "newval")
283 self
.confirm(len(child
.attributes
) == 2)
286 def testDeleteAttr(self
):
288 child
= dom
.appendChild(dom
.createElement("abc"))
290 self
.confirm(len(child
.attributes
) == 0)
291 child
.setAttribute("def", "ghi")
292 self
.confirm(len(child
.attributes
) == 1)
293 del child
.attributes
["def"]
294 self
.confirm(len(child
.attributes
) == 0)
297 def testRemoveAttr(self
):
299 child
= dom
.appendChild(dom
.createElement("abc"))
301 child
.setAttribute("def", "ghi")
302 self
.confirm(len(child
.attributes
) == 1)
303 child
.removeAttribute("def")
304 self
.confirm(len(child
.attributes
) == 0)
307 def testRemoveAttrNS(self
):
309 child
= dom
.appendChild(
310 dom
.createElementNS("http://www.python.org", "python:abc"))
311 child
.setAttributeNS("http://www.w3.org", "xmlns:python",
312 "http://www.python.org")
313 child
.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
314 self
.confirm(len(child
.attributes
) == 2)
315 child
.removeAttributeNS("http://www.python.org", "abcattr")
316 self
.confirm(len(child
.attributes
) == 1)
319 def testRemoveAttributeNode(self
):
321 child
= dom
.appendChild(dom
.createElement("foo"))
322 child
.setAttribute("spam", "jam")
323 self
.confirm(len(child
.attributes
) == 1)
324 node
= child
.getAttributeNode("spam")
325 child
.removeAttributeNode(node
)
326 self
.confirm(len(child
.attributes
) == 0
327 and child
.getAttributeNode("spam") is None)
330 def testChangeAttr(self
):
331 dom
= parseString("<abc/>")
332 el
= dom
.documentElement
333 el
.setAttribute("spam", "jam")
334 self
.confirm(len(el
.attributes
) == 1)
335 el
.setAttribute("spam", "bam")
336 # Set this attribute to be an ID and make sure that doesn't change
337 # when changing the value:
338 el
.setIdAttribute("spam")
339 self
.confirm(len(el
.attributes
) == 1
340 and el
.attributes
["spam"].value
== "bam"
341 and el
.attributes
["spam"].nodeValue
== "bam"
342 and el
.getAttribute("spam") == "bam"
343 and el
.getAttributeNode("spam").isId
)
344 el
.attributes
["spam"] = "ham"
345 self
.confirm(len(el
.attributes
) == 1
346 and el
.attributes
["spam"].value
== "ham"
347 and el
.attributes
["spam"].nodeValue
== "ham"
348 and el
.getAttribute("spam") == "ham"
349 and el
.attributes
["spam"].isId
)
350 el
.setAttribute("spam2", "bam")
351 self
.confirm(len(el
.attributes
) == 2
352 and el
.attributes
["spam"].value
== "ham"
353 and el
.attributes
["spam"].nodeValue
== "ham"
354 and el
.getAttribute("spam") == "ham"
355 and el
.attributes
["spam2"].value
== "bam"
356 and el
.attributes
["spam2"].nodeValue
== "bam"
357 and el
.getAttribute("spam2") == "bam")
358 el
.attributes
["spam2"] = "bam2"
359 self
.confirm(len(el
.attributes
) == 2
360 and el
.attributes
["spam"].value
== "ham"
361 and el
.attributes
["spam"].nodeValue
== "ham"
362 and el
.getAttribute("spam") == "ham"
363 and el
.attributes
["spam2"].value
== "bam2"
364 and el
.attributes
["spam2"].nodeValue
== "bam2"
365 and el
.getAttribute("spam2") == "bam2")
368 def testGetAttrList(self
):
371 def testGetAttrValues(self
): pass
373 def testGetAttrLength(self
): pass
375 def testGetAttribute(self
): pass
377 def testGetAttributeNS(self
): pass
379 def testGetAttributeNode(self
): pass
381 def testGetElementsByTagNameNS(self
):
382 d
="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
386 elems
= dom
.getElementsByTagNameNS("http://pyxml.sf.net/minidom",
388 self
.confirm(len(elems
) == 1
389 and elems
[0].namespaceURI
== "http://pyxml.sf.net/minidom"
390 and elems
[0].localName
== "myelem"
391 and elems
[0].prefix
== "minidom"
392 and elems
[0].tagName
== "minidom:myelem"
393 and elems
[0].nodeName
== "minidom:myelem")
396 def get_empty_nodelist_from_elements_by_tagName_ns_helper(self
, doc
, nsuri
,
398 nodelist
= doc
.getElementsByTagNameNS(nsuri
, lname
)
399 self
.confirm(len(nodelist
) == 0)
401 def testGetEmptyNodeListFromElementsByTagNameNS(self
):
402 doc
= parseString('<doc/>')
403 self
.get_empty_nodelist_from_elements_by_tagName_ns_helper(
404 doc
, 'http://xml.python.org/namespaces/a', 'localname')
405 self
.get_empty_nodelist_from_elements_by_tagName_ns_helper(
407 self
.get_empty_nodelist_from_elements_by_tagName_ns_helper(
408 doc
, 'http://xml.python.org/namespaces/a', '*')
410 doc
= parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
411 self
.get_empty_nodelist_from_elements_by_tagName_ns_helper(
412 doc
, "http://xml.python.org/splat", "not-there")
413 self
.get_empty_nodelist_from_elements_by_tagName_ns_helper(
414 doc
, "*", "not-there")
415 self
.get_empty_nodelist_from_elements_by_tagName_ns_helper(
416 doc
, "http://somewhere.else.net/not-there", "e")
418 def testElementReprAndStr(self
):
420 el
= dom
.appendChild(dom
.createElement("abc"))
423 self
.confirm(string1
== string2
)
426 def testElementReprAndStrUnicode(self
):
428 el
= dom
.appendChild(dom
.createElement("abc"))
431 self
.confirm(string1
== string2
)
434 def testElementReprAndStrUnicodeNS(self
):
436 el
= dom
.appendChild(
437 dom
.createElementNS("http://www.slashdot.org", "slash:abc"))
440 self
.confirm(string1
== string2
)
441 self
.confirm(string1
.find("slash:abc") != -1)
444 def testAttributeRepr(self
):
446 el
= dom
.appendChild(dom
.createElement("abc"))
447 node
= el
.setAttribute("abc", "def")
448 self
.confirm(str(node
) == repr(node
))
451 def testTextNodeRepr(self
): pass
453 def testWriteXML(self
):
454 str = '<?xml version="1.0" ?><a b="c"/>'
455 dom
= parseString(str)
458 self
.confirm(str == domstr
)
460 def testAltNewline(self
):
461 str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
462 dom
= parseString(str)
463 domstr
= dom
.toprettyxml(newl
="\r\n")
465 self
.confirm(domstr
== str.replace("\n", "\r\n"))
467 def testProcessingInstruction(self
):
468 dom
= parseString('<e><?mypi \t\n data \t\n ?></e>')
469 pi
= dom
.documentElement
.firstChild
470 self
.confirm(pi
.target
== "mypi"
471 and pi
.data
== "data \t\n "
472 and pi
.nodeName
== "mypi"
473 and pi
.nodeType
== Node
.PROCESSING_INSTRUCTION_NODE
474 and pi
.attributes
is None
475 and not pi
.hasChildNodes()
476 and len(pi
.childNodes
) == 0
477 and pi
.firstChild
is None
478 and pi
.lastChild
is None
479 and pi
.localName
is None
480 and pi
.namespaceURI
== xml
.dom
.EMPTY_NAMESPACE
)
482 def testProcessingInstructionRepr(self
): pass
484 def testTextRepr(self
): pass
486 def testWriteText(self
): pass
488 def testDocumentElement(self
): pass
490 def testTooManyDocumentElements(self
):
491 doc
= parseString("<doc/>")
492 elem
= doc
.createElement("extra")
493 # Should raise an exception when adding an extra document element.
494 self
.assertRaises(xml
.dom
.HierarchyRequestErr
, doc
.appendChild
, elem
)
498 def testCreateElementNS(self
): pass
500 def testCreateAttributeNS(self
): pass
502 def testParse(self
): pass
504 def testParseString(self
): pass
506 def testComment(self
): pass
508 def testAttrListItem(self
): pass
510 def testAttrListItems(self
): pass
512 def testAttrListItemNS(self
): pass
514 def testAttrListKeys(self
): pass
516 def testAttrListKeysNS(self
): pass
518 def testRemoveNamedItem(self
):
519 doc
= parseString("<doc a=''/>")
520 e
= doc
.documentElement
522 a1
= e
.getAttributeNode("a")
523 a2
= attrs
.removeNamedItem("a")
524 self
.confirm(a1
.isSameNode(a2
))
525 self
.assertRaises(xml
.dom
.NotFoundErr
, attrs
.removeNamedItem
, "a")
527 def testRemoveNamedItemNS(self
):
528 doc
= parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
529 e
= doc
.documentElement
531 a1
= e
.getAttributeNodeNS("http://xml.python.org/", "b")
532 a2
= attrs
.removeNamedItemNS("http://xml.python.org/", "b")
533 self
.confirm(a1
.isSameNode(a2
))
534 self
.assertRaises(xml
.dom
.NotFoundErr
, attrs
.removeNamedItemNS
,
535 "http://xml.python.org/", "b")
537 def testAttrListValues(self
): pass
539 def testAttrListLength(self
): pass
541 def testAttrList__getitem__(self
): pass
543 def testAttrList__setitem__(self
): pass
545 def testSetAttrValueandNodeValue(self
): pass
547 def testParseElement(self
): pass
549 def testParseAttributes(self
): pass
551 def testParseElementNamespaces(self
): pass
553 def testParseAttributeNamespaces(self
): pass
555 def testParseProcessingInstructions(self
): pass
557 def testChildNodes(self
): pass
559 def testFirstChild(self
): pass
561 def testHasChildNodes(self
): pass
563 def _testCloneElementCopiesAttributes(self
, e1
, e2
, test
):
564 attrs1
= e1
.attributes
565 attrs2
= e2
.attributes
566 keys1
= list(attrs1
.keys())
567 keys2
= list(attrs2
.keys())
570 self
.confirm(keys1
== keys2
, "clone of element has same attribute keys")
571 for i
in range(len(keys1
)):
574 self
.confirm(a1
is not a2
575 and a1
.value
== a2
.value
576 and a1
.nodeValue
== a2
.nodeValue
577 and a1
.namespaceURI
== a2
.namespaceURI
578 and a1
.localName
== a2
.localName
579 , "clone of attribute node has proper attribute values")
580 self
.confirm(a2
.ownerElement
is e2
,
581 "clone of attribute node correctly owned")
583 def _setupCloneElement(self
, deep
):
584 dom
= parseString("<doc attr='value'><foo/></doc>")
585 root
= dom
.documentElement
586 clone
= root
.cloneNode(deep
)
587 self
._testCloneElementCopiesAttributes
(
588 root
, clone
, "testCloneElement" + (deep
and "Deep" or "Shallow"))
589 # mutilate the original so shared data is detected
590 root
.tagName
= root
.nodeName
= "MODIFIED"
591 root
.setAttribute("attr", "NEW VALUE")
592 root
.setAttribute("added", "VALUE")
595 def testCloneElementShallow(self
):
596 dom
, clone
= self
._setupCloneElement
(0)
597 self
.confirm(len(clone
.childNodes
) == 0
598 and clone
.childNodes
.length
== 0
599 and clone
.parentNode
is None
600 and clone
.toxml() == '<doc attr="value"/>'
601 , "testCloneElementShallow")
604 def testCloneElementDeep(self
):
605 dom
, clone
= self
._setupCloneElement
(1)
606 self
.confirm(len(clone
.childNodes
) == 1
607 and clone
.childNodes
.length
== 1
608 and clone
.parentNode
is None
609 and clone
.toxml() == '<doc attr="value"><foo/></doc>'
610 , "testCloneElementDeep")
613 def testCloneDocumentShallow(self
):
614 doc
= parseString("<?xml version='1.0'?>\n"
617 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
619 "<doc attr='value'/>")
620 doc2
= doc
.cloneNode(0)
621 self
.confirm(doc2
is None,
622 "testCloneDocumentShallow:"
623 " shallow cloning of documents makes no sense!")
625 def testCloneDocumentDeep(self
):
626 doc
= parseString("<?xml version='1.0'?>\n"
629 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
631 "<doc attr='value'/>")
632 doc2
= doc
.cloneNode(1)
633 self
.confirm(not (doc
.isSameNode(doc2
) or doc2
.isSameNode(doc
)),
634 "testCloneDocumentDeep: document objects not distinct")
635 self
.confirm(len(doc
.childNodes
) == len(doc2
.childNodes
),
636 "testCloneDocumentDeep: wrong number of Document children")
637 self
.confirm(doc2
.documentElement
.nodeType
== Node
.ELEMENT_NODE
,
638 "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
639 self
.confirm(doc2
.documentElement
.ownerDocument
.isSameNode(doc2
),
640 "testCloneDocumentDeep: documentElement owner is not new document")
641 self
.confirm(not doc
.documentElement
.isSameNode(doc2
.documentElement
),
642 "testCloneDocumentDeep: documentElement should not be shared")
643 if doc
.doctype
is not None:
644 # check the doctype iff the original DOM maintained it
645 self
.confirm(doc2
.doctype
.nodeType
== Node
.DOCUMENT_TYPE_NODE
,
646 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
647 self
.confirm(doc2
.doctype
.ownerDocument
.isSameNode(doc2
))
648 self
.confirm(not doc
.doctype
.isSameNode(doc2
.doctype
))
650 def testCloneDocumentTypeDeepOk(self
):
651 doctype
= create_nonempty_doctype()
652 clone
= doctype
.cloneNode(1)
653 self
.confirm(clone
is not None
654 and clone
.nodeName
== doctype
.nodeName
655 and clone
.name
== doctype
.name
656 and clone
.publicId
== doctype
.publicId
657 and clone
.systemId
== doctype
.systemId
658 and len(clone
.entities
) == len(doctype
.entities
)
659 and clone
.entities
.item(len(clone
.entities
)) is None
660 and len(clone
.notations
) == len(doctype
.notations
)
661 and clone
.notations
.item(len(clone
.notations
)) is None
662 and len(clone
.childNodes
) == 0)
663 for i
in range(len(doctype
.entities
)):
664 se
= doctype
.entities
.item(i
)
665 ce
= clone
.entities
.item(i
)
666 self
.confirm((not se
.isSameNode(ce
))
667 and (not ce
.isSameNode(se
))
668 and ce
.nodeName
== se
.nodeName
669 and ce
.notationName
== se
.notationName
670 and ce
.publicId
== se
.publicId
671 and ce
.systemId
== se
.systemId
672 and ce
.encoding
== se
.encoding
673 and ce
.actualEncoding
== se
.actualEncoding
674 and ce
.version
== se
.version
)
675 for i
in range(len(doctype
.notations
)):
676 sn
= doctype
.notations
.item(i
)
677 cn
= clone
.notations
.item(i
)
678 self
.confirm((not sn
.isSameNode(cn
))
679 and (not cn
.isSameNode(sn
))
680 and cn
.nodeName
== sn
.nodeName
681 and cn
.publicId
== sn
.publicId
682 and cn
.systemId
== sn
.systemId
)
684 def testCloneDocumentTypeDeepNotOk(self
):
685 doc
= create_doc_with_doctype()
686 clone
= doc
.doctype
.cloneNode(1)
687 self
.confirm(clone
is None, "testCloneDocumentTypeDeepNotOk")
689 def testCloneDocumentTypeShallowOk(self
):
690 doctype
= create_nonempty_doctype()
691 clone
= doctype
.cloneNode(0)
692 self
.confirm(clone
is not None
693 and clone
.nodeName
== doctype
.nodeName
694 and clone
.name
== doctype
.name
695 and clone
.publicId
== doctype
.publicId
696 and clone
.systemId
== doctype
.systemId
697 and len(clone
.entities
) == 0
698 and clone
.entities
.item(0) is None
699 and len(clone
.notations
) == 0
700 and clone
.notations
.item(0) is None
701 and len(clone
.childNodes
) == 0)
703 def testCloneDocumentTypeShallowNotOk(self
):
704 doc
= create_doc_with_doctype()
705 clone
= doc
.doctype
.cloneNode(0)
706 self
.confirm(clone
is None, "testCloneDocumentTypeShallowNotOk")
708 def check_import_document(self
, deep
, testName
):
709 doc1
= parseString("<doc/>")
710 doc2
= parseString("<doc/>")
711 self
.assertRaises(xml
.dom
.NotSupportedErr
, doc1
.importNode
, doc2
, deep
)
713 def testImportDocumentShallow(self
):
714 self
.check_import_document(0, "testImportDocumentShallow")
716 def testImportDocumentDeep(self
):
717 self
.check_import_document(1, "testImportDocumentDeep")
719 def testImportDocumentTypeShallow(self
):
720 src
= create_doc_with_doctype()
721 target
= create_doc_without_doctype()
722 self
.assertRaises(xml
.dom
.NotSupportedErr
, target
.importNode
,
725 def testImportDocumentTypeDeep(self
):
726 src
= create_doc_with_doctype()
727 target
= create_doc_without_doctype()
728 self
.assertRaises(xml
.dom
.NotSupportedErr
, target
.importNode
,
731 # Testing attribute clones uses a helper, and should always be deep,
732 # even if the argument to cloneNode is false.
733 def check_clone_attribute(self
, deep
, testName
):
734 doc
= parseString("<doc attr='value'/>")
735 attr
= doc
.documentElement
.getAttributeNode("attr")
736 self
.failIfEqual(attr
, None)
737 clone
= attr
.cloneNode(deep
)
738 self
.confirm(not clone
.isSameNode(attr
))
739 self
.confirm(not attr
.isSameNode(clone
))
740 self
.confirm(clone
.ownerElement
is None,
741 testName
+ ": ownerElement should be None")
742 self
.confirm(clone
.ownerDocument
.isSameNode(attr
.ownerDocument
),
743 testName
+ ": ownerDocument does not match")
744 self
.confirm(clone
.specified
,
745 testName
+ ": cloned attribute must have specified == True")
747 def testCloneAttributeShallow(self
):
748 self
.check_clone_attribute(0, "testCloneAttributeShallow")
750 def testCloneAttributeDeep(self
):
751 self
.check_clone_attribute(1, "testCloneAttributeDeep")
753 def check_clone_pi(self
, deep
, testName
):
754 doc
= parseString("<?target data?><doc/>")
756 self
.assertEquals(pi
.nodeType
, Node
.PROCESSING_INSTRUCTION_NODE
)
757 clone
= pi
.cloneNode(deep
)
758 self
.confirm(clone
.target
== pi
.target
759 and clone
.data
== pi
.data
)
761 def testClonePIShallow(self
):
762 self
.check_clone_pi(0, "testClonePIShallow")
764 def testClonePIDeep(self
):
765 self
.check_clone_pi(1, "testClonePIDeep")
767 def testNormalize(self
):
768 doc
= parseString("<doc/>")
769 root
= doc
.documentElement
770 root
.appendChild(doc
.createTextNode("first"))
771 root
.appendChild(doc
.createTextNode("second"))
772 self
.confirm(len(root
.childNodes
) == 2
773 and root
.childNodes
.length
== 2,
774 "testNormalize -- preparation")
776 self
.confirm(len(root
.childNodes
) == 1
777 and root
.childNodes
.length
== 1
778 and root
.firstChild
is root
.lastChild
779 and root
.firstChild
.data
== "firstsecond"
780 , "testNormalize -- result")
783 doc
= parseString("<doc/>")
784 root
= doc
.documentElement
785 root
.appendChild(doc
.createTextNode(""))
787 self
.confirm(len(root
.childNodes
) == 0
788 and root
.childNodes
.length
== 0,
789 "testNormalize -- single empty node removed")
792 def testNormalizeCombineAndNextSibling(self
):
793 doc
= parseString("<doc/>")
794 root
= doc
.documentElement
795 root
.appendChild(doc
.createTextNode("first"))
796 root
.appendChild(doc
.createTextNode("second"))
797 root
.appendChild(doc
.createElement("i"))
798 self
.confirm(len(root
.childNodes
) == 3
799 and root
.childNodes
.length
== 3,
800 "testNormalizeCombineAndNextSibling -- preparation")
802 self
.confirm(len(root
.childNodes
) == 2
803 and root
.childNodes
.length
== 2
804 and root
.firstChild
.data
== "firstsecond"
805 and root
.firstChild
is not root
.lastChild
806 and root
.firstChild
.nextSibling
is root
.lastChild
807 and root
.firstChild
.previousSibling
is None
808 and root
.lastChild
.previousSibling
is root
.firstChild
809 and root
.lastChild
.nextSibling
is None
810 , "testNormalizeCombinedAndNextSibling -- result")
813 def testNormalizeDeleteWithPrevSibling(self
):
814 doc
= parseString("<doc/>")
815 root
= doc
.documentElement
816 root
.appendChild(doc
.createTextNode("first"))
817 root
.appendChild(doc
.createTextNode(""))
818 self
.confirm(len(root
.childNodes
) == 2
819 and root
.childNodes
.length
== 2,
820 "testNormalizeDeleteWithPrevSibling -- preparation")
822 self
.confirm(len(root
.childNodes
) == 1
823 and root
.childNodes
.length
== 1
824 and root
.firstChild
.data
== "first"
825 and root
.firstChild
is root
.lastChild
826 and root
.firstChild
.nextSibling
is None
827 and root
.firstChild
.previousSibling
is None
828 , "testNormalizeDeleteWithPrevSibling -- result")
831 def testNormalizeDeleteWithNextSibling(self
):
832 doc
= parseString("<doc/>")
833 root
= doc
.documentElement
834 root
.appendChild(doc
.createTextNode(""))
835 root
.appendChild(doc
.createTextNode("second"))
836 self
.confirm(len(root
.childNodes
) == 2
837 and root
.childNodes
.length
== 2,
838 "testNormalizeDeleteWithNextSibling -- preparation")
840 self
.confirm(len(root
.childNodes
) == 1
841 and root
.childNodes
.length
== 1
842 and root
.firstChild
.data
== "second"
843 and root
.firstChild
is root
.lastChild
844 and root
.firstChild
.nextSibling
is None
845 and root
.firstChild
.previousSibling
is None
846 , "testNormalizeDeleteWithNextSibling -- result")
849 def testNormalizeDeleteWithTwoNonTextSiblings(self
):
850 doc
= parseString("<doc/>")
851 root
= doc
.documentElement
852 root
.appendChild(doc
.createElement("i"))
853 root
.appendChild(doc
.createTextNode(""))
854 root
.appendChild(doc
.createElement("i"))
855 self
.confirm(len(root
.childNodes
) == 3
856 and root
.childNodes
.length
== 3,
857 "testNormalizeDeleteWithTwoSiblings -- preparation")
859 self
.confirm(len(root
.childNodes
) == 2
860 and root
.childNodes
.length
== 2
861 and root
.firstChild
is not root
.lastChild
862 and root
.firstChild
.nextSibling
is root
.lastChild
863 and root
.firstChild
.previousSibling
is None
864 and root
.lastChild
.previousSibling
is root
.firstChild
865 and root
.lastChild
.nextSibling
is None
866 , "testNormalizeDeleteWithTwoSiblings -- result")
869 def testNormalizeDeleteAndCombine(self
):
870 doc
= parseString("<doc/>")
871 root
= doc
.documentElement
872 root
.appendChild(doc
.createTextNode(""))
873 root
.appendChild(doc
.createTextNode("second"))
874 root
.appendChild(doc
.createTextNode(""))
875 root
.appendChild(doc
.createTextNode("fourth"))
876 root
.appendChild(doc
.createTextNode(""))
877 self
.confirm(len(root
.childNodes
) == 5
878 and root
.childNodes
.length
== 5,
879 "testNormalizeDeleteAndCombine -- preparation")
881 self
.confirm(len(root
.childNodes
) == 1
882 and root
.childNodes
.length
== 1
883 and root
.firstChild
is root
.lastChild
884 and root
.firstChild
.data
== "secondfourth"
885 and root
.firstChild
.previousSibling
is None
886 and root
.firstChild
.nextSibling
is None
887 , "testNormalizeDeleteAndCombine -- result")
890 def testNormalizeRecursion(self
):
891 doc
= parseString("<doc>"
908 root
= doc
.documentElement
909 root
.childNodes
[0].appendChild(doc
.createTextNode(""))
910 root
.childNodes
[0].appendChild(doc
.createTextNode("x"))
911 root
.childNodes
[1].childNodes
[0].appendChild(doc
.createTextNode("x2"))
912 root
.childNodes
[1].appendChild(doc
.createTextNode("x3"))
913 root
.appendChild(doc
.createTextNode(""))
914 self
.confirm(len(root
.childNodes
) == 3
915 and root
.childNodes
.length
== 3
916 and len(root
.childNodes
[0].childNodes
) == 4
917 and root
.childNodes
[0].childNodes
.length
== 4
918 and len(root
.childNodes
[1].childNodes
) == 3
919 and root
.childNodes
[1].childNodes
.length
== 3
920 and len(root
.childNodes
[1].childNodes
[0].childNodes
) == 2
921 and root
.childNodes
[1].childNodes
[0].childNodes
.length
== 2
922 , "testNormalize2 -- preparation")
924 self
.confirm(len(root
.childNodes
) == 2
925 and root
.childNodes
.length
== 2
926 and len(root
.childNodes
[0].childNodes
) == 2
927 and root
.childNodes
[0].childNodes
.length
== 2
928 and len(root
.childNodes
[1].childNodes
) == 2
929 and root
.childNodes
[1].childNodes
.length
== 2
930 and len(root
.childNodes
[1].childNodes
[0].childNodes
) == 1
931 and root
.childNodes
[1].childNodes
[0].childNodes
.length
== 1
932 , "testNormalize2 -- childNodes lengths")
933 self
.confirm(root
.childNodes
[0].childNodes
[1].data
== "tx"
934 and root
.childNodes
[1].childNodes
[0].childNodes
[0].data
== "t2x2"
935 and root
.childNodes
[1].childNodes
[1].data
== "t3x3"
936 , "testNormalize2 -- joined text fields")
937 self
.confirm(root
.childNodes
[0].childNodes
[1].nextSibling
is None
938 and root
.childNodes
[0].childNodes
[1].previousSibling
939 is root
.childNodes
[0].childNodes
[0]
940 and root
.childNodes
[0].childNodes
[0].previousSibling
is None
941 and root
.childNodes
[0].childNodes
[0].nextSibling
942 is root
.childNodes
[0].childNodes
[1]
943 and root
.childNodes
[1].childNodes
[1].nextSibling
is None
944 and root
.childNodes
[1].childNodes
[1].previousSibling
945 is root
.childNodes
[1].childNodes
[0]
946 and root
.childNodes
[1].childNodes
[0].previousSibling
is None
947 and root
.childNodes
[1].childNodes
[0].nextSibling
948 is root
.childNodes
[1].childNodes
[1]
949 , "testNormalize2 -- sibling pointers")
953 def testBug1433694(self
):
954 doc
= parseString("<o><i/>t</o>")
955 node
= doc
.documentElement
956 node
.childNodes
[1].nodeValue
= ""
958 self
.confirm(node
.childNodes
[-1].nextSibling
== None,
959 "Final child's .nextSibling should be None")
961 def testSiblings(self
):
962 doc
= parseString("<doc><?pi?>text?<elm/></doc>")
963 root
= doc
.documentElement
964 (pi
, text
, elm
) = root
.childNodes
966 self
.confirm(pi
.nextSibling
is text
and
967 pi
.previousSibling
is None and
968 text
.nextSibling
is elm
and
969 text
.previousSibling
is pi
and
970 elm
.nextSibling
is None and
971 elm
.previousSibling
is text
, "testSiblings")
975 def testParents(self
):
977 "<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
978 root
= doc
.documentElement
979 elm1
= root
.childNodes
[0]
980 (elm2a
, elm2b
) = elm1
.childNodes
981 elm3
= elm2b
.childNodes
[0]
983 self
.confirm(root
.parentNode
is doc
and
984 elm1
.parentNode
is root
and
985 elm2a
.parentNode
is elm1
and
986 elm2b
.parentNode
is elm1
and
987 elm3
.parentNode
is elm2b
, "testParents")
990 def testNodeListItem(self
):
991 doc
= parseString("<doc><e/><e/></doc>")
992 children
= doc
.childNodes
993 docelem
= children
[0]
994 self
.confirm(children
[0] is children
.item(0)
995 and children
.item(1) is None
996 and docelem
.childNodes
.item(0) is docelem
.childNodes
[0]
997 and docelem
.childNodes
.item(1) is docelem
.childNodes
[1]
998 and docelem
.childNodes
.item(0).childNodes
.item(0) is None,
999 "test NodeList.item()")
1002 def testSAX2DOM(self
):
1003 from xml
.dom
import pulldom
1005 sax2dom
= pulldom
.SAX2DOM()
1006 sax2dom
.startDocument()
1007 sax2dom
.startElement("doc", {})
1008 sax2dom
.characters("text")
1009 sax2dom
.startElement("subelm", {})
1010 sax2dom
.characters("text")
1011 sax2dom
.endElement("subelm")
1012 sax2dom
.characters("text")
1013 sax2dom
.endElement("doc")
1014 sax2dom
.endDocument()
1016 doc
= sax2dom
.document
1017 root
= doc
.documentElement
1018 (text1
, elm1
, text2
) = root
.childNodes
1019 text3
= elm1
.childNodes
[0]
1021 self
.confirm(text1
.previousSibling
is None and
1022 text1
.nextSibling
is elm1
and
1023 elm1
.previousSibling
is text1
and
1024 elm1
.nextSibling
is text2
and
1025 text2
.previousSibling
is elm1
and
1026 text2
.nextSibling
is None and
1027 text3
.previousSibling
is None and
1028 text3
.nextSibling
is None, "testSAX2DOM - siblings")
1030 self
.confirm(root
.parentNode
is doc
and
1031 text1
.parentNode
is root
and
1032 elm1
.parentNode
is root
and
1033 text2
.parentNode
is root
and
1034 text3
.parentNode
is elm1
, "testSAX2DOM - parents")
1037 def testEncodings(self
):
1038 doc
= parseString('<foo>€</foo>')
1039 self
.assertEqual(doc
.toxml(),
1040 '<?xml version="1.0" ?><foo>\u20ac</foo>')
1041 self
.assertEqual(doc
.toxml('utf-8'),
1042 b
'<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>')
1043 self
.assertEqual(doc
.toxml('iso-8859-15'),
1044 b
'<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>')
1046 # Verify that character decoding errors throw exceptions instead
1048 self
.assertRaises(UnicodeDecodeError, parseString
,
1049 b
'<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
1053 class UserDataHandler
:
1055 def handle(self
, operation
, key
, data
, src
, dst
):
1056 dst
.setUserData(key
, data
+ 1, self
)
1057 src
.setUserData(key
, None, None)
1060 def testUserData(self
):
1062 n
= dom
.createElement('e')
1063 self
.confirm(n
.getUserData("foo") is None)
1064 n
.setUserData("foo", None, None)
1065 self
.confirm(n
.getUserData("foo") is None)
1066 n
.setUserData("foo", 12, 12)
1067 n
.setUserData("bar", 13, 13)
1068 self
.confirm(n
.getUserData("foo") == 12)
1069 self
.confirm(n
.getUserData("bar") == 13)
1070 n
.setUserData("foo", None, None)
1071 self
.confirm(n
.getUserData("foo") is None)
1072 self
.confirm(n
.getUserData("bar") == 13)
1074 handler
= self
.UserDataHandler()
1075 n
.setUserData("bar", 12, handler
)
1077 self
.confirm(handler
.called
1078 and n
.getUserData("bar") is None
1079 and c
.getUserData("bar") == 13)
1084 def checkRenameNodeSharedConstraints(self
, doc
, node
):
1085 # Make sure illegal NS usage is detected:
1086 self
.assertRaises(xml
.dom
.NamespaceErr
, doc
.renameNode
, node
,
1087 "http://xml.python.org/ns", "xmlns:foo")
1088 doc2
= parseString("<doc/>")
1089 self
.assertRaises(xml
.dom
.WrongDocumentErr
, doc2
.renameNode
, node
,
1090 xml
.dom
.EMPTY_NAMESPACE
, "foo")
1092 def testRenameAttribute(self
):
1093 doc
= parseString("<doc a='v'/>")
1094 elem
= doc
.documentElement
1095 attrmap
= elem
.attributes
1096 attr
= elem
.attributes
['a']
1099 attr
= doc
.renameNode(attr
, xml
.dom
.EMPTY_NAMESPACE
, "b")
1100 self
.confirm(attr
.name
== "b"
1101 and attr
.nodeName
== "b"
1102 and attr
.localName
is None
1103 and attr
.namespaceURI
== xml
.dom
.EMPTY_NAMESPACE
1104 and attr
.prefix
is None
1105 and attr
.value
== "v"
1106 and elem
.getAttributeNode("a") is None
1107 and elem
.getAttributeNode("b").isSameNode(attr
)
1108 and attrmap
["b"].isSameNode(attr
)
1109 and attr
.ownerDocument
.isSameNode(doc
)
1110 and attr
.ownerElement
.isSameNode(elem
))
1112 # Rename to have a namespace, no prefix
1113 attr
= doc
.renameNode(attr
, "http://xml.python.org/ns", "c")
1114 self
.confirm(attr
.name
== "c"
1115 and attr
.nodeName
== "c"
1116 and attr
.localName
== "c"
1117 and attr
.namespaceURI
== "http://xml.python.org/ns"
1118 and attr
.prefix
is None
1119 and attr
.value
== "v"
1120 and elem
.getAttributeNode("a") is None
1121 and elem
.getAttributeNode("b") is None
1122 and elem
.getAttributeNode("c").isSameNode(attr
)
1123 and elem
.getAttributeNodeNS(
1124 "http://xml.python.org/ns", "c").isSameNode(attr
)
1125 and attrmap
["c"].isSameNode(attr
)
1126 and attrmap
[("http://xml.python.org/ns", "c")].isSameNode(attr
))
1128 # Rename to have a namespace, with prefix
1129 attr
= doc
.renameNode(attr
, "http://xml.python.org/ns2", "p:d")
1130 self
.confirm(attr
.name
== "p:d"
1131 and attr
.nodeName
== "p:d"
1132 and attr
.localName
== "d"
1133 and attr
.namespaceURI
== "http://xml.python.org/ns2"
1134 and attr
.prefix
== "p"
1135 and attr
.value
== "v"
1136 and elem
.getAttributeNode("a") is None
1137 and elem
.getAttributeNode("b") is None
1138 and elem
.getAttributeNode("c") is None
1139 and elem
.getAttributeNodeNS(
1140 "http://xml.python.org/ns", "c") is None
1141 and elem
.getAttributeNode("p:d").isSameNode(attr
)
1142 and elem
.getAttributeNodeNS(
1143 "http://xml.python.org/ns2", "d").isSameNode(attr
)
1144 and attrmap
["p:d"].isSameNode(attr
)
1145 and attrmap
[("http://xml.python.org/ns2", "d")].isSameNode(attr
))
1147 # Rename back to a simple non-NS node
1148 attr
= doc
.renameNode(attr
, xml
.dom
.EMPTY_NAMESPACE
, "e")
1149 self
.confirm(attr
.name
== "e"
1150 and attr
.nodeName
== "e"
1151 and attr
.localName
is None
1152 and attr
.namespaceURI
== xml
.dom
.EMPTY_NAMESPACE
1153 and attr
.prefix
is None
1154 and attr
.value
== "v"
1155 and elem
.getAttributeNode("a") is None
1156 and elem
.getAttributeNode("b") is None
1157 and elem
.getAttributeNode("c") is None
1158 and elem
.getAttributeNode("p:d") is None
1159 and elem
.getAttributeNodeNS(
1160 "http://xml.python.org/ns", "c") is None
1161 and elem
.getAttributeNode("e").isSameNode(attr
)
1162 and attrmap
["e"].isSameNode(attr
))
1164 self
.assertRaises(xml
.dom
.NamespaceErr
, doc
.renameNode
, attr
,
1165 "http://xml.python.org/ns", "xmlns")
1166 self
.checkRenameNodeSharedConstraints(doc
, attr
)
1169 def testRenameElement(self
):
1170 doc
= parseString("<doc/>")
1171 elem
= doc
.documentElement
1174 elem
= doc
.renameNode(elem
, xml
.dom
.EMPTY_NAMESPACE
, "a")
1175 self
.confirm(elem
.tagName
== "a"
1176 and elem
.nodeName
== "a"
1177 and elem
.localName
is None
1178 and elem
.namespaceURI
== xml
.dom
.EMPTY_NAMESPACE
1179 and elem
.prefix
is None
1180 and elem
.ownerDocument
.isSameNode(doc
))
1182 # Rename to have a namespace, no prefix
1183 elem
= doc
.renameNode(elem
, "http://xml.python.org/ns", "b")
1184 self
.confirm(elem
.tagName
== "b"
1185 and elem
.nodeName
== "b"
1186 and elem
.localName
== "b"
1187 and elem
.namespaceURI
== "http://xml.python.org/ns"
1188 and elem
.prefix
is None
1189 and elem
.ownerDocument
.isSameNode(doc
))
1191 # Rename to have a namespace, with prefix
1192 elem
= doc
.renameNode(elem
, "http://xml.python.org/ns2", "p:c")
1193 self
.confirm(elem
.tagName
== "p:c"
1194 and elem
.nodeName
== "p:c"
1195 and elem
.localName
== "c"
1196 and elem
.namespaceURI
== "http://xml.python.org/ns2"
1197 and elem
.prefix
== "p"
1198 and elem
.ownerDocument
.isSameNode(doc
))
1200 # Rename back to a simple non-NS node
1201 elem
= doc
.renameNode(elem
, xml
.dom
.EMPTY_NAMESPACE
, "d")
1202 self
.confirm(elem
.tagName
== "d"
1203 and elem
.nodeName
== "d"
1204 and elem
.localName
is None
1205 and elem
.namespaceURI
== xml
.dom
.EMPTY_NAMESPACE
1206 and elem
.prefix
is None
1207 and elem
.ownerDocument
.isSameNode(doc
))
1209 self
.checkRenameNodeSharedConstraints(doc
, elem
)
1212 def testRenameOther(self
):
1213 # We have to create a comment node explicitly since not all DOM
1214 # builders used with minidom add comments to the DOM.
1215 doc
= xml
.dom
.minidom
.getDOMImplementation().createDocument(
1216 xml
.dom
.EMPTY_NAMESPACE
, "e", None)
1217 node
= doc
.createComment("comment")
1218 self
.assertRaises(xml
.dom
.NotSupportedErr
, doc
.renameNode
, node
,
1219 xml
.dom
.EMPTY_NAMESPACE
, "foo")
1222 def testWholeText(self
):
1223 doc
= parseString("<doc>a</doc>")
1224 elem
= doc
.documentElement
1225 text
= elem
.childNodes
[0]
1226 self
.assertEquals(text
.nodeType
, Node
.TEXT_NODE
)
1228 self
.checkWholeText(text
, "a")
1229 elem
.appendChild(doc
.createTextNode("b"))
1230 self
.checkWholeText(text
, "ab")
1231 elem
.insertBefore(doc
.createCDATASection("c"), text
)
1232 self
.checkWholeText(text
, "cab")
1234 # make sure we don't cross other nodes
1235 splitter
= doc
.createComment("comment")
1236 elem
.appendChild(splitter
)
1237 text2
= doc
.createTextNode("d")
1238 elem
.appendChild(text2
)
1239 self
.checkWholeText(text
, "cab")
1240 self
.checkWholeText(text2
, "d")
1242 x
= doc
.createElement("x")
1243 elem
.replaceChild(x
, splitter
)
1245 self
.checkWholeText(text
, "cab")
1246 self
.checkWholeText(text2
, "d")
1248 x
= doc
.createProcessingInstruction("y", "z")
1249 elem
.replaceChild(x
, splitter
)
1251 self
.checkWholeText(text
, "cab")
1252 self
.checkWholeText(text2
, "d")
1254 elem
.removeChild(splitter
)
1255 self
.checkWholeText(text
, "cabd")
1256 self
.checkWholeText(text2
, "cabd")
1258 def testPatch1094164(self
):
1259 doc
= parseString("<doc><e/></doc>")
1260 elem
= doc
.documentElement
1262 self
.confirm(e
.parentNode
is elem
, "Before replaceChild()")
1263 # Check that replacing a child with itself leaves the tree unchanged
1264 elem
.replaceChild(e
, e
)
1265 self
.confirm(e
.parentNode
is elem
, "After replaceChild()")
1267 def testReplaceWholeText(self
):
1269 doc
= parseString("<doc>a<e/>d</doc>")
1270 elem
= doc
.documentElement
1271 text1
= elem
.firstChild
1272 text2
= elem
.lastChild
1273 splitter
= text1
.nextSibling
1274 elem
.insertBefore(doc
.createTextNode("b"), splitter
)
1275 elem
.insertBefore(doc
.createCDATASection("c"), text1
)
1276 return doc
, elem
, text1
, splitter
, text2
1278 doc
, elem
, text1
, splitter
, text2
= setup()
1279 text
= text1
.replaceWholeText("new content")
1280 self
.checkWholeText(text
, "new content")
1281 self
.checkWholeText(text2
, "d")
1282 self
.confirm(len(elem
.childNodes
) == 3)
1284 doc
, elem
, text1
, splitter
, text2
= setup()
1285 text
= text2
.replaceWholeText("new content")
1286 self
.checkWholeText(text
, "new content")
1287 self
.checkWholeText(text1
, "cab")
1288 self
.confirm(len(elem
.childNodes
) == 5)
1290 doc
, elem
, text1
, splitter
, text2
= setup()
1291 text
= text1
.replaceWholeText("")
1292 self
.checkWholeText(text2
, "d")
1293 self
.confirm(text
is None
1294 and len(elem
.childNodes
) == 2)
1296 def testSchemaType(self
):
1299 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
1300 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
1301 " <!ATTLIST doc id ID #IMPLIED \n"
1302 " ref IDREF #IMPLIED \n"
1303 " refs IDREFS #IMPLIED \n"
1304 " enum (a|b) #IMPLIED \n"
1305 " ent ENTITY #IMPLIED \n"
1306 " ents ENTITIES #IMPLIED \n"
1307 " nm NMTOKEN #IMPLIED \n"
1308 " nms NMTOKENS #IMPLIED \n"
1309 " text CDATA #IMPLIED \n"
1311 "]><doc id='name' notid='name' text='splat!' enum='b'"
1312 " ref='name' refs='name name' ent='e1' ents='e1 e2'"
1313 " nm='123' nms='123 abc' />")
1314 elem
= doc
.documentElement
1315 # We don't want to rely on any specific loader at this point, so
1316 # just make sure we can get to all the names, and that the
1317 # DTD-based namespace is right. The names can vary by loader
1318 # since each supports a different level of DTD information.
1320 self
.confirm(t
.name
is None
1321 and t
.namespace
== xml
.dom
.EMPTY_NAMESPACE
)
1322 names
= "id notid text enum ref refs ent ents nm nms".split()
1324 a
= elem
.getAttributeNode(name
)
1326 self
.confirm(hasattr(t
, "name")
1327 and t
.namespace
== xml
.dom
.EMPTY_NAMESPACE
)
1329 def testSetIdAttribute(self
):
1330 doc
= parseString("<doc a1='v' a2='w'/>")
1331 e
= doc
.documentElement
1332 a1
= e
.getAttributeNode("a1")
1333 a2
= e
.getAttributeNode("a2")
1334 self
.confirm(doc
.getElementById("v") is None
1337 e
.setIdAttribute("a1")
1338 self
.confirm(e
.isSameNode(doc
.getElementById("v"))
1341 e
.setIdAttribute("a2")
1342 self
.confirm(e
.isSameNode(doc
.getElementById("v"))
1343 and e
.isSameNode(doc
.getElementById("w"))
1346 # replace the a1 node; the new node should *not* be an ID
1347 a3
= doc
.createAttribute("a1")
1349 e
.setAttributeNode(a3
)
1350 self
.confirm(doc
.getElementById("v") is None
1351 and e
.isSameNode(doc
.getElementById("w"))
1355 # renaming an attribute should not affect its ID-ness:
1356 doc
.renameNode(a2
, xml
.dom
.EMPTY_NAMESPACE
, "an")
1357 self
.confirm(e
.isSameNode(doc
.getElementById("w"))
1360 def testSetIdAttributeNS(self
):
1361 NS1
= "http://xml.python.org/ns1"
1362 NS2
= "http://xml.python.org/ns2"
1363 doc
= parseString("<doc"
1364 " xmlns:ns1='" + NS1
+ "'"
1365 " xmlns:ns2='" + NS2
+ "'"
1366 " ns1:a1='v' ns2:a2='w'/>")
1367 e
= doc
.documentElement
1368 a1
= e
.getAttributeNodeNS(NS1
, "a1")
1369 a2
= e
.getAttributeNodeNS(NS2
, "a2")
1370 self
.confirm(doc
.getElementById("v") is None
1373 e
.setIdAttributeNS(NS1
, "a1")
1374 self
.confirm(e
.isSameNode(doc
.getElementById("v"))
1377 e
.setIdAttributeNS(NS2
, "a2")
1378 self
.confirm(e
.isSameNode(doc
.getElementById("v"))
1379 and e
.isSameNode(doc
.getElementById("w"))
1382 # replace the a1 node; the new node should *not* be an ID
1383 a3
= doc
.createAttributeNS(NS1
, "a1")
1385 e
.setAttributeNode(a3
)
1386 self
.confirm(e
.isSameNode(doc
.getElementById("w")))
1387 self
.confirm(not a1
.isId
)
1388 self
.confirm(a2
.isId
)
1389 self
.confirm(not a3
.isId
)
1390 self
.confirm(doc
.getElementById("v") is None)
1391 # renaming an attribute should not affect its ID-ness:
1392 doc
.renameNode(a2
, xml
.dom
.EMPTY_NAMESPACE
, "an")
1393 self
.confirm(e
.isSameNode(doc
.getElementById("w"))
1396 def testSetIdAttributeNode(self
):
1397 NS1
= "http://xml.python.org/ns1"
1398 NS2
= "http://xml.python.org/ns2"
1399 doc
= parseString("<doc"
1400 " xmlns:ns1='" + NS1
+ "'"
1401 " xmlns:ns2='" + NS2
+ "'"
1402 " ns1:a1='v' ns2:a2='w'/>")
1403 e
= doc
.documentElement
1404 a1
= e
.getAttributeNodeNS(NS1
, "a1")
1405 a2
= e
.getAttributeNodeNS(NS2
, "a2")
1406 self
.confirm(doc
.getElementById("v") is None
1409 e
.setIdAttributeNode(a1
)
1410 self
.confirm(e
.isSameNode(doc
.getElementById("v"))
1413 e
.setIdAttributeNode(a2
)
1414 self
.confirm(e
.isSameNode(doc
.getElementById("v"))
1415 and e
.isSameNode(doc
.getElementById("w"))
1418 # replace the a1 node; the new node should *not* be an ID
1419 a3
= doc
.createAttributeNS(NS1
, "a1")
1421 e
.setAttributeNode(a3
)
1422 self
.confirm(e
.isSameNode(doc
.getElementById("w")))
1423 self
.confirm(not a1
.isId
)
1424 self
.confirm(a2
.isId
)
1425 self
.confirm(not a3
.isId
)
1426 self
.confirm(doc
.getElementById("v") is None)
1427 # renaming an attribute should not affect its ID-ness:
1428 doc
.renameNode(a2
, xml
.dom
.EMPTY_NAMESPACE
, "an")
1429 self
.confirm(e
.isSameNode(doc
.getElementById("w"))
1432 def testPickledDocument(self
):
1433 doc
= parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
1434 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
1435 " 'http://xml.python.org/system' [\n"
1436 " <!ELEMENT e EMPTY>\n"
1437 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
1438 "]><doc attr='value'> text\n"
1439 "<?pi sample?> <!-- comment --> <e/> </doc>")
1440 s
= pickle
.dumps(doc
)
1441 doc2
= pickle
.loads(s
)
1442 stack
= [(doc
, doc2
)]
1444 n1
, n2
= stack
.pop()
1445 self
.confirm(n1
.nodeType
== n2
.nodeType
1446 and len(n1
.childNodes
) == len(n2
.childNodes
)
1447 and n1
.nodeName
== n2
.nodeName
1448 and not n1
.isSameNode(n2
)
1449 and not n2
.isSameNode(n1
))
1450 if n1
.nodeType
== Node
.DOCUMENT_TYPE_NODE
:
1455 self
.confirm(len(n1
.entities
) == len(n2
.entities
)
1456 and len(n1
.notations
) == len(n2
.notations
))
1457 for i
in range(len(n1
.notations
)):
1458 no1
= n1
.notations
.item(i
)
1459 no2
= n1
.notations
.item(i
)
1460 self
.confirm(no1
.name
== no2
.name
1461 and no1
.publicId
== no2
.publicId
1462 and no1
.systemId
== no2
.systemId
)
1463 statck
.append((no1
, no2
))
1464 for i
in range(len(n1
.entities
)):
1465 e1
= n1
.entities
.item(i
)
1466 e2
= n2
.entities
.item(i
)
1467 self
.confirm(e1
.notationName
== e2
.notationName
1468 and e1
.publicId
== e2
.publicId
1469 and e1
.systemId
== e2
.systemId
)
1470 stack
.append((e1
, e2
))
1471 if n1
.nodeType
!= Node
.DOCUMENT_NODE
:
1472 self
.confirm(n1
.ownerDocument
.isSameNode(doc
)
1473 and n2
.ownerDocument
.isSameNode(doc2
))
1474 for i
in range(len(n1
.childNodes
)):
1475 stack
.append((n1
.childNodes
[i
], n2
.childNodes
[i
]))
1477 def testSerializeCommentNodeWithDoubleHyphen(self
):
1478 doc
= create_doc_without_doctype()
1479 doc
.appendChild(doc
.createComment("foo--bar"))
1480 self
.assertRaises(ValueError, doc
.toxml
)
1483 run_unittest(MinidomTest
)
1485 if __name__
== "__main__":