blob: 7ccb8f40c76c9350e3ec967a03edf04d0d524984 [file] [log] [blame]
Fred Drakefbdeaad2006-07-29 16:56:15 +00001# test for xml.dom.minidom
Paul Prescod7993bcc2000-07-01 14:54:16 +00002
Guido van Rossume2ae77b2001-10-24 20:42:55 +00003import os
Fred Drake17647f52000-07-03 16:37:42 +00004import sys
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +00005import pickle
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +00006from StringIO import StringIO
Benjamin Petersonbec087f2009-03-26 21:10:30 +00007from test.test_support import verbose, run_unittest
Collin Winterd28fcbc2007-03-28 23:34:06 +00008import unittest
Fred Drake17647f52000-07-03 16:37:42 +00009
Fred Drakefbdeaad2006-07-29 16:56:15 +000010import xml.dom
11import xml.dom.minidom
12import xml.parsers.expat
Fred Drakec441f7b2002-07-19 22:16:41 +000013
Fred Drakefbdeaad2006-07-29 16:56:15 +000014from xml.dom.minidom import parse, Node, Document, parseString
15from xml.dom.minidom import getDOMImplementation
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +000016
Fred Drakec441f7b2002-07-19 22:16:41 +000017
Fred Drake17647f52000-07-03 16:37:42 +000018if __name__ == "__main__":
19 base = sys.argv[0]
20else:
21 base = __file__
Guido van Rossume2ae77b2001-10-24 20:42:55 +000022tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml")
Fred Drake17647f52000-07-03 16:37:42 +000023del base
Paul Prescod7993bcc2000-07-01 14:54:16 +000024
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000025# The tests of DocumentType importing use these helpers to construct
26# the documents to work with, since not all DOM builders actually
27# create the DocumentType nodes.
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000028def create_doc_without_doctype(doctype=None):
29 return getDOMImplementation().createDocument(None, "doc", doctype)
30
31def create_nonempty_doctype():
32 doctype = getDOMImplementation().createDocumentType("doc", None, None)
33 doctype.entities._seq = []
34 doctype.notations._seq = []
Fred Drakefbdeaad2006-07-29 16:56:15 +000035 notation = xml.dom.minidom.Notation("my-notation", None,
36 "http://xml.python.org/notations/my")
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000037 doctype.notations._seq.append(notation)
Fred Drakefbdeaad2006-07-29 16:56:15 +000038 entity = xml.dom.minidom.Entity("my-entity", None,
39 "http://xml.python.org/entities/my",
40 "my-notation")
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000041 entity.version = "1.0"
42 entity.encoding = "utf-8"
43 entity.actualEncoding = "us-ascii"
44 doctype.entities._seq.append(entity)
45 return doctype
46
47def create_doc_with_doctype():
48 doctype = create_nonempty_doctype()
49 doc = create_doc_without_doctype(doctype)
50 doctype.entities.item(0).ownerDocument = doc
51 doctype.notations.item(0).ownerDocument = doc
52 return doc
53
Collin Winterd28fcbc2007-03-28 23:34:06 +000054class MinidomTest(unittest.TestCase):
55 def tearDown(self):
Paul Prescod7993bcc2000-07-01 14:54:16 +000056 try:
Collin Winterd28fcbc2007-03-28 23:34:06 +000057 Node.allnodes
58 except AttributeError:
59 # We don't actually have the minidom from the standard library,
60 # but are picking up the PyXML version from site-packages.
61 pass
62 else:
63 self.confirm(len(Node.allnodes) == 0,
64 "assertion: len(Node.allnodes) == 0")
65 if len(Node.allnodes):
66 print "Garbage left over:"
67 if verbose:
68 print Node.allnodes.items()[0:10]
69 else:
70 # Don't print specific nodes if repeatable results
71 # are needed
72 print len(Node.allnodes)
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000073 Node.allnodes = {}
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000074
Collin Winterd28fcbc2007-03-28 23:34:06 +000075 def confirm(self, test, testname = "Test"):
76 self.assertTrue(test, testname)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000077
Collin Winterd28fcbc2007-03-28 23:34:06 +000078 def checkWholeText(self, node, s):
79 t = node.wholeText
80 self.confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000081
Collin Winterd28fcbc2007-03-28 23:34:06 +000082 def testParseFromFile(self):
83 dom = parse(StringIO(open(tstfile).read()))
84 dom.unlink()
85 self.confirm(isinstance(dom,Document))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000086
Collin Winterd28fcbc2007-03-28 23:34:06 +000087 def testGetElementsByTagName(self):
88 dom = parse(tstfile)
89 self.confirm(dom.getElementsByTagName("LI") == \
90 dom.documentElement.getElementsByTagName("LI"))
91 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000092
Collin Winterd28fcbc2007-03-28 23:34:06 +000093 def testInsertBefore(self):
94 dom = parseString("<doc><foo/></doc>")
95 root = dom.documentElement
96 elem = root.childNodes[0]
97 nelem = dom.createElement("element")
98 root.insertBefore(nelem, elem)
99 self.confirm(len(root.childNodes) == 2
100 and root.childNodes.length == 2
101 and root.childNodes[0] is nelem
102 and root.childNodes.item(0) is nelem
103 and root.childNodes[1] is elem
104 and root.childNodes.item(1) is elem
105 and root.firstChild is nelem
106 and root.lastChild is elem
107 and root.toxml() == "<doc><element/><foo/></doc>"
108 , "testInsertBefore -- node properly placed in tree")
109 nelem = dom.createElement("element")
110 root.insertBefore(nelem, None)
111 self.confirm(len(root.childNodes) == 3
112 and root.childNodes.length == 3
113 and root.childNodes[1] is elem
114 and root.childNodes.item(1) is elem
115 and root.childNodes[2] is nelem
116 and root.childNodes.item(2) is nelem
117 and root.lastChild is nelem
118 and nelem.previousSibling is elem
119 and root.toxml() == "<doc><element/><foo/><element/></doc>"
120 , "testInsertBefore -- node properly placed in tree")
121 nelem2 = dom.createElement("bar")
122 root.insertBefore(nelem2, nelem)
123 self.confirm(len(root.childNodes) == 4
124 and root.childNodes.length == 4
125 and root.childNodes[2] is nelem2
126 and root.childNodes.item(2) is nelem2
127 and root.childNodes[3] is nelem
128 and root.childNodes.item(3) is nelem
129 and nelem2.nextSibling is nelem
130 and nelem.previousSibling is nelem2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000131 and root.toxml() ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000132 "<doc><element/><foo/><bar/><element/></doc>"
133 , "testInsertBefore -- node properly placed in tree")
134 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000135
Collin Winterd28fcbc2007-03-28 23:34:06 +0000136 def _create_fragment_test_nodes(self):
137 dom = parseString("<doc/>")
138 orig = dom.createTextNode("original")
139 c1 = dom.createTextNode("foo")
140 c2 = dom.createTextNode("bar")
141 c3 = dom.createTextNode("bat")
142 dom.documentElement.appendChild(orig)
143 frag = dom.createDocumentFragment()
144 frag.appendChild(c1)
145 frag.appendChild(c2)
146 frag.appendChild(c3)
147 return dom, orig, c1, c2, c3, frag
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000148
Collin Winterd28fcbc2007-03-28 23:34:06 +0000149 def testInsertBeforeFragment(self):
150 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
151 dom.documentElement.insertBefore(frag, None)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000152 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000153 (orig, c1, c2, c3),
154 "insertBefore(<fragment>, None)")
155 frag.unlink()
156 dom.unlink()
Paul Prescod10d27662000-09-18 19:07:26 +0000157
Collin Winterd28fcbc2007-03-28 23:34:06 +0000158 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
159 dom.documentElement.insertBefore(frag, orig)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000160 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000161 (c1, c2, c3, orig),
162 "insertBefore(<fragment>, orig)")
163 frag.unlink()
164 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000165
Collin Winterd28fcbc2007-03-28 23:34:06 +0000166 def testAppendChild(self):
167 dom = parse(tstfile)
168 dom.documentElement.appendChild(dom.createComment(u"Hello"))
169 self.confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
170 self.confirm(dom.documentElement.childNodes[-1].data == "Hello")
171 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000172
Collin Winterd28fcbc2007-03-28 23:34:06 +0000173 def testAppendChildFragment(self):
174 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
175 dom.documentElement.appendChild(frag)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000176 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000177 (orig, c1, c2, c3),
178 "appendChild(<fragment>)")
179 frag.unlink()
180 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000181
Collin Winterd28fcbc2007-03-28 23:34:06 +0000182 def testReplaceChildFragment(self):
183 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
184 dom.documentElement.replaceChild(frag, orig)
185 orig.unlink()
186 self.confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
187 "replaceChild(<fragment>)")
188 frag.unlink()
189 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000190
Collin Winterd28fcbc2007-03-28 23:34:06 +0000191 def testLegalChildren(self):
192 dom = Document()
193 elem = dom.createElement('element')
194 text = dom.createTextNode('text')
195 self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000196
Collin Winterd28fcbc2007-03-28 23:34:06 +0000197 dom.appendChild(elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000198 self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000199 elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000200 self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000201 elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000202
Collin Winterd28fcbc2007-03-28 23:34:06 +0000203 nodemap = elem.attributes
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000204 self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000205 text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000206 self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000207 text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000208
Collin Winterd28fcbc2007-03-28 23:34:06 +0000209 elem.appendChild(text)
210 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000211
Collin Winterd28fcbc2007-03-28 23:34:06 +0000212 def testNamedNodeMapSetItem(self):
213 dom = Document()
214 elem = dom.createElement('element')
215 attrs = elem.attributes
216 attrs["foo"] = "bar"
217 a = attrs.item(0)
218 self.confirm(a.ownerDocument is dom,
219 "NamedNodeMap.__setitem__() sets ownerDocument")
220 self.confirm(a.ownerElement is elem,
221 "NamedNodeMap.__setitem__() sets ownerElement")
222 self.confirm(a.value == "bar",
223 "NamedNodeMap.__setitem__() sets value")
224 self.confirm(a.nodeValue == "bar",
225 "NamedNodeMap.__setitem__() sets nodeValue")
226 elem.unlink()
227 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000228
Collin Winterd28fcbc2007-03-28 23:34:06 +0000229 def testNonZero(self):
230 dom = parse(tstfile)
231 self.confirm(dom)# should not be zero
232 dom.appendChild(dom.createComment("foo"))
233 self.confirm(not dom.childNodes[-1].childNodes)
234 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000235
Collin Winterd28fcbc2007-03-28 23:34:06 +0000236 def testUnlink(self):
237 dom = parse(tstfile)
238 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000239
Collin Winterd28fcbc2007-03-28 23:34:06 +0000240 def testElement(self):
241 dom = Document()
242 dom.appendChild(dom.createElement("abc"))
243 self.confirm(dom.documentElement)
244 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000245
Collin Winterd28fcbc2007-03-28 23:34:06 +0000246 def testAAA(self):
247 dom = parseString("<abc/>")
248 el = dom.documentElement
249 el.setAttribute("spam", "jam2")
250 self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
251 a = el.getAttributeNode("spam")
252 self.confirm(a.ownerDocument is dom,
253 "setAttribute() sets ownerDocument")
254 self.confirm(a.ownerElement is dom.documentElement,
255 "setAttribute() sets ownerElement")
256 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000257
Collin Winterd28fcbc2007-03-28 23:34:06 +0000258 def testAAB(self):
259 dom = parseString("<abc/>")
260 el = dom.documentElement
261 el.setAttribute("spam", "jam")
262 el.setAttribute("spam", "jam2")
263 self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
264 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000265
Collin Winterd28fcbc2007-03-28 23:34:06 +0000266 def testAddAttr(self):
267 dom = Document()
268 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000269
Collin Winterd28fcbc2007-03-28 23:34:06 +0000270 child.setAttribute("def", "ghi")
271 self.confirm(child.getAttribute("def") == "ghi")
272 self.confirm(child.attributes["def"].value == "ghi")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000273
Collin Winterd28fcbc2007-03-28 23:34:06 +0000274 child.setAttribute("jkl", "mno")
275 self.confirm(child.getAttribute("jkl") == "mno")
276 self.confirm(child.attributes["jkl"].value == "mno")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000277
Collin Winterd28fcbc2007-03-28 23:34:06 +0000278 self.confirm(len(child.attributes) == 2)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000279
Collin Winterd28fcbc2007-03-28 23:34:06 +0000280 child.setAttribute("def", "newval")
281 self.confirm(child.getAttribute("def") == "newval")
282 self.confirm(child.attributes["def"].value == "newval")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000283
Collin Winterd28fcbc2007-03-28 23:34:06 +0000284 self.confirm(len(child.attributes) == 2)
285 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000286
Collin Winterd28fcbc2007-03-28 23:34:06 +0000287 def testDeleteAttr(self):
288 dom = Document()
289 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000290
Collin Winterd28fcbc2007-03-28 23:34:06 +0000291 self.confirm(len(child.attributes) == 0)
292 child.setAttribute("def", "ghi")
293 self.confirm(len(child.attributes) == 1)
294 del child.attributes["def"]
295 self.confirm(len(child.attributes) == 0)
296 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000297
Collin Winterd28fcbc2007-03-28 23:34:06 +0000298 def testRemoveAttr(self):
299 dom = Document()
300 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000301
Collin Winterd28fcbc2007-03-28 23:34:06 +0000302 child.setAttribute("def", "ghi")
303 self.confirm(len(child.attributes) == 1)
304 child.removeAttribute("def")
305 self.confirm(len(child.attributes) == 0)
306 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000307
Collin Winterd28fcbc2007-03-28 23:34:06 +0000308 def testRemoveAttrNS(self):
309 dom = Document()
310 child = dom.appendChild(
311 dom.createElementNS("http://www.python.org", "python:abc"))
312 child.setAttributeNS("http://www.w3.org", "xmlns:python",
313 "http://www.python.org")
314 child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
315 self.confirm(len(child.attributes) == 2)
316 child.removeAttributeNS("http://www.python.org", "abcattr")
317 self.confirm(len(child.attributes) == 1)
318 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000319
Collin Winterd28fcbc2007-03-28 23:34:06 +0000320 def testRemoveAttributeNode(self):
321 dom = Document()
322 child = dom.appendChild(dom.createElement("foo"))
323 child.setAttribute("spam", "jam")
324 self.confirm(len(child.attributes) == 1)
325 node = child.getAttributeNode("spam")
326 child.removeAttributeNode(node)
327 self.confirm(len(child.attributes) == 0
328 and child.getAttributeNode("spam") is None)
329 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000330
Collin Winterd28fcbc2007-03-28 23:34:06 +0000331 def testChangeAttr(self):
332 dom = parseString("<abc/>")
333 el = dom.documentElement
334 el.setAttribute("spam", "jam")
335 self.confirm(len(el.attributes) == 1)
336 el.setAttribute("spam", "bam")
337 # Set this attribute to be an ID and make sure that doesn't change
338 # when changing the value:
339 el.setIdAttribute("spam")
340 self.confirm(len(el.attributes) == 1
341 and el.attributes["spam"].value == "bam"
342 and el.attributes["spam"].nodeValue == "bam"
343 and el.getAttribute("spam") == "bam"
344 and el.getAttributeNode("spam").isId)
345 el.attributes["spam"] = "ham"
346 self.confirm(len(el.attributes) == 1
347 and el.attributes["spam"].value == "ham"
348 and el.attributes["spam"].nodeValue == "ham"
349 and el.getAttribute("spam") == "ham"
350 and el.attributes["spam"].isId)
351 el.setAttribute("spam2", "bam")
352 self.confirm(len(el.attributes) == 2
353 and el.attributes["spam"].value == "ham"
354 and el.attributes["spam"].nodeValue == "ham"
355 and el.getAttribute("spam") == "ham"
356 and el.attributes["spam2"].value == "bam"
357 and el.attributes["spam2"].nodeValue == "bam"
358 and el.getAttribute("spam2") == "bam")
359 el.attributes["spam2"] = "bam2"
360 self.confirm(len(el.attributes) == 2
361 and el.attributes["spam"].value == "ham"
362 and el.attributes["spam"].nodeValue == "ham"
363 and el.getAttribute("spam") == "ham"
364 and el.attributes["spam2"].value == "bam2"
365 and el.attributes["spam2"].nodeValue == "bam2"
366 and el.getAttribute("spam2") == "bam2")
367 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000368
Collin Winterd28fcbc2007-03-28 23:34:06 +0000369 def testGetAttrList(self):
370 pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000371
Collin Winterd28fcbc2007-03-28 23:34:06 +0000372 def testGetAttrValues(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000373
Collin Winterd28fcbc2007-03-28 23:34:06 +0000374 def testGetAttrLength(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000375
Collin Winterd28fcbc2007-03-28 23:34:06 +0000376 def testGetAttribute(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000377
Collin Winterd28fcbc2007-03-28 23:34:06 +0000378 def testGetAttributeNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000379
Collin Winterd28fcbc2007-03-28 23:34:06 +0000380 def testGetAttributeNode(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000381
Collin Winterd28fcbc2007-03-28 23:34:06 +0000382 def testGetElementsByTagNameNS(self):
383 d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
384 <minidom:myelem/>
385 </foo>"""
386 dom = parseString(d)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000387 elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom",
Collin Winterd28fcbc2007-03-28 23:34:06 +0000388 "myelem")
389 self.confirm(len(elems) == 1
390 and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"
391 and elems[0].localName == "myelem"
392 and elems[0].prefix == "minidom"
393 and elems[0].tagName == "minidom:myelem"
394 and elems[0].nodeName == "minidom:myelem")
395 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000396
397 def get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000398 lname):
399 nodelist = doc.getElementsByTagNameNS(nsuri, lname)
400 self.confirm(len(nodelist) == 0)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000401
Collin Winterd28fcbc2007-03-28 23:34:06 +0000402 def testGetEmptyNodeListFromElementsByTagNameNS(self):
403 doc = parseString('<doc/>')
404 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
405 doc, 'http://xml.python.org/namespaces/a', 'localname')
406 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
407 doc, '*', 'splat')
408 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
409 doc, 'http://xml.python.org/namespaces/a', '*')
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000410
Collin Winterd28fcbc2007-03-28 23:34:06 +0000411 doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
412 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
413 doc, "http://xml.python.org/splat", "not-there")
414 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
415 doc, "*", "not-there")
416 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
417 doc, "http://somewhere.else.net/not-there", "e")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000418
Collin Winterd28fcbc2007-03-28 23:34:06 +0000419 def testElementReprAndStr(self):
420 dom = Document()
421 el = dom.appendChild(dom.createElement("abc"))
422 string1 = repr(el)
423 string2 = str(el)
424 self.confirm(string1 == string2)
425 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000426
Collin Winterd28fcbc2007-03-28 23:34:06 +0000427 def testElementReprAndStrUnicode(self):
428 dom = Document()
429 el = dom.appendChild(dom.createElement(u"abc"))
430 string1 = repr(el)
431 string2 = str(el)
432 self.confirm(string1 == string2)
433 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000434
Collin Winterd28fcbc2007-03-28 23:34:06 +0000435 def testElementReprAndStrUnicodeNS(self):
436 dom = Document()
437 el = dom.appendChild(
438 dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
439 string1 = repr(el)
440 string2 = str(el)
441 self.confirm(string1 == string2)
442 self.confirm(string1.find("slash:abc") != -1)
443 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000444
Collin Winterd28fcbc2007-03-28 23:34:06 +0000445 def testAttributeRepr(self):
446 dom = Document()
447 el = dom.appendChild(dom.createElement(u"abc"))
448 node = el.setAttribute("abc", "def")
449 self.confirm(str(node) == repr(node))
450 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000451
Collin Winterd28fcbc2007-03-28 23:34:06 +0000452 def testTextNodeRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000453
Collin Winterd28fcbc2007-03-28 23:34:06 +0000454 def testWriteXML(self):
455 str = '<?xml version="1.0" ?><a b="c"/>'
456 dom = parseString(str)
457 domstr = dom.toxml()
458 dom.unlink()
459 self.confirm(str == domstr)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000460
Collin Winterd28fcbc2007-03-28 23:34:06 +0000461 def testAltNewline(self):
462 str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
463 dom = parseString(str)
464 domstr = dom.toprettyxml(newl="\r\n")
465 dom.unlink()
466 self.confirm(domstr == str.replace("\n", "\r\n"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000467
Collin Winterd28fcbc2007-03-28 23:34:06 +0000468 def testProcessingInstruction(self):
469 dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
470 pi = dom.documentElement.firstChild
471 self.confirm(pi.target == "mypi"
472 and pi.data == "data \t\n "
473 and pi.nodeName == "mypi"
474 and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
475 and pi.attributes is None
476 and not pi.hasChildNodes()
477 and len(pi.childNodes) == 0
478 and pi.firstChild is None
479 and pi.lastChild is None
480 and pi.localName is None
481 and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000482
Collin Winterd28fcbc2007-03-28 23:34:06 +0000483 def testProcessingInstructionRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000484
Collin Winterd28fcbc2007-03-28 23:34:06 +0000485 def testTextRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000486
Collin Winterd28fcbc2007-03-28 23:34:06 +0000487 def testWriteText(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000488
Collin Winterd28fcbc2007-03-28 23:34:06 +0000489 def testDocumentElement(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000490
Collin Winterd28fcbc2007-03-28 23:34:06 +0000491 def testTooManyDocumentElements(self):
492 doc = parseString("<doc/>")
493 elem = doc.createElement("extra")
494 # Should raise an exception when adding an extra document element.
495 self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem)
496 elem.unlink()
497 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000498
Collin Winterd28fcbc2007-03-28 23:34:06 +0000499 def testCreateElementNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000500
Collin Winterd28fcbc2007-03-28 23:34:06 +0000501 def testCreateAttributeNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000502
Collin Winterd28fcbc2007-03-28 23:34:06 +0000503 def testParse(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000504
Collin Winterd28fcbc2007-03-28 23:34:06 +0000505 def testParseString(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000506
Collin Winterd28fcbc2007-03-28 23:34:06 +0000507 def testComment(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000508
Collin Winterd28fcbc2007-03-28 23:34:06 +0000509 def testAttrListItem(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000510
Collin Winterd28fcbc2007-03-28 23:34:06 +0000511 def testAttrListItems(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000512
Collin Winterd28fcbc2007-03-28 23:34:06 +0000513 def testAttrListItemNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000514
Collin Winterd28fcbc2007-03-28 23:34:06 +0000515 def testAttrListKeys(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000516
Collin Winterd28fcbc2007-03-28 23:34:06 +0000517 def testAttrListKeysNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000518
Collin Winterd28fcbc2007-03-28 23:34:06 +0000519 def testRemoveNamedItem(self):
520 doc = parseString("<doc a=''/>")
521 e = doc.documentElement
522 attrs = e.attributes
523 a1 = e.getAttributeNode("a")
524 a2 = attrs.removeNamedItem("a")
525 self.confirm(a1.isSameNode(a2))
526 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000527
Collin Winterd28fcbc2007-03-28 23:34:06 +0000528 def testRemoveNamedItemNS(self):
529 doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
530 e = doc.documentElement
531 attrs = e.attributes
532 a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
533 a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
534 self.confirm(a1.isSameNode(a2))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000535 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000536 "http://xml.python.org/", "b")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000537
Collin Winterd28fcbc2007-03-28 23:34:06 +0000538 def testAttrListValues(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000539
Collin Winterd28fcbc2007-03-28 23:34:06 +0000540 def testAttrListLength(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000541
Collin Winterd28fcbc2007-03-28 23:34:06 +0000542 def testAttrList__getitem__(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000543
Collin Winterd28fcbc2007-03-28 23:34:06 +0000544 def testAttrList__setitem__(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000545
Collin Winterd28fcbc2007-03-28 23:34:06 +0000546 def testSetAttrValueandNodeValue(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000547
Collin Winterd28fcbc2007-03-28 23:34:06 +0000548 def testParseElement(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000549
Collin Winterd28fcbc2007-03-28 23:34:06 +0000550 def testParseAttributes(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000551
Collin Winterd28fcbc2007-03-28 23:34:06 +0000552 def testParseElementNamespaces(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000553
Collin Winterd28fcbc2007-03-28 23:34:06 +0000554 def testParseAttributeNamespaces(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000555
Collin Winterd28fcbc2007-03-28 23:34:06 +0000556 def testParseProcessingInstructions(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000557
Collin Winterd28fcbc2007-03-28 23:34:06 +0000558 def testChildNodes(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000559
Collin Winterd28fcbc2007-03-28 23:34:06 +0000560 def testFirstChild(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000561
Collin Winterd28fcbc2007-03-28 23:34:06 +0000562 def testHasChildNodes(self): pass
563
564 def _testCloneElementCopiesAttributes(self, e1, e2, test):
565 attrs1 = e1.attributes
566 attrs2 = e2.attributes
567 keys1 = attrs1.keys()
568 keys2 = attrs2.keys()
569 keys1.sort()
570 keys2.sort()
571 self.confirm(keys1 == keys2, "clone of element has same attribute keys")
572 for i in range(len(keys1)):
573 a1 = attrs1.item(i)
574 a2 = attrs2.item(i)
575 self.confirm(a1 is not a2
576 and a1.value == a2.value
577 and a1.nodeValue == a2.nodeValue
578 and a1.namespaceURI == a2.namespaceURI
579 and a1.localName == a2.localName
580 , "clone of attribute node has proper attribute values")
581 self.confirm(a2.ownerElement is e2,
582 "clone of attribute node correctly owned")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000583
Collin Winterd28fcbc2007-03-28 23:34:06 +0000584 def _setupCloneElement(self, deep):
585 dom = parseString("<doc attr='value'><foo/></doc>")
586 root = dom.documentElement
587 clone = root.cloneNode(deep)
588 self._testCloneElementCopiesAttributes(
589 root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
590 # mutilate the original so shared data is detected
591 root.tagName = root.nodeName = "MODIFIED"
592 root.setAttribute("attr", "NEW VALUE")
593 root.setAttribute("added", "VALUE")
594 return dom, clone
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000595
Collin Winterd28fcbc2007-03-28 23:34:06 +0000596 def testCloneElementShallow(self):
597 dom, clone = self._setupCloneElement(0)
598 self.confirm(len(clone.childNodes) == 0
599 and clone.childNodes.length == 0
600 and clone.parentNode is None
601 and clone.toxml() == '<doc attr="value"/>'
602 , "testCloneElementShallow")
603 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000604
Collin Winterd28fcbc2007-03-28 23:34:06 +0000605 def testCloneElementDeep(self):
606 dom, clone = self._setupCloneElement(1)
607 self.confirm(len(clone.childNodes) == 1
608 and clone.childNodes.length == 1
609 and clone.parentNode is None
610 and clone.toxml() == '<doc attr="value"><foo/></doc>'
611 , "testCloneElementDeep")
612 dom.unlink()
613
614 def testCloneDocumentShallow(self):
615 doc = parseString("<?xml version='1.0'?>\n"
616 "<!-- comment -->"
617 "<!DOCTYPE doc [\n"
618 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
619 "]>\n"
620 "<doc attr='value'/>")
621 doc2 = doc.cloneNode(0)
622 self.confirm(doc2 is None,
623 "testCloneDocumentShallow:"
624 " shallow cloning of documents makes no sense!")
625
626 def testCloneDocumentDeep(self):
627 doc = parseString("<?xml version='1.0'?>\n"
628 "<!-- comment -->"
629 "<!DOCTYPE doc [\n"
630 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
631 "]>\n"
632 "<doc attr='value'/>")
633 doc2 = doc.cloneNode(1)
634 self.confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
635 "testCloneDocumentDeep: document objects not distinct")
636 self.confirm(len(doc.childNodes) == len(doc2.childNodes),
637 "testCloneDocumentDeep: wrong number of Document children")
638 self.confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
639 "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
640 self.confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
641 "testCloneDocumentDeep: documentElement owner is not new document")
642 self.confirm(not doc.documentElement.isSameNode(doc2.documentElement),
643 "testCloneDocumentDeep: documentElement should not be shared")
644 if doc.doctype is not None:
645 # check the doctype iff the original DOM maintained it
646 self.confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
647 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
648 self.confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
649 self.confirm(not doc.doctype.isSameNode(doc2.doctype))
650
651 def testCloneDocumentTypeDeepOk(self):
652 doctype = create_nonempty_doctype()
653 clone = doctype.cloneNode(1)
654 self.confirm(clone is not None
655 and clone.nodeName == doctype.nodeName
656 and clone.name == doctype.name
657 and clone.publicId == doctype.publicId
658 and clone.systemId == doctype.systemId
659 and len(clone.entities) == len(doctype.entities)
660 and clone.entities.item(len(clone.entities)) is None
661 and len(clone.notations) == len(doctype.notations)
662 and clone.notations.item(len(clone.notations)) is None
663 and len(clone.childNodes) == 0)
664 for i in range(len(doctype.entities)):
665 se = doctype.entities.item(i)
666 ce = clone.entities.item(i)
667 self.confirm((not se.isSameNode(ce))
668 and (not ce.isSameNode(se))
669 and ce.nodeName == se.nodeName
670 and ce.notationName == se.notationName
671 and ce.publicId == se.publicId
672 and ce.systemId == se.systemId
673 and ce.encoding == se.encoding
674 and ce.actualEncoding == se.actualEncoding
675 and ce.version == se.version)
676 for i in range(len(doctype.notations)):
677 sn = doctype.notations.item(i)
678 cn = clone.notations.item(i)
679 self.confirm((not sn.isSameNode(cn))
680 and (not cn.isSameNode(sn))
681 and cn.nodeName == sn.nodeName
682 and cn.publicId == sn.publicId
683 and cn.systemId == sn.systemId)
684
685 def testCloneDocumentTypeDeepNotOk(self):
686 doc = create_doc_with_doctype()
687 clone = doc.doctype.cloneNode(1)
688 self.confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
689
690 def testCloneDocumentTypeShallowOk(self):
691 doctype = create_nonempty_doctype()
692 clone = doctype.cloneNode(0)
693 self.confirm(clone is not None
694 and clone.nodeName == doctype.nodeName
695 and clone.name == doctype.name
696 and clone.publicId == doctype.publicId
697 and clone.systemId == doctype.systemId
698 and len(clone.entities) == 0
699 and clone.entities.item(0) is None
700 and len(clone.notations) == 0
701 and clone.notations.item(0) is None
702 and len(clone.childNodes) == 0)
703
704 def testCloneDocumentTypeShallowNotOk(self):
705 doc = create_doc_with_doctype()
706 clone = doc.doctype.cloneNode(0)
707 self.confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
708
709 def check_import_document(self, deep, testName):
710 doc1 = parseString("<doc/>")
711 doc2 = parseString("<doc/>")
712 self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000713
Collin Winterd28fcbc2007-03-28 23:34:06 +0000714 def testImportDocumentShallow(self):
715 self.check_import_document(0, "testImportDocumentShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000716
Collin Winterd28fcbc2007-03-28 23:34:06 +0000717 def testImportDocumentDeep(self):
718 self.check_import_document(1, "testImportDocumentDeep")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000719
Collin Winterd28fcbc2007-03-28 23:34:06 +0000720 def testImportDocumentTypeShallow(self):
721 src = create_doc_with_doctype()
722 target = create_doc_without_doctype()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000723 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000724 src.doctype, 0)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000725
Collin Winterd28fcbc2007-03-28 23:34:06 +0000726 def testImportDocumentTypeDeep(self):
727 src = create_doc_with_doctype()
728 target = create_doc_without_doctype()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000729 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000730 src.doctype, 1)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000731
Collin Winterd28fcbc2007-03-28 23:34:06 +0000732 # Testing attribute clones uses a helper, and should always be deep,
733 # even if the argument to cloneNode is false.
734 def check_clone_attribute(self, deep, testName):
735 doc = parseString("<doc attr='value'/>")
736 attr = doc.documentElement.getAttributeNode("attr")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000737 self.assertNotEqual(attr, None)
Collin Winterd28fcbc2007-03-28 23:34:06 +0000738 clone = attr.cloneNode(deep)
739 self.confirm(not clone.isSameNode(attr))
740 self.confirm(not attr.isSameNode(clone))
741 self.confirm(clone.ownerElement is None,
742 testName + ": ownerElement should be None")
743 self.confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
744 testName + ": ownerDocument does not match")
745 self.confirm(clone.specified,
746 testName + ": cloned attribute must have specified == True")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000747
Collin Winterd28fcbc2007-03-28 23:34:06 +0000748 def testCloneAttributeShallow(self):
749 self.check_clone_attribute(0, "testCloneAttributeShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000750
Collin Winterd28fcbc2007-03-28 23:34:06 +0000751 def testCloneAttributeDeep(self):
752 self.check_clone_attribute(1, "testCloneAttributeDeep")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000753
Collin Winterd28fcbc2007-03-28 23:34:06 +0000754 def check_clone_pi(self, deep, testName):
755 doc = parseString("<?target data?><doc/>")
756 pi = doc.firstChild
757 self.assertEquals(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE)
758 clone = pi.cloneNode(deep)
759 self.confirm(clone.target == pi.target
760 and clone.data == pi.data)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000761
Collin Winterd28fcbc2007-03-28 23:34:06 +0000762 def testClonePIShallow(self):
763 self.check_clone_pi(0, "testClonePIShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000764
Collin Winterd28fcbc2007-03-28 23:34:06 +0000765 def testClonePIDeep(self):
766 self.check_clone_pi(1, "testClonePIDeep")
767
768 def testNormalize(self):
769 doc = parseString("<doc/>")
770 root = doc.documentElement
771 root.appendChild(doc.createTextNode("first"))
772 root.appendChild(doc.createTextNode("second"))
773 self.confirm(len(root.childNodes) == 2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000774 and root.childNodes.length == 2,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000775 "testNormalize -- preparation")
776 doc.normalize()
777 self.confirm(len(root.childNodes) == 1
778 and root.childNodes.length == 1
779 and root.firstChild is root.lastChild
780 and root.firstChild.data == "firstsecond"
781 , "testNormalize -- result")
782 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000783
Collin Winterd28fcbc2007-03-28 23:34:06 +0000784 doc = parseString("<doc/>")
785 root = doc.documentElement
786 root.appendChild(doc.createTextNode(""))
787 doc.normalize()
788 self.confirm(len(root.childNodes) == 0
789 and root.childNodes.length == 0,
790 "testNormalize -- single empty node removed")
791 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000792
R. David Murray0374a822009-04-09 21:54:50 +0000793 def testNormalizeCombineAndNextSibling(self):
794 doc = parseString("<doc/>")
795 root = doc.documentElement
796 root.appendChild(doc.createTextNode("first"))
797 root.appendChild(doc.createTextNode("second"))
798 root.appendChild(doc.createElement("i"))
799 self.confirm(len(root.childNodes) == 3
800 and root.childNodes.length == 3,
801 "testNormalizeCombineAndNextSibling -- preparation")
802 doc.normalize()
803 self.confirm(len(root.childNodes) == 2
804 and root.childNodes.length == 2
805 and root.firstChild.data == "firstsecond"
806 and root.firstChild is not root.lastChild
807 and root.firstChild.nextSibling is root.lastChild
808 and root.firstChild.previousSibling is None
809 and root.lastChild.previousSibling is root.firstChild
810 and root.lastChild.nextSibling is None
811 , "testNormalizeCombinedAndNextSibling -- result")
812 doc.unlink()
813
814 def testNormalizeDeleteWithPrevSibling(self):
815 doc = parseString("<doc/>")
816 root = doc.documentElement
817 root.appendChild(doc.createTextNode("first"))
818 root.appendChild(doc.createTextNode(""))
819 self.confirm(len(root.childNodes) == 2
820 and root.childNodes.length == 2,
821 "testNormalizeDeleteWithPrevSibling -- preparation")
822 doc.normalize()
823 self.confirm(len(root.childNodes) == 1
824 and root.childNodes.length == 1
825 and root.firstChild.data == "first"
826 and root.firstChild is root.lastChild
827 and root.firstChild.nextSibling is None
828 and root.firstChild.previousSibling is None
829 , "testNormalizeDeleteWithPrevSibling -- result")
830 doc.unlink()
831
832 def testNormalizeDeleteWithNextSibling(self):
833 doc = parseString("<doc/>")
834 root = doc.documentElement
835 root.appendChild(doc.createTextNode(""))
836 root.appendChild(doc.createTextNode("second"))
837 self.confirm(len(root.childNodes) == 2
838 and root.childNodes.length == 2,
839 "testNormalizeDeleteWithNextSibling -- preparation")
840 doc.normalize()
841 self.confirm(len(root.childNodes) == 1
842 and root.childNodes.length == 1
843 and root.firstChild.data == "second"
844 and root.firstChild is root.lastChild
845 and root.firstChild.nextSibling is None
846 and root.firstChild.previousSibling is None
847 , "testNormalizeDeleteWithNextSibling -- result")
848 doc.unlink()
849
850 def testNormalizeDeleteWithTwoNonTextSiblings(self):
851 doc = parseString("<doc/>")
852 root = doc.documentElement
853 root.appendChild(doc.createElement("i"))
854 root.appendChild(doc.createTextNode(""))
855 root.appendChild(doc.createElement("i"))
856 self.confirm(len(root.childNodes) == 3
857 and root.childNodes.length == 3,
858 "testNormalizeDeleteWithTwoSiblings -- preparation")
859 doc.normalize()
860 self.confirm(len(root.childNodes) == 2
861 and root.childNodes.length == 2
862 and root.firstChild is not root.lastChild
863 and root.firstChild.nextSibling is root.lastChild
864 and root.firstChild.previousSibling is None
865 and root.lastChild.previousSibling is root.firstChild
866 and root.lastChild.nextSibling is None
867 , "testNormalizeDeleteWithTwoSiblings -- result")
868 doc.unlink()
869
870 def testNormalizeDeleteAndCombine(self):
871 doc = parseString("<doc/>")
872 root = doc.documentElement
873 root.appendChild(doc.createTextNode(""))
874 root.appendChild(doc.createTextNode("second"))
875 root.appendChild(doc.createTextNode(""))
876 root.appendChild(doc.createTextNode("fourth"))
877 root.appendChild(doc.createTextNode(""))
878 self.confirm(len(root.childNodes) == 5
879 and root.childNodes.length == 5,
880 "testNormalizeDeleteAndCombine -- preparation")
881 doc.normalize()
882 self.confirm(len(root.childNodes) == 1
883 and root.childNodes.length == 1
884 and root.firstChild is root.lastChild
885 and root.firstChild.data == "secondfourth"
886 and root.firstChild.previousSibling is None
887 and root.firstChild.nextSibling is None
888 , "testNormalizeDeleteAndCombine -- result")
889 doc.unlink()
890
891 def testNormalizeRecursion(self):
892 doc = parseString("<doc>"
893 "<o>"
894 "<i/>"
895 "t"
896 #
897 #x
898 "</o>"
899 "<o>"
900 "<o>"
901 "t2"
902 #x2
903 "</o>"
904 "t3"
905 #x3
906 "</o>"
907 #
908 "</doc>")
909 root = doc.documentElement
910 root.childNodes[0].appendChild(doc.createTextNode(""))
911 root.childNodes[0].appendChild(doc.createTextNode("x"))
912 root.childNodes[1].childNodes[0].appendChild(doc.createTextNode("x2"))
913 root.childNodes[1].appendChild(doc.createTextNode("x3"))
914 root.appendChild(doc.createTextNode(""))
915 self.confirm(len(root.childNodes) == 3
916 and root.childNodes.length == 3
917 and len(root.childNodes[0].childNodes) == 4
918 and root.childNodes[0].childNodes.length == 4
919 and len(root.childNodes[1].childNodes) == 3
920 and root.childNodes[1].childNodes.length == 3
921 and len(root.childNodes[1].childNodes[0].childNodes) == 2
922 and root.childNodes[1].childNodes[0].childNodes.length == 2
923 , "testNormalize2 -- preparation")
924 doc.normalize()
925 self.confirm(len(root.childNodes) == 2
926 and root.childNodes.length == 2
927 and len(root.childNodes[0].childNodes) == 2
928 and root.childNodes[0].childNodes.length == 2
929 and len(root.childNodes[1].childNodes) == 2
930 and root.childNodes[1].childNodes.length == 2
931 and len(root.childNodes[1].childNodes[0].childNodes) == 1
932 and root.childNodes[1].childNodes[0].childNodes.length == 1
933 , "testNormalize2 -- childNodes lengths")
934 self.confirm(root.childNodes[0].childNodes[1].data == "tx"
935 and root.childNodes[1].childNodes[0].childNodes[0].data == "t2x2"
936 and root.childNodes[1].childNodes[1].data == "t3x3"
937 , "testNormalize2 -- joined text fields")
938 self.confirm(root.childNodes[0].childNodes[1].nextSibling is None
939 and root.childNodes[0].childNodes[1].previousSibling
940 is root.childNodes[0].childNodes[0]
941 and root.childNodes[0].childNodes[0].previousSibling is None
942 and root.childNodes[0].childNodes[0].nextSibling
943 is root.childNodes[0].childNodes[1]
944 and root.childNodes[1].childNodes[1].nextSibling is None
945 and root.childNodes[1].childNodes[1].previousSibling
946 is root.childNodes[1].childNodes[0]
947 and root.childNodes[1].childNodes[0].previousSibling is None
948 and root.childNodes[1].childNodes[0].nextSibling
949 is root.childNodes[1].childNodes[1]
950 , "testNormalize2 -- sibling pointers")
951 doc.unlink()
952
953
Andrew M. Kuchling19aff0c2008-02-23 17:10:46 +0000954 def testBug1433694(self):
955 doc = parseString("<o><i/>t</o>")
956 node = doc.documentElement
957 node.childNodes[1].nodeValue = ""
958 node.normalize()
959 self.confirm(node.childNodes[-1].nextSibling == None,
960 "Final child's .nextSibling should be None")
961
Collin Winterd28fcbc2007-03-28 23:34:06 +0000962 def testSiblings(self):
963 doc = parseString("<doc><?pi?>text?<elm/></doc>")
964 root = doc.documentElement
965 (pi, text, elm) = root.childNodes
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000966
Collin Winterd28fcbc2007-03-28 23:34:06 +0000967 self.confirm(pi.nextSibling is text and
968 pi.previousSibling is None and
969 text.nextSibling is elm and
970 text.previousSibling is pi and
971 elm.nextSibling is None and
972 elm.previousSibling is text, "testSiblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000973
Collin Winterd28fcbc2007-03-28 23:34:06 +0000974 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000975
Collin Winterd28fcbc2007-03-28 23:34:06 +0000976 def testParents(self):
977 doc = parseString(
978 "<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
979 root = doc.documentElement
980 elm1 = root.childNodes[0]
981 (elm2a, elm2b) = elm1.childNodes
982 elm3 = elm2b.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000983
Collin Winterd28fcbc2007-03-28 23:34:06 +0000984 self.confirm(root.parentNode is doc and
985 elm1.parentNode is root and
986 elm2a.parentNode is elm1 and
987 elm2b.parentNode is elm1 and
988 elm3.parentNode is elm2b, "testParents")
989 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000990
Collin Winterd28fcbc2007-03-28 23:34:06 +0000991 def testNodeListItem(self):
992 doc = parseString("<doc><e/><e/></doc>")
993 children = doc.childNodes
994 docelem = children[0]
995 self.confirm(children[0] is children.item(0)
996 and children.item(1) is None
997 and docelem.childNodes.item(0) is docelem.childNodes[0]
998 and docelem.childNodes.item(1) is docelem.childNodes[1]
999 and docelem.childNodes.item(0).childNodes.item(0) is None,
1000 "test NodeList.item()")
1001 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001002
Collin Winterd28fcbc2007-03-28 23:34:06 +00001003 def testSAX2DOM(self):
1004 from xml.dom import pulldom
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001005
Collin Winterd28fcbc2007-03-28 23:34:06 +00001006 sax2dom = pulldom.SAX2DOM()
1007 sax2dom.startDocument()
1008 sax2dom.startElement("doc", {})
1009 sax2dom.characters("text")
1010 sax2dom.startElement("subelm", {})
1011 sax2dom.characters("text")
1012 sax2dom.endElement("subelm")
1013 sax2dom.characters("text")
1014 sax2dom.endElement("doc")
1015 sax2dom.endDocument()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001016
Collin Winterd28fcbc2007-03-28 23:34:06 +00001017 doc = sax2dom.document
1018 root = doc.documentElement
1019 (text1, elm1, text2) = root.childNodes
1020 text3 = elm1.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001021
Collin Winterd28fcbc2007-03-28 23:34:06 +00001022 self.confirm(text1.previousSibling is None and
1023 text1.nextSibling is elm1 and
1024 elm1.previousSibling is text1 and
1025 elm1.nextSibling is text2 and
1026 text2.previousSibling is elm1 and
1027 text2.nextSibling is None and
1028 text3.previousSibling is None and
1029 text3.nextSibling is None, "testSAX2DOM - siblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001030
Collin Winterd28fcbc2007-03-28 23:34:06 +00001031 self.confirm(root.parentNode is doc and
1032 text1.parentNode is root and
1033 elm1.parentNode is root and
1034 text2.parentNode is root and
1035 text3.parentNode is elm1, "testSAX2DOM - parents")
1036 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001037
Collin Winterd28fcbc2007-03-28 23:34:06 +00001038 def testEncodings(self):
1039 doc = parseString('<foo>&#x20ac;</foo>')
1040 self.confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001041 and doc.toxml('utf-8') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +00001042 '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001043 and doc.toxml('iso-8859-15') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +00001044 '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
1045 "testEncodings - encoding EURO SIGN")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001046
1047 # Verify that character decoding errors throw exceptions instead
Collin Winterd28fcbc2007-03-28 23:34:06 +00001048 # of crashing
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001049 self.assertRaises(UnicodeDecodeError, parseString,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001050 '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001051
Collin Winterd28fcbc2007-03-28 23:34:06 +00001052 doc.unlink()
1053
1054 class UserDataHandler:
1055 called = 0
1056 def handle(self, operation, key, data, src, dst):
1057 dst.setUserData(key, data + 1, self)
1058 src.setUserData(key, None, None)
1059 self.called = 1
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001060
Collin Winterd28fcbc2007-03-28 23:34:06 +00001061 def testUserData(self):
1062 dom = Document()
1063 n = dom.createElement('e')
1064 self.confirm(n.getUserData("foo") is None)
1065 n.setUserData("foo", None, None)
1066 self.confirm(n.getUserData("foo") is None)
1067 n.setUserData("foo", 12, 12)
1068 n.setUserData("bar", 13, 13)
1069 self.confirm(n.getUserData("foo") == 12)
1070 self.confirm(n.getUserData("bar") == 13)
1071 n.setUserData("foo", None, None)
1072 self.confirm(n.getUserData("foo") is None)
1073 self.confirm(n.getUserData("bar") == 13)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001074
Collin Winterd28fcbc2007-03-28 23:34:06 +00001075 handler = self.UserDataHandler()
1076 n.setUserData("bar", 12, handler)
1077 c = n.cloneNode(1)
1078 self.confirm(handler.called
1079 and n.getUserData("bar") is None
1080 and c.getUserData("bar") == 13)
1081 n.unlink()
1082 c.unlink()
1083 dom.unlink()
1084
1085 def checkRenameNodeSharedConstraints(self, doc, node):
1086 # Make sure illegal NS usage is detected:
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001087 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001088 "http://xml.python.org/ns", "xmlns:foo")
1089 doc2 = parseString("<doc/>")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001090 self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001091 xml.dom.EMPTY_NAMESPACE, "foo")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001092
Collin Winterd28fcbc2007-03-28 23:34:06 +00001093 def testRenameAttribute(self):
1094 doc = parseString("<doc a='v'/>")
1095 elem = doc.documentElement
1096 attrmap = elem.attributes
1097 attr = elem.attributes['a']
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001098
Collin Winterd28fcbc2007-03-28 23:34:06 +00001099 # Simple renaming
1100 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
1101 self.confirm(attr.name == "b"
1102 and attr.nodeName == "b"
1103 and attr.localName is None
1104 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
1105 and attr.prefix is None
1106 and attr.value == "v"
1107 and elem.getAttributeNode("a") is None
1108 and elem.getAttributeNode("b").isSameNode(attr)
1109 and attrmap["b"].isSameNode(attr)
1110 and attr.ownerDocument.isSameNode(doc)
1111 and attr.ownerElement.isSameNode(elem))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001112
Collin Winterd28fcbc2007-03-28 23:34:06 +00001113 # Rename to have a namespace, no prefix
1114 attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
1115 self.confirm(attr.name == "c"
1116 and attr.nodeName == "c"
1117 and attr.localName == "c"
1118 and attr.namespaceURI == "http://xml.python.org/ns"
1119 and attr.prefix is None
1120 and attr.value == "v"
1121 and elem.getAttributeNode("a") is None
1122 and elem.getAttributeNode("b") is None
1123 and elem.getAttributeNode("c").isSameNode(attr)
1124 and elem.getAttributeNodeNS(
1125 "http://xml.python.org/ns", "c").isSameNode(attr)
1126 and attrmap["c"].isSameNode(attr)
1127 and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001128
Collin Winterd28fcbc2007-03-28 23:34:06 +00001129 # Rename to have a namespace, with prefix
1130 attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
1131 self.confirm(attr.name == "p:d"
1132 and attr.nodeName == "p:d"
1133 and attr.localName == "d"
1134 and attr.namespaceURI == "http://xml.python.org/ns2"
1135 and attr.prefix == "p"
1136 and attr.value == "v"
1137 and elem.getAttributeNode("a") is None
1138 and elem.getAttributeNode("b") is None
1139 and elem.getAttributeNode("c") is None
1140 and elem.getAttributeNodeNS(
1141 "http://xml.python.org/ns", "c") is None
1142 and elem.getAttributeNode("p:d").isSameNode(attr)
1143 and elem.getAttributeNodeNS(
1144 "http://xml.python.org/ns2", "d").isSameNode(attr)
1145 and attrmap["p:d"].isSameNode(attr)
1146 and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001147
Collin Winterd28fcbc2007-03-28 23:34:06 +00001148 # Rename back to a simple non-NS node
1149 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
1150 self.confirm(attr.name == "e"
1151 and attr.nodeName == "e"
1152 and attr.localName is None
1153 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
1154 and attr.prefix is None
1155 and attr.value == "v"
1156 and elem.getAttributeNode("a") is None
1157 and elem.getAttributeNode("b") is None
1158 and elem.getAttributeNode("c") is None
1159 and elem.getAttributeNode("p:d") is None
1160 and elem.getAttributeNodeNS(
1161 "http://xml.python.org/ns", "c") is None
1162 and elem.getAttributeNode("e").isSameNode(attr)
1163 and attrmap["e"].isSameNode(attr))
1164
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001165 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001166 "http://xml.python.org/ns", "xmlns")
1167 self.checkRenameNodeSharedConstraints(doc, attr)
1168 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001169
Collin Winterd28fcbc2007-03-28 23:34:06 +00001170 def testRenameElement(self):
1171 doc = parseString("<doc/>")
1172 elem = doc.documentElement
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001173
Collin Winterd28fcbc2007-03-28 23:34:06 +00001174 # Simple renaming
1175 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
1176 self.confirm(elem.tagName == "a"
1177 and elem.nodeName == "a"
1178 and elem.localName is None
1179 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1180 and elem.prefix is None
1181 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001182
Collin Winterd28fcbc2007-03-28 23:34:06 +00001183 # Rename to have a namespace, no prefix
1184 elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
1185 self.confirm(elem.tagName == "b"
1186 and elem.nodeName == "b"
1187 and elem.localName == "b"
1188 and elem.namespaceURI == "http://xml.python.org/ns"
1189 and elem.prefix is None
1190 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001191
Collin Winterd28fcbc2007-03-28 23:34:06 +00001192 # Rename to have a namespace, with prefix
1193 elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
1194 self.confirm(elem.tagName == "p:c"
1195 and elem.nodeName == "p:c"
1196 and elem.localName == "c"
1197 and elem.namespaceURI == "http://xml.python.org/ns2"
1198 and elem.prefix == "p"
1199 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001200
Collin Winterd28fcbc2007-03-28 23:34:06 +00001201 # Rename back to a simple non-NS node
1202 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
1203 self.confirm(elem.tagName == "d"
1204 and elem.nodeName == "d"
1205 and elem.localName is None
1206 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1207 and elem.prefix is None
1208 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001209
Collin Winterd28fcbc2007-03-28 23:34:06 +00001210 self.checkRenameNodeSharedConstraints(doc, elem)
1211 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001212
Collin Winterd28fcbc2007-03-28 23:34:06 +00001213 def testRenameOther(self):
1214 # We have to create a comment node explicitly since not all DOM
1215 # builders used with minidom add comments to the DOM.
1216 doc = xml.dom.minidom.getDOMImplementation().createDocument(
1217 xml.dom.EMPTY_NAMESPACE, "e", None)
1218 node = doc.createComment("comment")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001219 self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001220 xml.dom.EMPTY_NAMESPACE, "foo")
1221 doc.unlink()
1222
1223 def testWholeText(self):
1224 doc = parseString("<doc>a</doc>")
1225 elem = doc.documentElement
1226 text = elem.childNodes[0]
1227 self.assertEquals(text.nodeType, Node.TEXT_NODE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001228
Collin Winterd28fcbc2007-03-28 23:34:06 +00001229 self.checkWholeText(text, "a")
1230 elem.appendChild(doc.createTextNode("b"))
1231 self.checkWholeText(text, "ab")
1232 elem.insertBefore(doc.createCDATASection("c"), text)
1233 self.checkWholeText(text, "cab")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001234
Collin Winterd28fcbc2007-03-28 23:34:06 +00001235 # make sure we don't cross other nodes
1236 splitter = doc.createComment("comment")
1237 elem.appendChild(splitter)
1238 text2 = doc.createTextNode("d")
1239 elem.appendChild(text2)
1240 self.checkWholeText(text, "cab")
1241 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001242
Collin Winterd28fcbc2007-03-28 23:34:06 +00001243 x = doc.createElement("x")
1244 elem.replaceChild(x, splitter)
1245 splitter = x
1246 self.checkWholeText(text, "cab")
1247 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001248
Collin Winterd28fcbc2007-03-28 23:34:06 +00001249 x = doc.createProcessingInstruction("y", "z")
1250 elem.replaceChild(x, splitter)
1251 splitter = x
1252 self.checkWholeText(text, "cab")
1253 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001254
Collin Winterd28fcbc2007-03-28 23:34:06 +00001255 elem.removeChild(splitter)
1256 self.checkWholeText(text, "cabd")
1257 self.checkWholeText(text2, "cabd")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001258
Collin Winterd28fcbc2007-03-28 23:34:06 +00001259 def testPatch1094164(self):
1260 doc = parseString("<doc><e/></doc>")
1261 elem = doc.documentElement
1262 e = elem.firstChild
1263 self.confirm(e.parentNode is elem, "Before replaceChild()")
1264 # Check that replacing a child with itself leaves the tree unchanged
1265 elem.replaceChild(e, e)
1266 self.confirm(e.parentNode is elem, "After replaceChild()")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001267
Collin Winterd28fcbc2007-03-28 23:34:06 +00001268 def testReplaceWholeText(self):
1269 def setup():
1270 doc = parseString("<doc>a<e/>d</doc>")
1271 elem = doc.documentElement
1272 text1 = elem.firstChild
1273 text2 = elem.lastChild
1274 splitter = text1.nextSibling
1275 elem.insertBefore(doc.createTextNode("b"), splitter)
1276 elem.insertBefore(doc.createCDATASection("c"), text1)
1277 return doc, elem, text1, splitter, text2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001278
Collin Winterd28fcbc2007-03-28 23:34:06 +00001279 doc, elem, text1, splitter, text2 = setup()
1280 text = text1.replaceWholeText("new content")
1281 self.checkWholeText(text, "new content")
1282 self.checkWholeText(text2, "d")
1283 self.confirm(len(elem.childNodes) == 3)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001284
Collin Winterd28fcbc2007-03-28 23:34:06 +00001285 doc, elem, text1, splitter, text2 = setup()
1286 text = text2.replaceWholeText("new content")
1287 self.checkWholeText(text, "new content")
1288 self.checkWholeText(text1, "cab")
1289 self.confirm(len(elem.childNodes) == 5)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001290
Collin Winterd28fcbc2007-03-28 23:34:06 +00001291 doc, elem, text1, splitter, text2 = setup()
1292 text = text1.replaceWholeText("")
1293 self.checkWholeText(text2, "d")
1294 self.confirm(text is None
1295 and len(elem.childNodes) == 2)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001296
Collin Winterd28fcbc2007-03-28 23:34:06 +00001297 def testSchemaType(self):
1298 doc = parseString(
1299 "<!DOCTYPE doc [\n"
1300 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
1301 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
1302 " <!ATTLIST doc id ID #IMPLIED \n"
1303 " ref IDREF #IMPLIED \n"
1304 " refs IDREFS #IMPLIED \n"
1305 " enum (a|b) #IMPLIED \n"
1306 " ent ENTITY #IMPLIED \n"
1307 " ents ENTITIES #IMPLIED \n"
1308 " nm NMTOKEN #IMPLIED \n"
1309 " nms NMTOKENS #IMPLIED \n"
1310 " text CDATA #IMPLIED \n"
1311 " >\n"
1312 "]><doc id='name' notid='name' text='splat!' enum='b'"
1313 " ref='name' refs='name name' ent='e1' ents='e1 e2'"
1314 " nm='123' nms='123 abc' />")
1315 elem = doc.documentElement
1316 # We don't want to rely on any specific loader at this point, so
1317 # just make sure we can get to all the names, and that the
1318 # DTD-based namespace is right. The names can vary by loader
1319 # since each supports a different level of DTD information.
1320 t = elem.schemaType
1321 self.confirm(t.name is None
1322 and t.namespace == xml.dom.EMPTY_NAMESPACE)
1323 names = "id notid text enum ref refs ent ents nm nms".split()
1324 for name in names:
1325 a = elem.getAttributeNode(name)
1326 t = a.schemaType
1327 self.confirm(hasattr(t, "name")
1328 and t.namespace == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001329
Collin Winterd28fcbc2007-03-28 23:34:06 +00001330 def testSetIdAttribute(self):
1331 doc = parseString("<doc a1='v' a2='w'/>")
1332 e = doc.documentElement
1333 a1 = e.getAttributeNode("a1")
1334 a2 = e.getAttributeNode("a2")
1335 self.confirm(doc.getElementById("v") is None
1336 and not a1.isId
1337 and not a2.isId)
1338 e.setIdAttribute("a1")
1339 self.confirm(e.isSameNode(doc.getElementById("v"))
1340 and a1.isId
1341 and not a2.isId)
1342 e.setIdAttribute("a2")
1343 self.confirm(e.isSameNode(doc.getElementById("v"))
1344 and e.isSameNode(doc.getElementById("w"))
1345 and a1.isId
1346 and a2.isId)
1347 # replace the a1 node; the new node should *not* be an ID
1348 a3 = doc.createAttribute("a1")
1349 a3.value = "v"
1350 e.setAttributeNode(a3)
1351 self.confirm(doc.getElementById("v") is None
1352 and e.isSameNode(doc.getElementById("w"))
1353 and not a1.isId
1354 and a2.isId
1355 and not a3.isId)
1356 # renaming an attribute should not affect its ID-ness:
1357 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1358 self.confirm(e.isSameNode(doc.getElementById("w"))
1359 and a2.isId)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001360
Collin Winterd28fcbc2007-03-28 23:34:06 +00001361 def testSetIdAttributeNS(self):
1362 NS1 = "http://xml.python.org/ns1"
1363 NS2 = "http://xml.python.org/ns2"
1364 doc = parseString("<doc"
1365 " xmlns:ns1='" + NS1 + "'"
1366 " xmlns:ns2='" + NS2 + "'"
1367 " ns1:a1='v' ns2:a2='w'/>")
1368 e = doc.documentElement
1369 a1 = e.getAttributeNodeNS(NS1, "a1")
1370 a2 = e.getAttributeNodeNS(NS2, "a2")
1371 self.confirm(doc.getElementById("v") is None
1372 and not a1.isId
1373 and not a2.isId)
1374 e.setIdAttributeNS(NS1, "a1")
1375 self.confirm(e.isSameNode(doc.getElementById("v"))
1376 and a1.isId
1377 and not a2.isId)
1378 e.setIdAttributeNS(NS2, "a2")
1379 self.confirm(e.isSameNode(doc.getElementById("v"))
1380 and e.isSameNode(doc.getElementById("w"))
1381 and a1.isId
1382 and a2.isId)
1383 # replace the a1 node; the new node should *not* be an ID
1384 a3 = doc.createAttributeNS(NS1, "a1")
1385 a3.value = "v"
1386 e.setAttributeNode(a3)
1387 self.confirm(e.isSameNode(doc.getElementById("w")))
1388 self.confirm(not a1.isId)
1389 self.confirm(a2.isId)
1390 self.confirm(not a3.isId)
1391 self.confirm(doc.getElementById("v") is None)
1392 # renaming an attribute should not affect its ID-ness:
1393 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1394 self.confirm(e.isSameNode(doc.getElementById("w"))
1395 and a2.isId)
1396
1397 def testSetIdAttributeNode(self):
1398 NS1 = "http://xml.python.org/ns1"
1399 NS2 = "http://xml.python.org/ns2"
1400 doc = parseString("<doc"
1401 " xmlns:ns1='" + NS1 + "'"
1402 " xmlns:ns2='" + NS2 + "'"
1403 " ns1:a1='v' ns2:a2='w'/>")
1404 e = doc.documentElement
1405 a1 = e.getAttributeNodeNS(NS1, "a1")
1406 a2 = e.getAttributeNodeNS(NS2, "a2")
1407 self.confirm(doc.getElementById("v") is None
1408 and not a1.isId
1409 and not a2.isId)
1410 e.setIdAttributeNode(a1)
1411 self.confirm(e.isSameNode(doc.getElementById("v"))
1412 and a1.isId
1413 and not a2.isId)
1414 e.setIdAttributeNode(a2)
1415 self.confirm(e.isSameNode(doc.getElementById("v"))
1416 and e.isSameNode(doc.getElementById("w"))
1417 and a1.isId
1418 and a2.isId)
1419 # replace the a1 node; the new node should *not* be an ID
1420 a3 = doc.createAttributeNS(NS1, "a1")
1421 a3.value = "v"
1422 e.setAttributeNode(a3)
1423 self.confirm(e.isSameNode(doc.getElementById("w")))
1424 self.confirm(not a1.isId)
1425 self.confirm(a2.isId)
1426 self.confirm(not a3.isId)
1427 self.confirm(doc.getElementById("v") is None)
1428 # renaming an attribute should not affect its ID-ness:
1429 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1430 self.confirm(e.isSameNode(doc.getElementById("w"))
1431 and a2.isId)
1432
1433 def testPickledDocument(self):
1434 doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
1435 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
1436 " 'http://xml.python.org/system' [\n"
1437 " <!ELEMENT e EMPTY>\n"
1438 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
1439 "]><doc attr='value'> text\n"
1440 "<?pi sample?> <!-- comment --> <e/> </doc>")
1441 s = pickle.dumps(doc)
1442 doc2 = pickle.loads(s)
1443 stack = [(doc, doc2)]
1444 while stack:
1445 n1, n2 = stack.pop()
1446 self.confirm(n1.nodeType == n2.nodeType
1447 and len(n1.childNodes) == len(n2.childNodes)
1448 and n1.nodeName == n2.nodeName
1449 and not n1.isSameNode(n2)
1450 and not n2.isSameNode(n1))
1451 if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
1452 len(n1.entities)
1453 len(n2.entities)
1454 len(n1.notations)
1455 len(n2.notations)
1456 self.confirm(len(n1.entities) == len(n2.entities)
1457 and len(n1.notations) == len(n2.notations))
1458 for i in range(len(n1.notations)):
Georg Brandlcd4a21b2010-02-06 23:34:10 +00001459 # XXX this loop body doesn't seem to be executed?
Collin Winterd28fcbc2007-03-28 23:34:06 +00001460 no1 = n1.notations.item(i)
1461 no2 = n1.notations.item(i)
1462 self.confirm(no1.name == no2.name
1463 and no1.publicId == no2.publicId
1464 and no1.systemId == no2.systemId)
Georg Brandlcd4a21b2010-02-06 23:34:10 +00001465 stack.append((no1, no2))
Collin Winterd28fcbc2007-03-28 23:34:06 +00001466 for i in range(len(n1.entities)):
1467 e1 = n1.entities.item(i)
1468 e2 = n2.entities.item(i)
1469 self.confirm(e1.notationName == e2.notationName
1470 and e1.publicId == e2.publicId
1471 and e1.systemId == e2.systemId)
1472 stack.append((e1, e2))
1473 if n1.nodeType != Node.DOCUMENT_NODE:
1474 self.confirm(n1.ownerDocument.isSameNode(doc)
1475 and n2.ownerDocument.isSameNode(doc2))
1476 for i in range(len(n1.childNodes)):
1477 stack.append((n1.childNodes[i], n2.childNodes[i]))
1478
Martin v. Löwis27e4a172008-05-23 15:18:28 +00001479 def testSerializeCommentNodeWithDoubleHyphen(self):
1480 doc = create_doc_without_doctype()
1481 doc.appendChild(doc.createComment("foo--bar"))
1482 self.assertRaises(ValueError, doc.toxml)
1483
Collin Winterd28fcbc2007-03-28 23:34:06 +00001484def test_main():
1485 run_unittest(MinidomTest)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001486
Collin Winterd28fcbc2007-03-28 23:34:06 +00001487if __name__ == "__main__":
1488 test_main()