blob: 1f0b229fb26bb054ffd46545c22d96cb07ef1cb5 [file] [log] [blame]
Fred Drakefbdeaad2006-07-29 16:56:15 +00001# test for xml.dom.minidom
Paul Prescod7993bcc2000-07-01 14:54:16 +00002
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +00003import pickle
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +00004from StringIO import StringIO
Florent Xicluna1b51c3d2010-03-13 12:41:48 +00005from test.test_support import verbose, run_unittest, findfile
Collin Winterd28fcbc2007-03-28 23:34:06 +00006import unittest
Fred Drake17647f52000-07-03 16:37:42 +00007
Fred Drakefbdeaad2006-07-29 16:56:15 +00008import xml.dom
9import xml.dom.minidom
10import xml.parsers.expat
Fred Drakec441f7b2002-07-19 22:16:41 +000011
Fred Drakefbdeaad2006-07-29 16:56:15 +000012from xml.dom.minidom import parse, Node, Document, parseString
13from xml.dom.minidom import getDOMImplementation
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +000014
Fred Drakec441f7b2002-07-19 22:16:41 +000015
Florent Xicluna1b51c3d2010-03-13 12:41:48 +000016tstfile = findfile("test.xml", subdir="xmltestdata")
17
Paul Prescod7993bcc2000-07-01 14:54:16 +000018
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000019# The tests of DocumentType importing use these helpers to construct
20# the documents to work with, since not all DOM builders actually
21# create the DocumentType nodes.
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000022def create_doc_without_doctype(doctype=None):
23 return getDOMImplementation().createDocument(None, "doc", doctype)
24
25def create_nonempty_doctype():
26 doctype = getDOMImplementation().createDocumentType("doc", None, None)
27 doctype.entities._seq = []
28 doctype.notations._seq = []
Fred Drakefbdeaad2006-07-29 16:56:15 +000029 notation = xml.dom.minidom.Notation("my-notation", None,
30 "http://xml.python.org/notations/my")
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000031 doctype.notations._seq.append(notation)
Fred Drakefbdeaad2006-07-29 16:56:15 +000032 entity = xml.dom.minidom.Entity("my-entity", None,
33 "http://xml.python.org/entities/my",
34 "my-notation")
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000035 entity.version = "1.0"
36 entity.encoding = "utf-8"
37 entity.actualEncoding = "us-ascii"
38 doctype.entities._seq.append(entity)
39 return doctype
40
41def create_doc_with_doctype():
42 doctype = create_nonempty_doctype()
43 doc = create_doc_without_doctype(doctype)
44 doctype.entities.item(0).ownerDocument = doc
45 doctype.notations.item(0).ownerDocument = doc
46 return doc
47
Collin Winterd28fcbc2007-03-28 23:34:06 +000048class MinidomTest(unittest.TestCase):
49 def tearDown(self):
Paul Prescod7993bcc2000-07-01 14:54:16 +000050 try:
Collin Winterd28fcbc2007-03-28 23:34:06 +000051 Node.allnodes
52 except AttributeError:
53 # We don't actually have the minidom from the standard library,
54 # but are picking up the PyXML version from site-packages.
55 pass
56 else:
57 self.confirm(len(Node.allnodes) == 0,
58 "assertion: len(Node.allnodes) == 0")
59 if len(Node.allnodes):
60 print "Garbage left over:"
61 if verbose:
62 print Node.allnodes.items()[0:10]
63 else:
64 # Don't print specific nodes if repeatable results
65 # are needed
66 print len(Node.allnodes)
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000067 Node.allnodes = {}
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000068
Collin Winterd28fcbc2007-03-28 23:34:06 +000069 def confirm(self, test, testname = "Test"):
70 self.assertTrue(test, testname)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000071
Collin Winterd28fcbc2007-03-28 23:34:06 +000072 def checkWholeText(self, node, s):
73 t = node.wholeText
74 self.confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000075
Collin Winterd28fcbc2007-03-28 23:34:06 +000076 def testParseFromFile(self):
77 dom = parse(StringIO(open(tstfile).read()))
78 dom.unlink()
79 self.confirm(isinstance(dom,Document))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000080
Collin Winterd28fcbc2007-03-28 23:34:06 +000081 def testGetElementsByTagName(self):
82 dom = parse(tstfile)
83 self.confirm(dom.getElementsByTagName("LI") == \
84 dom.documentElement.getElementsByTagName("LI"))
85 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000086
Collin Winterd28fcbc2007-03-28 23:34:06 +000087 def testInsertBefore(self):
88 dom = parseString("<doc><foo/></doc>")
89 root = dom.documentElement
90 elem = root.childNodes[0]
91 nelem = dom.createElement("element")
92 root.insertBefore(nelem, elem)
93 self.confirm(len(root.childNodes) == 2
94 and root.childNodes.length == 2
95 and root.childNodes[0] is nelem
96 and root.childNodes.item(0) is nelem
97 and root.childNodes[1] is elem
98 and root.childNodes.item(1) is elem
99 and root.firstChild is nelem
100 and root.lastChild is elem
101 and root.toxml() == "<doc><element/><foo/></doc>"
102 , "testInsertBefore -- node properly placed in tree")
103 nelem = dom.createElement("element")
104 root.insertBefore(nelem, None)
105 self.confirm(len(root.childNodes) == 3
106 and root.childNodes.length == 3
107 and root.childNodes[1] is elem
108 and root.childNodes.item(1) is elem
109 and root.childNodes[2] is nelem
110 and root.childNodes.item(2) is nelem
111 and root.lastChild is nelem
112 and nelem.previousSibling is elem
113 and root.toxml() == "<doc><element/><foo/><element/></doc>"
114 , "testInsertBefore -- node properly placed in tree")
115 nelem2 = dom.createElement("bar")
116 root.insertBefore(nelem2, nelem)
117 self.confirm(len(root.childNodes) == 4
118 and root.childNodes.length == 4
119 and root.childNodes[2] is nelem2
120 and root.childNodes.item(2) is nelem2
121 and root.childNodes[3] is nelem
122 and root.childNodes.item(3) is nelem
123 and nelem2.nextSibling is nelem
124 and nelem.previousSibling is nelem2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000125 and root.toxml() ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000126 "<doc><element/><foo/><bar/><element/></doc>"
127 , "testInsertBefore -- node properly placed in tree")
128 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000129
Collin Winterd28fcbc2007-03-28 23:34:06 +0000130 def _create_fragment_test_nodes(self):
131 dom = parseString("<doc/>")
132 orig = dom.createTextNode("original")
133 c1 = dom.createTextNode("foo")
134 c2 = dom.createTextNode("bar")
135 c3 = dom.createTextNode("bat")
136 dom.documentElement.appendChild(orig)
137 frag = dom.createDocumentFragment()
138 frag.appendChild(c1)
139 frag.appendChild(c2)
140 frag.appendChild(c3)
141 return dom, orig, c1, c2, c3, frag
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000142
Collin Winterd28fcbc2007-03-28 23:34:06 +0000143 def testInsertBeforeFragment(self):
144 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
145 dom.documentElement.insertBefore(frag, None)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000146 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000147 (orig, c1, c2, c3),
148 "insertBefore(<fragment>, None)")
149 frag.unlink()
150 dom.unlink()
Paul Prescod10d27662000-09-18 19:07:26 +0000151
Collin Winterd28fcbc2007-03-28 23:34:06 +0000152 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
153 dom.documentElement.insertBefore(frag, orig)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000154 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000155 (c1, c2, c3, orig),
156 "insertBefore(<fragment>, orig)")
157 frag.unlink()
158 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000159
Collin Winterd28fcbc2007-03-28 23:34:06 +0000160 def testAppendChild(self):
161 dom = parse(tstfile)
162 dom.documentElement.appendChild(dom.createComment(u"Hello"))
163 self.confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
164 self.confirm(dom.documentElement.childNodes[-1].data == "Hello")
165 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000166
Collin Winterd28fcbc2007-03-28 23:34:06 +0000167 def testAppendChildFragment(self):
168 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
169 dom.documentElement.appendChild(frag)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000170 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000171 (orig, c1, c2, c3),
172 "appendChild(<fragment>)")
173 frag.unlink()
174 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000175
Collin Winterd28fcbc2007-03-28 23:34:06 +0000176 def testReplaceChildFragment(self):
177 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
178 dom.documentElement.replaceChild(frag, orig)
179 orig.unlink()
180 self.confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
181 "replaceChild(<fragment>)")
182 frag.unlink()
183 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000184
Collin Winterd28fcbc2007-03-28 23:34:06 +0000185 def testLegalChildren(self):
186 dom = Document()
187 elem = dom.createElement('element')
188 text = dom.createTextNode('text')
189 self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000190
Collin Winterd28fcbc2007-03-28 23:34:06 +0000191 dom.appendChild(elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000192 self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000193 elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000194 self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000195 elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000196
Collin Winterd28fcbc2007-03-28 23:34:06 +0000197 nodemap = elem.attributes
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000198 self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000199 text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000200 self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000201 text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000202
Collin Winterd28fcbc2007-03-28 23:34:06 +0000203 elem.appendChild(text)
204 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000205
Collin Winterd28fcbc2007-03-28 23:34:06 +0000206 def testNamedNodeMapSetItem(self):
207 dom = Document()
208 elem = dom.createElement('element')
209 attrs = elem.attributes
210 attrs["foo"] = "bar"
211 a = attrs.item(0)
212 self.confirm(a.ownerDocument is dom,
213 "NamedNodeMap.__setitem__() sets ownerDocument")
214 self.confirm(a.ownerElement is elem,
215 "NamedNodeMap.__setitem__() sets ownerElement")
216 self.confirm(a.value == "bar",
217 "NamedNodeMap.__setitem__() sets value")
218 self.confirm(a.nodeValue == "bar",
219 "NamedNodeMap.__setitem__() sets nodeValue")
220 elem.unlink()
221 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000222
Collin Winterd28fcbc2007-03-28 23:34:06 +0000223 def testNonZero(self):
224 dom = parse(tstfile)
225 self.confirm(dom)# should not be zero
226 dom.appendChild(dom.createComment("foo"))
227 self.confirm(not dom.childNodes[-1].childNodes)
228 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000229
Collin Winterd28fcbc2007-03-28 23:34:06 +0000230 def testUnlink(self):
231 dom = parse(tstfile)
232 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000233
Collin Winterd28fcbc2007-03-28 23:34:06 +0000234 def testElement(self):
235 dom = Document()
236 dom.appendChild(dom.createElement("abc"))
237 self.confirm(dom.documentElement)
238 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000239
Collin Winterd28fcbc2007-03-28 23:34:06 +0000240 def testAAA(self):
241 dom = parseString("<abc/>")
242 el = dom.documentElement
243 el.setAttribute("spam", "jam2")
244 self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
245 a = el.getAttributeNode("spam")
246 self.confirm(a.ownerDocument is dom,
247 "setAttribute() sets ownerDocument")
248 self.confirm(a.ownerElement is dom.documentElement,
249 "setAttribute() sets ownerElement")
250 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000251
Collin Winterd28fcbc2007-03-28 23:34:06 +0000252 def testAAB(self):
253 dom = parseString("<abc/>")
254 el = dom.documentElement
255 el.setAttribute("spam", "jam")
256 el.setAttribute("spam", "jam2")
257 self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
258 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000259
Collin Winterd28fcbc2007-03-28 23:34:06 +0000260 def testAddAttr(self):
261 dom = Document()
262 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000263
Collin Winterd28fcbc2007-03-28 23:34:06 +0000264 child.setAttribute("def", "ghi")
265 self.confirm(child.getAttribute("def") == "ghi")
266 self.confirm(child.attributes["def"].value == "ghi")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000267
Collin Winterd28fcbc2007-03-28 23:34:06 +0000268 child.setAttribute("jkl", "mno")
269 self.confirm(child.getAttribute("jkl") == "mno")
270 self.confirm(child.attributes["jkl"].value == "mno")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000271
Collin Winterd28fcbc2007-03-28 23:34:06 +0000272 self.confirm(len(child.attributes) == 2)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000273
Collin Winterd28fcbc2007-03-28 23:34:06 +0000274 child.setAttribute("def", "newval")
275 self.confirm(child.getAttribute("def") == "newval")
276 self.confirm(child.attributes["def"].value == "newval")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000277
Collin Winterd28fcbc2007-03-28 23:34:06 +0000278 self.confirm(len(child.attributes) == 2)
279 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000280
Collin Winterd28fcbc2007-03-28 23:34:06 +0000281 def testDeleteAttr(self):
282 dom = Document()
283 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000284
Collin Winterd28fcbc2007-03-28 23:34:06 +0000285 self.confirm(len(child.attributes) == 0)
286 child.setAttribute("def", "ghi")
287 self.confirm(len(child.attributes) == 1)
288 del child.attributes["def"]
289 self.confirm(len(child.attributes) == 0)
290 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000291
Collin Winterd28fcbc2007-03-28 23:34:06 +0000292 def testRemoveAttr(self):
293 dom = Document()
294 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000295
Collin Winterd28fcbc2007-03-28 23:34:06 +0000296 child.setAttribute("def", "ghi")
297 self.confirm(len(child.attributes) == 1)
298 child.removeAttribute("def")
299 self.confirm(len(child.attributes) == 0)
300 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000301
Collin Winterd28fcbc2007-03-28 23:34:06 +0000302 def testRemoveAttrNS(self):
303 dom = Document()
304 child = dom.appendChild(
305 dom.createElementNS("http://www.python.org", "python:abc"))
306 child.setAttributeNS("http://www.w3.org", "xmlns:python",
307 "http://www.python.org")
308 child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
309 self.confirm(len(child.attributes) == 2)
310 child.removeAttributeNS("http://www.python.org", "abcattr")
311 self.confirm(len(child.attributes) == 1)
312 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000313
Collin Winterd28fcbc2007-03-28 23:34:06 +0000314 def testRemoveAttributeNode(self):
315 dom = Document()
316 child = dom.appendChild(dom.createElement("foo"))
317 child.setAttribute("spam", "jam")
318 self.confirm(len(child.attributes) == 1)
319 node = child.getAttributeNode("spam")
320 child.removeAttributeNode(node)
321 self.confirm(len(child.attributes) == 0
322 and child.getAttributeNode("spam") is None)
323 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000324
Collin Winterd28fcbc2007-03-28 23:34:06 +0000325 def testChangeAttr(self):
326 dom = parseString("<abc/>")
327 el = dom.documentElement
328 el.setAttribute("spam", "jam")
329 self.confirm(len(el.attributes) == 1)
330 el.setAttribute("spam", "bam")
331 # Set this attribute to be an ID and make sure that doesn't change
332 # when changing the value:
333 el.setIdAttribute("spam")
334 self.confirm(len(el.attributes) == 1
335 and el.attributes["spam"].value == "bam"
336 and el.attributes["spam"].nodeValue == "bam"
337 and el.getAttribute("spam") == "bam"
338 and el.getAttributeNode("spam").isId)
339 el.attributes["spam"] = "ham"
340 self.confirm(len(el.attributes) == 1
341 and el.attributes["spam"].value == "ham"
342 and el.attributes["spam"].nodeValue == "ham"
343 and el.getAttribute("spam") == "ham"
344 and el.attributes["spam"].isId)
345 el.setAttribute("spam2", "bam")
346 self.confirm(len(el.attributes) == 2
347 and el.attributes["spam"].value == "ham"
348 and el.attributes["spam"].nodeValue == "ham"
349 and el.getAttribute("spam") == "ham"
350 and el.attributes["spam2"].value == "bam"
351 and el.attributes["spam2"].nodeValue == "bam"
352 and el.getAttribute("spam2") == "bam")
353 el.attributes["spam2"] = "bam2"
354 self.confirm(len(el.attributes) == 2
355 and el.attributes["spam"].value == "ham"
356 and el.attributes["spam"].nodeValue == "ham"
357 and el.getAttribute("spam") == "ham"
358 and el.attributes["spam2"].value == "bam2"
359 and el.attributes["spam2"].nodeValue == "bam2"
360 and el.getAttribute("spam2") == "bam2")
361 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000362
Collin Winterd28fcbc2007-03-28 23:34:06 +0000363 def testGetAttrList(self):
364 pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000365
Collin Winterd28fcbc2007-03-28 23:34:06 +0000366 def testGetAttrValues(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000367
Collin Winterd28fcbc2007-03-28 23:34:06 +0000368 def testGetAttrLength(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000369
Collin Winterd28fcbc2007-03-28 23:34:06 +0000370 def testGetAttribute(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000371
Collin Winterd28fcbc2007-03-28 23:34:06 +0000372 def testGetAttributeNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000373
Collin Winterd28fcbc2007-03-28 23:34:06 +0000374 def testGetAttributeNode(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000375
Collin Winterd28fcbc2007-03-28 23:34:06 +0000376 def testGetElementsByTagNameNS(self):
377 d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
378 <minidom:myelem/>
379 </foo>"""
380 dom = parseString(d)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000381 elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom",
Collin Winterd28fcbc2007-03-28 23:34:06 +0000382 "myelem")
383 self.confirm(len(elems) == 1
384 and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"
385 and elems[0].localName == "myelem"
386 and elems[0].prefix == "minidom"
387 and elems[0].tagName == "minidom:myelem"
388 and elems[0].nodeName == "minidom:myelem")
389 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000390
391 def get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000392 lname):
393 nodelist = doc.getElementsByTagNameNS(nsuri, lname)
394 self.confirm(len(nodelist) == 0)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000395
Collin Winterd28fcbc2007-03-28 23:34:06 +0000396 def testGetEmptyNodeListFromElementsByTagNameNS(self):
397 doc = parseString('<doc/>')
398 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
399 doc, 'http://xml.python.org/namespaces/a', 'localname')
400 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
401 doc, '*', 'splat')
402 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
403 doc, 'http://xml.python.org/namespaces/a', '*')
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000404
Collin Winterd28fcbc2007-03-28 23:34:06 +0000405 doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
406 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
407 doc, "http://xml.python.org/splat", "not-there")
408 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
409 doc, "*", "not-there")
410 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
411 doc, "http://somewhere.else.net/not-there", "e")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000412
Collin Winterd28fcbc2007-03-28 23:34:06 +0000413 def testElementReprAndStr(self):
414 dom = Document()
415 el = dom.appendChild(dom.createElement("abc"))
416 string1 = repr(el)
417 string2 = str(el)
418 self.confirm(string1 == string2)
419 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000420
Collin Winterd28fcbc2007-03-28 23:34:06 +0000421 def testElementReprAndStrUnicode(self):
422 dom = Document()
423 el = dom.appendChild(dom.createElement(u"abc"))
424 string1 = repr(el)
425 string2 = str(el)
426 self.confirm(string1 == string2)
427 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000428
Collin Winterd28fcbc2007-03-28 23:34:06 +0000429 def testElementReprAndStrUnicodeNS(self):
430 dom = Document()
431 el = dom.appendChild(
432 dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
433 string1 = repr(el)
434 string2 = str(el)
435 self.confirm(string1 == string2)
Ezio Melotti187f93d2010-03-17 14:22:34 +0000436 self.confirm("slash:abc" in string1)
Collin Winterd28fcbc2007-03-28 23:34:06 +0000437 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000438
Collin Winterd28fcbc2007-03-28 23:34:06 +0000439 def testAttributeRepr(self):
440 dom = Document()
441 el = dom.appendChild(dom.createElement(u"abc"))
442 node = el.setAttribute("abc", "def")
443 self.confirm(str(node) == repr(node))
444 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000445
Collin Winterd28fcbc2007-03-28 23:34:06 +0000446 def testTextNodeRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000447
Collin Winterd28fcbc2007-03-28 23:34:06 +0000448 def testWriteXML(self):
449 str = '<?xml version="1.0" ?><a b="c"/>'
450 dom = parseString(str)
451 domstr = dom.toxml()
452 dom.unlink()
453 self.confirm(str == domstr)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000454
Collin Winterd28fcbc2007-03-28 23:34:06 +0000455 def testAltNewline(self):
456 str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
457 dom = parseString(str)
458 domstr = dom.toprettyxml(newl="\r\n")
459 dom.unlink()
460 self.confirm(domstr == str.replace("\n", "\r\n"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000461
Collin Winterd28fcbc2007-03-28 23:34:06 +0000462 def testProcessingInstruction(self):
463 dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
464 pi = dom.documentElement.firstChild
465 self.confirm(pi.target == "mypi"
466 and pi.data == "data \t\n "
467 and pi.nodeName == "mypi"
468 and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
469 and pi.attributes is None
470 and not pi.hasChildNodes()
471 and len(pi.childNodes) == 0
472 and pi.firstChild is None
473 and pi.lastChild is None
474 and pi.localName is None
475 and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000476
Collin Winterd28fcbc2007-03-28 23:34:06 +0000477 def testProcessingInstructionRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000478
Collin Winterd28fcbc2007-03-28 23:34:06 +0000479 def testTextRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000480
Collin Winterd28fcbc2007-03-28 23:34:06 +0000481 def testWriteText(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000482
Collin Winterd28fcbc2007-03-28 23:34:06 +0000483 def testDocumentElement(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000484
Collin Winterd28fcbc2007-03-28 23:34:06 +0000485 def testTooManyDocumentElements(self):
486 doc = parseString("<doc/>")
487 elem = doc.createElement("extra")
488 # Should raise an exception when adding an extra document element.
489 self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem)
490 elem.unlink()
491 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000492
Collin Winterd28fcbc2007-03-28 23:34:06 +0000493 def testCreateElementNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000494
Collin Winterd28fcbc2007-03-28 23:34:06 +0000495 def testCreateAttributeNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000496
Collin Winterd28fcbc2007-03-28 23:34:06 +0000497 def testParse(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000498
Collin Winterd28fcbc2007-03-28 23:34:06 +0000499 def testParseString(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000500
Collin Winterd28fcbc2007-03-28 23:34:06 +0000501 def testComment(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000502
Collin Winterd28fcbc2007-03-28 23:34:06 +0000503 def testAttrListItem(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000504
Collin Winterd28fcbc2007-03-28 23:34:06 +0000505 def testAttrListItems(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000506
Collin Winterd28fcbc2007-03-28 23:34:06 +0000507 def testAttrListItemNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000508
Collin Winterd28fcbc2007-03-28 23:34:06 +0000509 def testAttrListKeys(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000510
Collin Winterd28fcbc2007-03-28 23:34:06 +0000511 def testAttrListKeysNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000512
Collin Winterd28fcbc2007-03-28 23:34:06 +0000513 def testRemoveNamedItem(self):
514 doc = parseString("<doc a=''/>")
515 e = doc.documentElement
516 attrs = e.attributes
517 a1 = e.getAttributeNode("a")
518 a2 = attrs.removeNamedItem("a")
519 self.confirm(a1.isSameNode(a2))
520 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000521
Collin Winterd28fcbc2007-03-28 23:34:06 +0000522 def testRemoveNamedItemNS(self):
523 doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
524 e = doc.documentElement
525 attrs = e.attributes
526 a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
527 a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
528 self.confirm(a1.isSameNode(a2))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000529 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000530 "http://xml.python.org/", "b")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000531
Collin Winterd28fcbc2007-03-28 23:34:06 +0000532 def testAttrListValues(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000533
Collin Winterd28fcbc2007-03-28 23:34:06 +0000534 def testAttrListLength(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000535
Collin Winterd28fcbc2007-03-28 23:34:06 +0000536 def testAttrList__getitem__(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000537
Collin Winterd28fcbc2007-03-28 23:34:06 +0000538 def testAttrList__setitem__(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000539
Collin Winterd28fcbc2007-03-28 23:34:06 +0000540 def testSetAttrValueandNodeValue(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000541
Collin Winterd28fcbc2007-03-28 23:34:06 +0000542 def testParseElement(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000543
Collin Winterd28fcbc2007-03-28 23:34:06 +0000544 def testParseAttributes(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000545
Collin Winterd28fcbc2007-03-28 23:34:06 +0000546 def testParseElementNamespaces(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000547
Collin Winterd28fcbc2007-03-28 23:34:06 +0000548 def testParseAttributeNamespaces(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000549
Collin Winterd28fcbc2007-03-28 23:34:06 +0000550 def testParseProcessingInstructions(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000551
Collin Winterd28fcbc2007-03-28 23:34:06 +0000552 def testChildNodes(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000553
Collin Winterd28fcbc2007-03-28 23:34:06 +0000554 def testFirstChild(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000555
Collin Winterd28fcbc2007-03-28 23:34:06 +0000556 def testHasChildNodes(self): pass
557
558 def _testCloneElementCopiesAttributes(self, e1, e2, test):
559 attrs1 = e1.attributes
560 attrs2 = e2.attributes
561 keys1 = attrs1.keys()
562 keys2 = attrs2.keys()
563 keys1.sort()
564 keys2.sort()
565 self.confirm(keys1 == keys2, "clone of element has same attribute keys")
566 for i in range(len(keys1)):
567 a1 = attrs1.item(i)
568 a2 = attrs2.item(i)
569 self.confirm(a1 is not a2
570 and a1.value == a2.value
571 and a1.nodeValue == a2.nodeValue
572 and a1.namespaceURI == a2.namespaceURI
573 and a1.localName == a2.localName
574 , "clone of attribute node has proper attribute values")
575 self.confirm(a2.ownerElement is e2,
576 "clone of attribute node correctly owned")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000577
Collin Winterd28fcbc2007-03-28 23:34:06 +0000578 def _setupCloneElement(self, deep):
579 dom = parseString("<doc attr='value'><foo/></doc>")
580 root = dom.documentElement
581 clone = root.cloneNode(deep)
582 self._testCloneElementCopiesAttributes(
583 root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
584 # mutilate the original so shared data is detected
585 root.tagName = root.nodeName = "MODIFIED"
586 root.setAttribute("attr", "NEW VALUE")
587 root.setAttribute("added", "VALUE")
588 return dom, clone
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000589
Collin Winterd28fcbc2007-03-28 23:34:06 +0000590 def testCloneElementShallow(self):
591 dom, clone = self._setupCloneElement(0)
592 self.confirm(len(clone.childNodes) == 0
593 and clone.childNodes.length == 0
594 and clone.parentNode is None
595 and clone.toxml() == '<doc attr="value"/>'
596 , "testCloneElementShallow")
597 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000598
Collin Winterd28fcbc2007-03-28 23:34:06 +0000599 def testCloneElementDeep(self):
600 dom, clone = self._setupCloneElement(1)
601 self.confirm(len(clone.childNodes) == 1
602 and clone.childNodes.length == 1
603 and clone.parentNode is None
604 and clone.toxml() == '<doc attr="value"><foo/></doc>'
605 , "testCloneElementDeep")
606 dom.unlink()
607
608 def testCloneDocumentShallow(self):
609 doc = parseString("<?xml version='1.0'?>\n"
610 "<!-- comment -->"
611 "<!DOCTYPE doc [\n"
612 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
613 "]>\n"
614 "<doc attr='value'/>")
615 doc2 = doc.cloneNode(0)
616 self.confirm(doc2 is None,
617 "testCloneDocumentShallow:"
618 " shallow cloning of documents makes no sense!")
619
620 def testCloneDocumentDeep(self):
621 doc = parseString("<?xml version='1.0'?>\n"
622 "<!-- comment -->"
623 "<!DOCTYPE doc [\n"
624 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
625 "]>\n"
626 "<doc attr='value'/>")
627 doc2 = doc.cloneNode(1)
628 self.confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
629 "testCloneDocumentDeep: document objects not distinct")
630 self.confirm(len(doc.childNodes) == len(doc2.childNodes),
631 "testCloneDocumentDeep: wrong number of Document children")
632 self.confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
633 "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
634 self.confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
635 "testCloneDocumentDeep: documentElement owner is not new document")
636 self.confirm(not doc.documentElement.isSameNode(doc2.documentElement),
637 "testCloneDocumentDeep: documentElement should not be shared")
638 if doc.doctype is not None:
639 # check the doctype iff the original DOM maintained it
640 self.confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
641 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
642 self.confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
643 self.confirm(not doc.doctype.isSameNode(doc2.doctype))
644
645 def testCloneDocumentTypeDeepOk(self):
646 doctype = create_nonempty_doctype()
647 clone = doctype.cloneNode(1)
648 self.confirm(clone is not None
649 and clone.nodeName == doctype.nodeName
650 and clone.name == doctype.name
651 and clone.publicId == doctype.publicId
652 and clone.systemId == doctype.systemId
653 and len(clone.entities) == len(doctype.entities)
654 and clone.entities.item(len(clone.entities)) is None
655 and len(clone.notations) == len(doctype.notations)
656 and clone.notations.item(len(clone.notations)) is None
657 and len(clone.childNodes) == 0)
658 for i in range(len(doctype.entities)):
659 se = doctype.entities.item(i)
660 ce = clone.entities.item(i)
661 self.confirm((not se.isSameNode(ce))
662 and (not ce.isSameNode(se))
663 and ce.nodeName == se.nodeName
664 and ce.notationName == se.notationName
665 and ce.publicId == se.publicId
666 and ce.systemId == se.systemId
667 and ce.encoding == se.encoding
668 and ce.actualEncoding == se.actualEncoding
669 and ce.version == se.version)
670 for i in range(len(doctype.notations)):
671 sn = doctype.notations.item(i)
672 cn = clone.notations.item(i)
673 self.confirm((not sn.isSameNode(cn))
674 and (not cn.isSameNode(sn))
675 and cn.nodeName == sn.nodeName
676 and cn.publicId == sn.publicId
677 and cn.systemId == sn.systemId)
678
679 def testCloneDocumentTypeDeepNotOk(self):
680 doc = create_doc_with_doctype()
681 clone = doc.doctype.cloneNode(1)
682 self.confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
683
684 def testCloneDocumentTypeShallowOk(self):
685 doctype = create_nonempty_doctype()
686 clone = doctype.cloneNode(0)
687 self.confirm(clone is not None
688 and clone.nodeName == doctype.nodeName
689 and clone.name == doctype.name
690 and clone.publicId == doctype.publicId
691 and clone.systemId == doctype.systemId
692 and len(clone.entities) == 0
693 and clone.entities.item(0) is None
694 and len(clone.notations) == 0
695 and clone.notations.item(0) is None
696 and len(clone.childNodes) == 0)
697
698 def testCloneDocumentTypeShallowNotOk(self):
699 doc = create_doc_with_doctype()
700 clone = doc.doctype.cloneNode(0)
701 self.confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
702
703 def check_import_document(self, deep, testName):
704 doc1 = parseString("<doc/>")
705 doc2 = parseString("<doc/>")
706 self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000707
Collin Winterd28fcbc2007-03-28 23:34:06 +0000708 def testImportDocumentShallow(self):
709 self.check_import_document(0, "testImportDocumentShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000710
Collin Winterd28fcbc2007-03-28 23:34:06 +0000711 def testImportDocumentDeep(self):
712 self.check_import_document(1, "testImportDocumentDeep")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000713
Collin Winterd28fcbc2007-03-28 23:34:06 +0000714 def testImportDocumentTypeShallow(self):
715 src = create_doc_with_doctype()
716 target = create_doc_without_doctype()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000717 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000718 src.doctype, 0)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000719
Collin Winterd28fcbc2007-03-28 23:34:06 +0000720 def testImportDocumentTypeDeep(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, 1)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000725
Collin Winterd28fcbc2007-03-28 23:34:06 +0000726 # Testing attribute clones uses a helper, and should always be deep,
727 # even if the argument to cloneNode is false.
728 def check_clone_attribute(self, deep, testName):
729 doc = parseString("<doc attr='value'/>")
730 attr = doc.documentElement.getAttributeNode("attr")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000731 self.assertNotEqual(attr, None)
Collin Winterd28fcbc2007-03-28 23:34:06 +0000732 clone = attr.cloneNode(deep)
733 self.confirm(not clone.isSameNode(attr))
734 self.confirm(not attr.isSameNode(clone))
735 self.confirm(clone.ownerElement is None,
736 testName + ": ownerElement should be None")
737 self.confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
738 testName + ": ownerDocument does not match")
739 self.confirm(clone.specified,
740 testName + ": cloned attribute must have specified == True")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000741
Collin Winterd28fcbc2007-03-28 23:34:06 +0000742 def testCloneAttributeShallow(self):
743 self.check_clone_attribute(0, "testCloneAttributeShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000744
Collin Winterd28fcbc2007-03-28 23:34:06 +0000745 def testCloneAttributeDeep(self):
746 self.check_clone_attribute(1, "testCloneAttributeDeep")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000747
Collin Winterd28fcbc2007-03-28 23:34:06 +0000748 def check_clone_pi(self, deep, testName):
749 doc = parseString("<?target data?><doc/>")
750 pi = doc.firstChild
751 self.assertEquals(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE)
752 clone = pi.cloneNode(deep)
753 self.confirm(clone.target == pi.target
754 and clone.data == pi.data)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000755
Collin Winterd28fcbc2007-03-28 23:34:06 +0000756 def testClonePIShallow(self):
757 self.check_clone_pi(0, "testClonePIShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000758
Collin Winterd28fcbc2007-03-28 23:34:06 +0000759 def testClonePIDeep(self):
760 self.check_clone_pi(1, "testClonePIDeep")
761
762 def testNormalize(self):
763 doc = parseString("<doc/>")
764 root = doc.documentElement
765 root.appendChild(doc.createTextNode("first"))
766 root.appendChild(doc.createTextNode("second"))
767 self.confirm(len(root.childNodes) == 2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000768 and root.childNodes.length == 2,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000769 "testNormalize -- preparation")
770 doc.normalize()
771 self.confirm(len(root.childNodes) == 1
772 and root.childNodes.length == 1
773 and root.firstChild is root.lastChild
774 and root.firstChild.data == "firstsecond"
775 , "testNormalize -- result")
776 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000777
Collin Winterd28fcbc2007-03-28 23:34:06 +0000778 doc = parseString("<doc/>")
779 root = doc.documentElement
780 root.appendChild(doc.createTextNode(""))
781 doc.normalize()
782 self.confirm(len(root.childNodes) == 0
783 and root.childNodes.length == 0,
784 "testNormalize -- single empty node removed")
785 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000786
R. David Murray0374a822009-04-09 21:54:50 +0000787 def testNormalizeCombineAndNextSibling(self):
788 doc = parseString("<doc/>")
789 root = doc.documentElement
790 root.appendChild(doc.createTextNode("first"))
791 root.appendChild(doc.createTextNode("second"))
792 root.appendChild(doc.createElement("i"))
793 self.confirm(len(root.childNodes) == 3
794 and root.childNodes.length == 3,
795 "testNormalizeCombineAndNextSibling -- preparation")
796 doc.normalize()
797 self.confirm(len(root.childNodes) == 2
798 and root.childNodes.length == 2
799 and root.firstChild.data == "firstsecond"
800 and root.firstChild is not root.lastChild
801 and root.firstChild.nextSibling is root.lastChild
802 and root.firstChild.previousSibling is None
803 and root.lastChild.previousSibling is root.firstChild
804 and root.lastChild.nextSibling is None
805 , "testNormalizeCombinedAndNextSibling -- result")
806 doc.unlink()
807
808 def testNormalizeDeleteWithPrevSibling(self):
809 doc = parseString("<doc/>")
810 root = doc.documentElement
811 root.appendChild(doc.createTextNode("first"))
812 root.appendChild(doc.createTextNode(""))
813 self.confirm(len(root.childNodes) == 2
814 and root.childNodes.length == 2,
815 "testNormalizeDeleteWithPrevSibling -- preparation")
816 doc.normalize()
817 self.confirm(len(root.childNodes) == 1
818 and root.childNodes.length == 1
819 and root.firstChild.data == "first"
820 and root.firstChild is root.lastChild
821 and root.firstChild.nextSibling is None
822 and root.firstChild.previousSibling is None
823 , "testNormalizeDeleteWithPrevSibling -- result")
824 doc.unlink()
825
826 def testNormalizeDeleteWithNextSibling(self):
827 doc = parseString("<doc/>")
828 root = doc.documentElement
829 root.appendChild(doc.createTextNode(""))
830 root.appendChild(doc.createTextNode("second"))
831 self.confirm(len(root.childNodes) == 2
832 and root.childNodes.length == 2,
833 "testNormalizeDeleteWithNextSibling -- preparation")
834 doc.normalize()
835 self.confirm(len(root.childNodes) == 1
836 and root.childNodes.length == 1
837 and root.firstChild.data == "second"
838 and root.firstChild is root.lastChild
839 and root.firstChild.nextSibling is None
840 and root.firstChild.previousSibling is None
841 , "testNormalizeDeleteWithNextSibling -- result")
842 doc.unlink()
843
844 def testNormalizeDeleteWithTwoNonTextSiblings(self):
845 doc = parseString("<doc/>")
846 root = doc.documentElement
847 root.appendChild(doc.createElement("i"))
848 root.appendChild(doc.createTextNode(""))
849 root.appendChild(doc.createElement("i"))
850 self.confirm(len(root.childNodes) == 3
851 and root.childNodes.length == 3,
852 "testNormalizeDeleteWithTwoSiblings -- preparation")
853 doc.normalize()
854 self.confirm(len(root.childNodes) == 2
855 and root.childNodes.length == 2
856 and root.firstChild is not root.lastChild
857 and root.firstChild.nextSibling is root.lastChild
858 and root.firstChild.previousSibling is None
859 and root.lastChild.previousSibling is root.firstChild
860 and root.lastChild.nextSibling is None
861 , "testNormalizeDeleteWithTwoSiblings -- result")
862 doc.unlink()
863
864 def testNormalizeDeleteAndCombine(self):
865 doc = parseString("<doc/>")
866 root = doc.documentElement
867 root.appendChild(doc.createTextNode(""))
868 root.appendChild(doc.createTextNode("second"))
869 root.appendChild(doc.createTextNode(""))
870 root.appendChild(doc.createTextNode("fourth"))
871 root.appendChild(doc.createTextNode(""))
872 self.confirm(len(root.childNodes) == 5
873 and root.childNodes.length == 5,
874 "testNormalizeDeleteAndCombine -- preparation")
875 doc.normalize()
876 self.confirm(len(root.childNodes) == 1
877 and root.childNodes.length == 1
878 and root.firstChild is root.lastChild
879 and root.firstChild.data == "secondfourth"
880 and root.firstChild.previousSibling is None
881 and root.firstChild.nextSibling is None
882 , "testNormalizeDeleteAndCombine -- result")
883 doc.unlink()
884
885 def testNormalizeRecursion(self):
886 doc = parseString("<doc>"
887 "<o>"
888 "<i/>"
889 "t"
890 #
891 #x
892 "</o>"
893 "<o>"
894 "<o>"
895 "t2"
896 #x2
897 "</o>"
898 "t3"
899 #x3
900 "</o>"
901 #
902 "</doc>")
903 root = doc.documentElement
904 root.childNodes[0].appendChild(doc.createTextNode(""))
905 root.childNodes[0].appendChild(doc.createTextNode("x"))
906 root.childNodes[1].childNodes[0].appendChild(doc.createTextNode("x2"))
907 root.childNodes[1].appendChild(doc.createTextNode("x3"))
908 root.appendChild(doc.createTextNode(""))
909 self.confirm(len(root.childNodes) == 3
910 and root.childNodes.length == 3
911 and len(root.childNodes[0].childNodes) == 4
912 and root.childNodes[0].childNodes.length == 4
913 and len(root.childNodes[1].childNodes) == 3
914 and root.childNodes[1].childNodes.length == 3
915 and len(root.childNodes[1].childNodes[0].childNodes) == 2
916 and root.childNodes[1].childNodes[0].childNodes.length == 2
917 , "testNormalize2 -- preparation")
918 doc.normalize()
919 self.confirm(len(root.childNodes) == 2
920 and root.childNodes.length == 2
921 and len(root.childNodes[0].childNodes) == 2
922 and root.childNodes[0].childNodes.length == 2
923 and len(root.childNodes[1].childNodes) == 2
924 and root.childNodes[1].childNodes.length == 2
925 and len(root.childNodes[1].childNodes[0].childNodes) == 1
926 and root.childNodes[1].childNodes[0].childNodes.length == 1
927 , "testNormalize2 -- childNodes lengths")
928 self.confirm(root.childNodes[0].childNodes[1].data == "tx"
929 and root.childNodes[1].childNodes[0].childNodes[0].data == "t2x2"
930 and root.childNodes[1].childNodes[1].data == "t3x3"
931 , "testNormalize2 -- joined text fields")
932 self.confirm(root.childNodes[0].childNodes[1].nextSibling is None
933 and root.childNodes[0].childNodes[1].previousSibling
934 is root.childNodes[0].childNodes[0]
935 and root.childNodes[0].childNodes[0].previousSibling is None
936 and root.childNodes[0].childNodes[0].nextSibling
937 is root.childNodes[0].childNodes[1]
938 and root.childNodes[1].childNodes[1].nextSibling is None
939 and root.childNodes[1].childNodes[1].previousSibling
940 is root.childNodes[1].childNodes[0]
941 and root.childNodes[1].childNodes[0].previousSibling is None
942 and root.childNodes[1].childNodes[0].nextSibling
943 is root.childNodes[1].childNodes[1]
944 , "testNormalize2 -- sibling pointers")
945 doc.unlink()
946
947
Andrew M. Kuchling19aff0c2008-02-23 17:10:46 +0000948 def testBug1433694(self):
949 doc = parseString("<o><i/>t</o>")
950 node = doc.documentElement
951 node.childNodes[1].nodeValue = ""
952 node.normalize()
Florent Xiclunabc27c6a2010-03-19 18:34:55 +0000953 self.confirm(node.childNodes[-1].nextSibling is None,
Andrew M. Kuchling19aff0c2008-02-23 17:10:46 +0000954 "Final child's .nextSibling should be None")
955
Collin Winterd28fcbc2007-03-28 23:34:06 +0000956 def testSiblings(self):
957 doc = parseString("<doc><?pi?>text?<elm/></doc>")
958 root = doc.documentElement
959 (pi, text, elm) = root.childNodes
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000960
Collin Winterd28fcbc2007-03-28 23:34:06 +0000961 self.confirm(pi.nextSibling is text and
962 pi.previousSibling is None and
963 text.nextSibling is elm and
964 text.previousSibling is pi and
965 elm.nextSibling is None and
966 elm.previousSibling is text, "testSiblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000967
Collin Winterd28fcbc2007-03-28 23:34:06 +0000968 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000969
Collin Winterd28fcbc2007-03-28 23:34:06 +0000970 def testParents(self):
971 doc = parseString(
972 "<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
973 root = doc.documentElement
974 elm1 = root.childNodes[0]
975 (elm2a, elm2b) = elm1.childNodes
976 elm3 = elm2b.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000977
Collin Winterd28fcbc2007-03-28 23:34:06 +0000978 self.confirm(root.parentNode is doc and
979 elm1.parentNode is root and
980 elm2a.parentNode is elm1 and
981 elm2b.parentNode is elm1 and
982 elm3.parentNode is elm2b, "testParents")
983 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000984
Collin Winterd28fcbc2007-03-28 23:34:06 +0000985 def testNodeListItem(self):
986 doc = parseString("<doc><e/><e/></doc>")
987 children = doc.childNodes
988 docelem = children[0]
989 self.confirm(children[0] is children.item(0)
990 and children.item(1) is None
991 and docelem.childNodes.item(0) is docelem.childNodes[0]
992 and docelem.childNodes.item(1) is docelem.childNodes[1]
993 and docelem.childNodes.item(0).childNodes.item(0) is None,
994 "test NodeList.item()")
995 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000996
Collin Winterd28fcbc2007-03-28 23:34:06 +0000997 def testSAX2DOM(self):
998 from xml.dom import pulldom
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000999
Collin Winterd28fcbc2007-03-28 23:34:06 +00001000 sax2dom = pulldom.SAX2DOM()
1001 sax2dom.startDocument()
1002 sax2dom.startElement("doc", {})
1003 sax2dom.characters("text")
1004 sax2dom.startElement("subelm", {})
1005 sax2dom.characters("text")
1006 sax2dom.endElement("subelm")
1007 sax2dom.characters("text")
1008 sax2dom.endElement("doc")
1009 sax2dom.endDocument()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001010
Collin Winterd28fcbc2007-03-28 23:34:06 +00001011 doc = sax2dom.document
1012 root = doc.documentElement
1013 (text1, elm1, text2) = root.childNodes
1014 text3 = elm1.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001015
Collin Winterd28fcbc2007-03-28 23:34:06 +00001016 self.confirm(text1.previousSibling is None and
1017 text1.nextSibling is elm1 and
1018 elm1.previousSibling is text1 and
1019 elm1.nextSibling is text2 and
1020 text2.previousSibling is elm1 and
1021 text2.nextSibling is None and
1022 text3.previousSibling is None and
1023 text3.nextSibling is None, "testSAX2DOM - siblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001024
Collin Winterd28fcbc2007-03-28 23:34:06 +00001025 self.confirm(root.parentNode is doc and
1026 text1.parentNode is root and
1027 elm1.parentNode is root and
1028 text2.parentNode is root and
1029 text3.parentNode is elm1, "testSAX2DOM - parents")
1030 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001031
Collin Winterd28fcbc2007-03-28 23:34:06 +00001032 def testEncodings(self):
1033 doc = parseString('<foo>&#x20ac;</foo>')
1034 self.confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001035 and doc.toxml('utf-8') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +00001036 '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001037 and doc.toxml('iso-8859-15') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +00001038 '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
1039 "testEncodings - encoding EURO SIGN")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001040
1041 # Verify that character decoding errors throw exceptions instead
Collin Winterd28fcbc2007-03-28 23:34:06 +00001042 # of crashing
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001043 self.assertRaises(UnicodeDecodeError, parseString,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001044 '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001045
Collin Winterd28fcbc2007-03-28 23:34:06 +00001046 doc.unlink()
1047
1048 class UserDataHandler:
1049 called = 0
1050 def handle(self, operation, key, data, src, dst):
1051 dst.setUserData(key, data + 1, self)
1052 src.setUserData(key, None, None)
1053 self.called = 1
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001054
Collin Winterd28fcbc2007-03-28 23:34:06 +00001055 def testUserData(self):
1056 dom = Document()
1057 n = dom.createElement('e')
1058 self.confirm(n.getUserData("foo") is None)
1059 n.setUserData("foo", None, None)
1060 self.confirm(n.getUserData("foo") is None)
1061 n.setUserData("foo", 12, 12)
1062 n.setUserData("bar", 13, 13)
1063 self.confirm(n.getUserData("foo") == 12)
1064 self.confirm(n.getUserData("bar") == 13)
1065 n.setUserData("foo", None, None)
1066 self.confirm(n.getUserData("foo") is None)
1067 self.confirm(n.getUserData("bar") == 13)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001068
Collin Winterd28fcbc2007-03-28 23:34:06 +00001069 handler = self.UserDataHandler()
1070 n.setUserData("bar", 12, handler)
1071 c = n.cloneNode(1)
1072 self.confirm(handler.called
1073 and n.getUserData("bar") is None
1074 and c.getUserData("bar") == 13)
1075 n.unlink()
1076 c.unlink()
1077 dom.unlink()
1078
1079 def checkRenameNodeSharedConstraints(self, doc, node):
1080 # Make sure illegal NS usage is detected:
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001081 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001082 "http://xml.python.org/ns", "xmlns:foo")
1083 doc2 = parseString("<doc/>")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001084 self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001085 xml.dom.EMPTY_NAMESPACE, "foo")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001086
Collin Winterd28fcbc2007-03-28 23:34:06 +00001087 def testRenameAttribute(self):
1088 doc = parseString("<doc a='v'/>")
1089 elem = doc.documentElement
1090 attrmap = elem.attributes
1091 attr = elem.attributes['a']
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001092
Collin Winterd28fcbc2007-03-28 23:34:06 +00001093 # Simple renaming
1094 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
1095 self.confirm(attr.name == "b"
1096 and attr.nodeName == "b"
1097 and attr.localName is None
1098 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
1099 and attr.prefix is None
1100 and attr.value == "v"
1101 and elem.getAttributeNode("a") is None
1102 and elem.getAttributeNode("b").isSameNode(attr)
1103 and attrmap["b"].isSameNode(attr)
1104 and attr.ownerDocument.isSameNode(doc)
1105 and attr.ownerElement.isSameNode(elem))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001106
Collin Winterd28fcbc2007-03-28 23:34:06 +00001107 # Rename to have a namespace, no prefix
1108 attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
1109 self.confirm(attr.name == "c"
1110 and attr.nodeName == "c"
1111 and attr.localName == "c"
1112 and attr.namespaceURI == "http://xml.python.org/ns"
1113 and attr.prefix is None
1114 and attr.value == "v"
1115 and elem.getAttributeNode("a") is None
1116 and elem.getAttributeNode("b") is None
1117 and elem.getAttributeNode("c").isSameNode(attr)
1118 and elem.getAttributeNodeNS(
1119 "http://xml.python.org/ns", "c").isSameNode(attr)
1120 and attrmap["c"].isSameNode(attr)
1121 and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001122
Collin Winterd28fcbc2007-03-28 23:34:06 +00001123 # Rename to have a namespace, with prefix
1124 attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
1125 self.confirm(attr.name == "p:d"
1126 and attr.nodeName == "p:d"
1127 and attr.localName == "d"
1128 and attr.namespaceURI == "http://xml.python.org/ns2"
1129 and attr.prefix == "p"
1130 and attr.value == "v"
1131 and elem.getAttributeNode("a") is None
1132 and elem.getAttributeNode("b") is None
1133 and elem.getAttributeNode("c") is None
1134 and elem.getAttributeNodeNS(
1135 "http://xml.python.org/ns", "c") is None
1136 and elem.getAttributeNode("p:d").isSameNode(attr)
1137 and elem.getAttributeNodeNS(
1138 "http://xml.python.org/ns2", "d").isSameNode(attr)
1139 and attrmap["p:d"].isSameNode(attr)
1140 and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001141
Collin Winterd28fcbc2007-03-28 23:34:06 +00001142 # Rename back to a simple non-NS node
1143 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
1144 self.confirm(attr.name == "e"
1145 and attr.nodeName == "e"
1146 and attr.localName is None
1147 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
1148 and attr.prefix is None
1149 and attr.value == "v"
1150 and elem.getAttributeNode("a") is None
1151 and elem.getAttributeNode("b") is None
1152 and elem.getAttributeNode("c") is None
1153 and elem.getAttributeNode("p:d") is None
1154 and elem.getAttributeNodeNS(
1155 "http://xml.python.org/ns", "c") is None
1156 and elem.getAttributeNode("e").isSameNode(attr)
1157 and attrmap["e"].isSameNode(attr))
1158
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001159 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001160 "http://xml.python.org/ns", "xmlns")
1161 self.checkRenameNodeSharedConstraints(doc, attr)
1162 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001163
Collin Winterd28fcbc2007-03-28 23:34:06 +00001164 def testRenameElement(self):
1165 doc = parseString("<doc/>")
1166 elem = doc.documentElement
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001167
Collin Winterd28fcbc2007-03-28 23:34:06 +00001168 # Simple renaming
1169 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
1170 self.confirm(elem.tagName == "a"
1171 and elem.nodeName == "a"
1172 and elem.localName is None
1173 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1174 and elem.prefix is None
1175 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001176
Collin Winterd28fcbc2007-03-28 23:34:06 +00001177 # Rename to have a namespace, no prefix
1178 elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
1179 self.confirm(elem.tagName == "b"
1180 and elem.nodeName == "b"
1181 and elem.localName == "b"
1182 and elem.namespaceURI == "http://xml.python.org/ns"
1183 and elem.prefix is None
1184 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001185
Collin Winterd28fcbc2007-03-28 23:34:06 +00001186 # Rename to have a namespace, with prefix
1187 elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
1188 self.confirm(elem.tagName == "p:c"
1189 and elem.nodeName == "p:c"
1190 and elem.localName == "c"
1191 and elem.namespaceURI == "http://xml.python.org/ns2"
1192 and elem.prefix == "p"
1193 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001194
Collin Winterd28fcbc2007-03-28 23:34:06 +00001195 # Rename back to a simple non-NS node
1196 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
1197 self.confirm(elem.tagName == "d"
1198 and elem.nodeName == "d"
1199 and elem.localName is None
1200 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1201 and elem.prefix is None
1202 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001203
Collin Winterd28fcbc2007-03-28 23:34:06 +00001204 self.checkRenameNodeSharedConstraints(doc, elem)
1205 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001206
Collin Winterd28fcbc2007-03-28 23:34:06 +00001207 def testRenameOther(self):
1208 # We have to create a comment node explicitly since not all DOM
1209 # builders used with minidom add comments to the DOM.
1210 doc = xml.dom.minidom.getDOMImplementation().createDocument(
1211 xml.dom.EMPTY_NAMESPACE, "e", None)
1212 node = doc.createComment("comment")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001213 self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001214 xml.dom.EMPTY_NAMESPACE, "foo")
1215 doc.unlink()
1216
1217 def testWholeText(self):
1218 doc = parseString("<doc>a</doc>")
1219 elem = doc.documentElement
1220 text = elem.childNodes[0]
1221 self.assertEquals(text.nodeType, Node.TEXT_NODE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001222
Collin Winterd28fcbc2007-03-28 23:34:06 +00001223 self.checkWholeText(text, "a")
1224 elem.appendChild(doc.createTextNode("b"))
1225 self.checkWholeText(text, "ab")
1226 elem.insertBefore(doc.createCDATASection("c"), text)
1227 self.checkWholeText(text, "cab")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001228
Collin Winterd28fcbc2007-03-28 23:34:06 +00001229 # make sure we don't cross other nodes
1230 splitter = doc.createComment("comment")
1231 elem.appendChild(splitter)
1232 text2 = doc.createTextNode("d")
1233 elem.appendChild(text2)
1234 self.checkWholeText(text, "cab")
1235 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001236
Collin Winterd28fcbc2007-03-28 23:34:06 +00001237 x = doc.createElement("x")
1238 elem.replaceChild(x, splitter)
1239 splitter = x
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.createProcessingInstruction("y", "z")
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 elem.removeChild(splitter)
1250 self.checkWholeText(text, "cabd")
1251 self.checkWholeText(text2, "cabd")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001252
Collin Winterd28fcbc2007-03-28 23:34:06 +00001253 def testPatch1094164(self):
1254 doc = parseString("<doc><e/></doc>")
1255 elem = doc.documentElement
1256 e = elem.firstChild
1257 self.confirm(e.parentNode is elem, "Before replaceChild()")
1258 # Check that replacing a child with itself leaves the tree unchanged
1259 elem.replaceChild(e, e)
1260 self.confirm(e.parentNode is elem, "After replaceChild()")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001261
Collin Winterd28fcbc2007-03-28 23:34:06 +00001262 def testReplaceWholeText(self):
1263 def setup():
1264 doc = parseString("<doc>a<e/>d</doc>")
1265 elem = doc.documentElement
1266 text1 = elem.firstChild
1267 text2 = elem.lastChild
1268 splitter = text1.nextSibling
1269 elem.insertBefore(doc.createTextNode("b"), splitter)
1270 elem.insertBefore(doc.createCDATASection("c"), text1)
1271 return doc, elem, text1, splitter, text2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001272
Collin Winterd28fcbc2007-03-28 23:34:06 +00001273 doc, elem, text1, splitter, text2 = setup()
1274 text = text1.replaceWholeText("new content")
1275 self.checkWholeText(text, "new content")
1276 self.checkWholeText(text2, "d")
1277 self.confirm(len(elem.childNodes) == 3)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001278
Collin Winterd28fcbc2007-03-28 23:34:06 +00001279 doc, elem, text1, splitter, text2 = setup()
1280 text = text2.replaceWholeText("new content")
1281 self.checkWholeText(text, "new content")
1282 self.checkWholeText(text1, "cab")
1283 self.confirm(len(elem.childNodes) == 5)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001284
Collin Winterd28fcbc2007-03-28 23:34:06 +00001285 doc, elem, text1, splitter, text2 = setup()
1286 text = text1.replaceWholeText("")
1287 self.checkWholeText(text2, "d")
1288 self.confirm(text is None
1289 and len(elem.childNodes) == 2)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001290
Collin Winterd28fcbc2007-03-28 23:34:06 +00001291 def testSchemaType(self):
1292 doc = parseString(
1293 "<!DOCTYPE doc [\n"
1294 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
1295 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
1296 " <!ATTLIST doc id ID #IMPLIED \n"
1297 " ref IDREF #IMPLIED \n"
1298 " refs IDREFS #IMPLIED \n"
1299 " enum (a|b) #IMPLIED \n"
1300 " ent ENTITY #IMPLIED \n"
1301 " ents ENTITIES #IMPLIED \n"
1302 " nm NMTOKEN #IMPLIED \n"
1303 " nms NMTOKENS #IMPLIED \n"
1304 " text CDATA #IMPLIED \n"
1305 " >\n"
1306 "]><doc id='name' notid='name' text='splat!' enum='b'"
1307 " ref='name' refs='name name' ent='e1' ents='e1 e2'"
1308 " nm='123' nms='123 abc' />")
1309 elem = doc.documentElement
1310 # We don't want to rely on any specific loader at this point, so
1311 # just make sure we can get to all the names, and that the
1312 # DTD-based namespace is right. The names can vary by loader
1313 # since each supports a different level of DTD information.
1314 t = elem.schemaType
1315 self.confirm(t.name is None
1316 and t.namespace == xml.dom.EMPTY_NAMESPACE)
1317 names = "id notid text enum ref refs ent ents nm nms".split()
1318 for name in names:
1319 a = elem.getAttributeNode(name)
1320 t = a.schemaType
1321 self.confirm(hasattr(t, "name")
1322 and t.namespace == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001323
Collin Winterd28fcbc2007-03-28 23:34:06 +00001324 def testSetIdAttribute(self):
1325 doc = parseString("<doc a1='v' a2='w'/>")
1326 e = doc.documentElement
1327 a1 = e.getAttributeNode("a1")
1328 a2 = e.getAttributeNode("a2")
1329 self.confirm(doc.getElementById("v") is None
1330 and not a1.isId
1331 and not a2.isId)
1332 e.setIdAttribute("a1")
1333 self.confirm(e.isSameNode(doc.getElementById("v"))
1334 and a1.isId
1335 and not a2.isId)
1336 e.setIdAttribute("a2")
1337 self.confirm(e.isSameNode(doc.getElementById("v"))
1338 and e.isSameNode(doc.getElementById("w"))
1339 and a1.isId
1340 and a2.isId)
1341 # replace the a1 node; the new node should *not* be an ID
1342 a3 = doc.createAttribute("a1")
1343 a3.value = "v"
1344 e.setAttributeNode(a3)
1345 self.confirm(doc.getElementById("v") is None
1346 and e.isSameNode(doc.getElementById("w"))
1347 and not a1.isId
1348 and a2.isId
1349 and not a3.isId)
1350 # renaming an attribute should not affect its ID-ness:
1351 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1352 self.confirm(e.isSameNode(doc.getElementById("w"))
1353 and a2.isId)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001354
Collin Winterd28fcbc2007-03-28 23:34:06 +00001355 def testSetIdAttributeNS(self):
1356 NS1 = "http://xml.python.org/ns1"
1357 NS2 = "http://xml.python.org/ns2"
1358 doc = parseString("<doc"
1359 " xmlns:ns1='" + NS1 + "'"
1360 " xmlns:ns2='" + NS2 + "'"
1361 " ns1:a1='v' ns2:a2='w'/>")
1362 e = doc.documentElement
1363 a1 = e.getAttributeNodeNS(NS1, "a1")
1364 a2 = e.getAttributeNodeNS(NS2, "a2")
1365 self.confirm(doc.getElementById("v") is None
1366 and not a1.isId
1367 and not a2.isId)
1368 e.setIdAttributeNS(NS1, "a1")
1369 self.confirm(e.isSameNode(doc.getElementById("v"))
1370 and a1.isId
1371 and not a2.isId)
1372 e.setIdAttributeNS(NS2, "a2")
1373 self.confirm(e.isSameNode(doc.getElementById("v"))
1374 and e.isSameNode(doc.getElementById("w"))
1375 and a1.isId
1376 and a2.isId)
1377 # replace the a1 node; the new node should *not* be an ID
1378 a3 = doc.createAttributeNS(NS1, "a1")
1379 a3.value = "v"
1380 e.setAttributeNode(a3)
1381 self.confirm(e.isSameNode(doc.getElementById("w")))
1382 self.confirm(not a1.isId)
1383 self.confirm(a2.isId)
1384 self.confirm(not a3.isId)
1385 self.confirm(doc.getElementById("v") is None)
1386 # renaming an attribute should not affect its ID-ness:
1387 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1388 self.confirm(e.isSameNode(doc.getElementById("w"))
1389 and a2.isId)
1390
1391 def testSetIdAttributeNode(self):
1392 NS1 = "http://xml.python.org/ns1"
1393 NS2 = "http://xml.python.org/ns2"
1394 doc = parseString("<doc"
1395 " xmlns:ns1='" + NS1 + "'"
1396 " xmlns:ns2='" + NS2 + "'"
1397 " ns1:a1='v' ns2:a2='w'/>")
1398 e = doc.documentElement
1399 a1 = e.getAttributeNodeNS(NS1, "a1")
1400 a2 = e.getAttributeNodeNS(NS2, "a2")
1401 self.confirm(doc.getElementById("v") is None
1402 and not a1.isId
1403 and not a2.isId)
1404 e.setIdAttributeNode(a1)
1405 self.confirm(e.isSameNode(doc.getElementById("v"))
1406 and a1.isId
1407 and not a2.isId)
1408 e.setIdAttributeNode(a2)
1409 self.confirm(e.isSameNode(doc.getElementById("v"))
1410 and e.isSameNode(doc.getElementById("w"))
1411 and a1.isId
1412 and a2.isId)
1413 # replace the a1 node; the new node should *not* be an ID
1414 a3 = doc.createAttributeNS(NS1, "a1")
1415 a3.value = "v"
1416 e.setAttributeNode(a3)
1417 self.confirm(e.isSameNode(doc.getElementById("w")))
1418 self.confirm(not a1.isId)
1419 self.confirm(a2.isId)
1420 self.confirm(not a3.isId)
1421 self.confirm(doc.getElementById("v") is None)
1422 # renaming an attribute should not affect its ID-ness:
1423 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1424 self.confirm(e.isSameNode(doc.getElementById("w"))
1425 and a2.isId)
1426
1427 def testPickledDocument(self):
1428 doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
1429 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
1430 " 'http://xml.python.org/system' [\n"
1431 " <!ELEMENT e EMPTY>\n"
1432 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
1433 "]><doc attr='value'> text\n"
1434 "<?pi sample?> <!-- comment --> <e/> </doc>")
1435 s = pickle.dumps(doc)
1436 doc2 = pickle.loads(s)
1437 stack = [(doc, doc2)]
1438 while stack:
1439 n1, n2 = stack.pop()
1440 self.confirm(n1.nodeType == n2.nodeType
1441 and len(n1.childNodes) == len(n2.childNodes)
1442 and n1.nodeName == n2.nodeName
1443 and not n1.isSameNode(n2)
1444 and not n2.isSameNode(n1))
1445 if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
1446 len(n1.entities)
1447 len(n2.entities)
1448 len(n1.notations)
1449 len(n2.notations)
1450 self.confirm(len(n1.entities) == len(n2.entities)
1451 and len(n1.notations) == len(n2.notations))
1452 for i in range(len(n1.notations)):
Georg Brandlcd4a21b2010-02-06 23:34:10 +00001453 # XXX this loop body doesn't seem to be executed?
Collin Winterd28fcbc2007-03-28 23:34:06 +00001454 no1 = n1.notations.item(i)
1455 no2 = n1.notations.item(i)
1456 self.confirm(no1.name == no2.name
1457 and no1.publicId == no2.publicId
1458 and no1.systemId == no2.systemId)
Georg Brandlcd4a21b2010-02-06 23:34:10 +00001459 stack.append((no1, no2))
Collin Winterd28fcbc2007-03-28 23:34:06 +00001460 for i in range(len(n1.entities)):
1461 e1 = n1.entities.item(i)
1462 e2 = n2.entities.item(i)
1463 self.confirm(e1.notationName == e2.notationName
1464 and e1.publicId == e2.publicId
1465 and e1.systemId == e2.systemId)
1466 stack.append((e1, e2))
1467 if n1.nodeType != Node.DOCUMENT_NODE:
1468 self.confirm(n1.ownerDocument.isSameNode(doc)
1469 and n2.ownerDocument.isSameNode(doc2))
1470 for i in range(len(n1.childNodes)):
1471 stack.append((n1.childNodes[i], n2.childNodes[i]))
1472
Martin v. Löwis27e4a172008-05-23 15:18:28 +00001473 def testSerializeCommentNodeWithDoubleHyphen(self):
1474 doc = create_doc_without_doctype()
1475 doc.appendChild(doc.createComment("foo--bar"))
1476 self.assertRaises(ValueError, doc.toxml)
1477
Collin Winterd28fcbc2007-03-28 23:34:06 +00001478def test_main():
1479 run_unittest(MinidomTest)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001480
Collin Winterd28fcbc2007-03-28 23:34:06 +00001481if __name__ == "__main__":
1482 test_main()