blob: cb1c60cb26a7b6d1a47a324d48071652d337be94 [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):
Collin Winterd28fcbc2007-03-28 23:34:06 +000049 def confirm(self, test, testname = "Test"):
50 self.assertTrue(test, testname)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000051
Collin Winterd28fcbc2007-03-28 23:34:06 +000052 def checkWholeText(self, node, s):
53 t = node.wholeText
54 self.confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000055
Collin Winterd28fcbc2007-03-28 23:34:06 +000056 def testParseFromFile(self):
57 dom = parse(StringIO(open(tstfile).read()))
58 dom.unlink()
59 self.confirm(isinstance(dom,Document))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000060
Collin Winterd28fcbc2007-03-28 23:34:06 +000061 def testGetElementsByTagName(self):
62 dom = parse(tstfile)
63 self.confirm(dom.getElementsByTagName("LI") == \
64 dom.documentElement.getElementsByTagName("LI"))
65 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000066
Collin Winterd28fcbc2007-03-28 23:34:06 +000067 def testInsertBefore(self):
68 dom = parseString("<doc><foo/></doc>")
69 root = dom.documentElement
70 elem = root.childNodes[0]
71 nelem = dom.createElement("element")
72 root.insertBefore(nelem, elem)
73 self.confirm(len(root.childNodes) == 2
74 and root.childNodes.length == 2
75 and root.childNodes[0] is nelem
76 and root.childNodes.item(0) is nelem
77 and root.childNodes[1] is elem
78 and root.childNodes.item(1) is elem
79 and root.firstChild is nelem
80 and root.lastChild is elem
81 and root.toxml() == "<doc><element/><foo/></doc>"
82 , "testInsertBefore -- node properly placed in tree")
83 nelem = dom.createElement("element")
84 root.insertBefore(nelem, None)
85 self.confirm(len(root.childNodes) == 3
86 and root.childNodes.length == 3
87 and root.childNodes[1] is elem
88 and root.childNodes.item(1) is elem
89 and root.childNodes[2] is nelem
90 and root.childNodes.item(2) is nelem
91 and root.lastChild is nelem
92 and nelem.previousSibling is elem
93 and root.toxml() == "<doc><element/><foo/><element/></doc>"
94 , "testInsertBefore -- node properly placed in tree")
95 nelem2 = dom.createElement("bar")
96 root.insertBefore(nelem2, nelem)
97 self.confirm(len(root.childNodes) == 4
98 and root.childNodes.length == 4
99 and root.childNodes[2] is nelem2
100 and root.childNodes.item(2) is nelem2
101 and root.childNodes[3] is nelem
102 and root.childNodes.item(3) is nelem
103 and nelem2.nextSibling is nelem
104 and nelem.previousSibling is nelem2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000105 and root.toxml() ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000106 "<doc><element/><foo/><bar/><element/></doc>"
107 , "testInsertBefore -- node properly placed in tree")
108 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000109
Collin Winterd28fcbc2007-03-28 23:34:06 +0000110 def _create_fragment_test_nodes(self):
111 dom = parseString("<doc/>")
112 orig = dom.createTextNode("original")
113 c1 = dom.createTextNode("foo")
114 c2 = dom.createTextNode("bar")
115 c3 = dom.createTextNode("bat")
116 dom.documentElement.appendChild(orig)
117 frag = dom.createDocumentFragment()
118 frag.appendChild(c1)
119 frag.appendChild(c2)
120 frag.appendChild(c3)
121 return dom, orig, c1, c2, c3, frag
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000122
Collin Winterd28fcbc2007-03-28 23:34:06 +0000123 def testInsertBeforeFragment(self):
124 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
125 dom.documentElement.insertBefore(frag, None)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000126 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000127 (orig, c1, c2, c3),
128 "insertBefore(<fragment>, None)")
129 frag.unlink()
130 dom.unlink()
Paul Prescod10d27662000-09-18 19:07:26 +0000131
Collin Winterd28fcbc2007-03-28 23:34:06 +0000132 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
133 dom.documentElement.insertBefore(frag, orig)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000134 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000135 (c1, c2, c3, orig),
136 "insertBefore(<fragment>, orig)")
137 frag.unlink()
138 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000139
Collin Winterd28fcbc2007-03-28 23:34:06 +0000140 def testAppendChild(self):
141 dom = parse(tstfile)
142 dom.documentElement.appendChild(dom.createComment(u"Hello"))
143 self.confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
144 self.confirm(dom.documentElement.childNodes[-1].data == "Hello")
145 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000146
Collin Winterd28fcbc2007-03-28 23:34:06 +0000147 def testAppendChildFragment(self):
148 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
149 dom.documentElement.appendChild(frag)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000150 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000151 (orig, c1, c2, c3),
152 "appendChild(<fragment>)")
153 frag.unlink()
154 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000155
Collin Winterd28fcbc2007-03-28 23:34:06 +0000156 def testReplaceChildFragment(self):
157 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
158 dom.documentElement.replaceChild(frag, orig)
159 orig.unlink()
160 self.confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
161 "replaceChild(<fragment>)")
162 frag.unlink()
163 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000164
Collin Winterd28fcbc2007-03-28 23:34:06 +0000165 def testLegalChildren(self):
166 dom = Document()
167 elem = dom.createElement('element')
168 text = dom.createTextNode('text')
169 self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000170
Collin Winterd28fcbc2007-03-28 23:34:06 +0000171 dom.appendChild(elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000172 self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000173 elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000174 self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000175 elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000176
Collin Winterd28fcbc2007-03-28 23:34:06 +0000177 nodemap = elem.attributes
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000178 self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000179 text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000180 self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000181 text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000182
Collin Winterd28fcbc2007-03-28 23:34:06 +0000183 elem.appendChild(text)
184 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000185
Collin Winterd28fcbc2007-03-28 23:34:06 +0000186 def testNamedNodeMapSetItem(self):
187 dom = Document()
188 elem = dom.createElement('element')
189 attrs = elem.attributes
190 attrs["foo"] = "bar"
191 a = attrs.item(0)
192 self.confirm(a.ownerDocument is dom,
193 "NamedNodeMap.__setitem__() sets ownerDocument")
194 self.confirm(a.ownerElement is elem,
195 "NamedNodeMap.__setitem__() sets ownerElement")
196 self.confirm(a.value == "bar",
197 "NamedNodeMap.__setitem__() sets value")
198 self.confirm(a.nodeValue == "bar",
199 "NamedNodeMap.__setitem__() sets nodeValue")
200 elem.unlink()
201 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000202
Collin Winterd28fcbc2007-03-28 23:34:06 +0000203 def testNonZero(self):
204 dom = parse(tstfile)
205 self.confirm(dom)# should not be zero
206 dom.appendChild(dom.createComment("foo"))
207 self.confirm(not dom.childNodes[-1].childNodes)
208 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000209
Collin Winterd28fcbc2007-03-28 23:34:06 +0000210 def testUnlink(self):
211 dom = parse(tstfile)
212 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000213
Collin Winterd28fcbc2007-03-28 23:34:06 +0000214 def testElement(self):
215 dom = Document()
216 dom.appendChild(dom.createElement("abc"))
217 self.confirm(dom.documentElement)
218 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000219
Collin Winterd28fcbc2007-03-28 23:34:06 +0000220 def testAAA(self):
221 dom = parseString("<abc/>")
222 el = dom.documentElement
223 el.setAttribute("spam", "jam2")
224 self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
225 a = el.getAttributeNode("spam")
226 self.confirm(a.ownerDocument is dom,
227 "setAttribute() sets ownerDocument")
228 self.confirm(a.ownerElement is dom.documentElement,
229 "setAttribute() sets ownerElement")
230 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000231
Collin Winterd28fcbc2007-03-28 23:34:06 +0000232 def testAAB(self):
233 dom = parseString("<abc/>")
234 el = dom.documentElement
235 el.setAttribute("spam", "jam")
236 el.setAttribute("spam", "jam2")
237 self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
238 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000239
Collin Winterd28fcbc2007-03-28 23:34:06 +0000240 def testAddAttr(self):
241 dom = Document()
242 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000243
Collin Winterd28fcbc2007-03-28 23:34:06 +0000244 child.setAttribute("def", "ghi")
245 self.confirm(child.getAttribute("def") == "ghi")
246 self.confirm(child.attributes["def"].value == "ghi")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000247
Collin Winterd28fcbc2007-03-28 23:34:06 +0000248 child.setAttribute("jkl", "mno")
249 self.confirm(child.getAttribute("jkl") == "mno")
250 self.confirm(child.attributes["jkl"].value == "mno")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000251
Collin Winterd28fcbc2007-03-28 23:34:06 +0000252 self.confirm(len(child.attributes) == 2)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000253
Collin Winterd28fcbc2007-03-28 23:34:06 +0000254 child.setAttribute("def", "newval")
255 self.confirm(child.getAttribute("def") == "newval")
256 self.confirm(child.attributes["def"].value == "newval")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000257
Collin Winterd28fcbc2007-03-28 23:34:06 +0000258 self.confirm(len(child.attributes) == 2)
259 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000260
Collin Winterd28fcbc2007-03-28 23:34:06 +0000261 def testDeleteAttr(self):
262 dom = Document()
263 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000264
Collin Winterd28fcbc2007-03-28 23:34:06 +0000265 self.confirm(len(child.attributes) == 0)
266 child.setAttribute("def", "ghi")
267 self.confirm(len(child.attributes) == 1)
268 del child.attributes["def"]
269 self.confirm(len(child.attributes) == 0)
270 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000271
Collin Winterd28fcbc2007-03-28 23:34:06 +0000272 def testRemoveAttr(self):
273 dom = Document()
274 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000275
Collin Winterd28fcbc2007-03-28 23:34:06 +0000276 child.setAttribute("def", "ghi")
277 self.confirm(len(child.attributes) == 1)
278 child.removeAttribute("def")
279 self.confirm(len(child.attributes) == 0)
280 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000281
Collin Winterd28fcbc2007-03-28 23:34:06 +0000282 def testRemoveAttrNS(self):
283 dom = Document()
284 child = dom.appendChild(
285 dom.createElementNS("http://www.python.org", "python:abc"))
286 child.setAttributeNS("http://www.w3.org", "xmlns:python",
287 "http://www.python.org")
288 child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
289 self.confirm(len(child.attributes) == 2)
290 child.removeAttributeNS("http://www.python.org", "abcattr")
291 self.confirm(len(child.attributes) == 1)
292 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000293
Collin Winterd28fcbc2007-03-28 23:34:06 +0000294 def testRemoveAttributeNode(self):
295 dom = Document()
296 child = dom.appendChild(dom.createElement("foo"))
297 child.setAttribute("spam", "jam")
298 self.confirm(len(child.attributes) == 1)
299 node = child.getAttributeNode("spam")
300 child.removeAttributeNode(node)
301 self.confirm(len(child.attributes) == 0
302 and child.getAttributeNode("spam") is None)
303 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000304
Collin Winterd28fcbc2007-03-28 23:34:06 +0000305 def testChangeAttr(self):
306 dom = parseString("<abc/>")
307 el = dom.documentElement
308 el.setAttribute("spam", "jam")
309 self.confirm(len(el.attributes) == 1)
310 el.setAttribute("spam", "bam")
311 # Set this attribute to be an ID and make sure that doesn't change
312 # when changing the value:
313 el.setIdAttribute("spam")
314 self.confirm(len(el.attributes) == 1
315 and el.attributes["spam"].value == "bam"
316 and el.attributes["spam"].nodeValue == "bam"
317 and el.getAttribute("spam") == "bam"
318 and el.getAttributeNode("spam").isId)
319 el.attributes["spam"] = "ham"
320 self.confirm(len(el.attributes) == 1
321 and el.attributes["spam"].value == "ham"
322 and el.attributes["spam"].nodeValue == "ham"
323 and el.getAttribute("spam") == "ham"
324 and el.attributes["spam"].isId)
325 el.setAttribute("spam2", "bam")
326 self.confirm(len(el.attributes) == 2
327 and el.attributes["spam"].value == "ham"
328 and el.attributes["spam"].nodeValue == "ham"
329 and el.getAttribute("spam") == "ham"
330 and el.attributes["spam2"].value == "bam"
331 and el.attributes["spam2"].nodeValue == "bam"
332 and el.getAttribute("spam2") == "bam")
333 el.attributes["spam2"] = "bam2"
334 self.confirm(len(el.attributes) == 2
335 and el.attributes["spam"].value == "ham"
336 and el.attributes["spam"].nodeValue == "ham"
337 and el.getAttribute("spam") == "ham"
338 and el.attributes["spam2"].value == "bam2"
339 and el.attributes["spam2"].nodeValue == "bam2"
340 and el.getAttribute("spam2") == "bam2")
341 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000342
Collin Winterd28fcbc2007-03-28 23:34:06 +0000343 def testGetAttrList(self):
344 pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000345
Collin Winterd28fcbc2007-03-28 23:34:06 +0000346 def testGetAttrValues(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000347
Collin Winterd28fcbc2007-03-28 23:34:06 +0000348 def testGetAttrLength(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000349
Collin Winterd28fcbc2007-03-28 23:34:06 +0000350 def testGetAttribute(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000351
Collin Winterd28fcbc2007-03-28 23:34:06 +0000352 def testGetAttributeNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000353
Collin Winterd28fcbc2007-03-28 23:34:06 +0000354 def testGetAttributeNode(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000355
Collin Winterd28fcbc2007-03-28 23:34:06 +0000356 def testGetElementsByTagNameNS(self):
357 d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
358 <minidom:myelem/>
359 </foo>"""
360 dom = parseString(d)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000361 elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom",
Collin Winterd28fcbc2007-03-28 23:34:06 +0000362 "myelem")
363 self.confirm(len(elems) == 1
364 and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"
365 and elems[0].localName == "myelem"
366 and elems[0].prefix == "minidom"
367 and elems[0].tagName == "minidom:myelem"
368 and elems[0].nodeName == "minidom:myelem")
369 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000370
371 def get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000372 lname):
373 nodelist = doc.getElementsByTagNameNS(nsuri, lname)
374 self.confirm(len(nodelist) == 0)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000375
Collin Winterd28fcbc2007-03-28 23:34:06 +0000376 def testGetEmptyNodeListFromElementsByTagNameNS(self):
377 doc = parseString('<doc/>')
378 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
379 doc, 'http://xml.python.org/namespaces/a', 'localname')
380 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
381 doc, '*', 'splat')
382 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
383 doc, 'http://xml.python.org/namespaces/a', '*')
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000384
Collin Winterd28fcbc2007-03-28 23:34:06 +0000385 doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
386 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
387 doc, "http://xml.python.org/splat", "not-there")
388 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
389 doc, "*", "not-there")
390 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
391 doc, "http://somewhere.else.net/not-there", "e")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000392
Collin Winterd28fcbc2007-03-28 23:34:06 +0000393 def testElementReprAndStr(self):
394 dom = Document()
395 el = dom.appendChild(dom.createElement("abc"))
396 string1 = repr(el)
397 string2 = str(el)
398 self.confirm(string1 == string2)
399 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000400
Collin Winterd28fcbc2007-03-28 23:34:06 +0000401 def testElementReprAndStrUnicode(self):
402 dom = Document()
403 el = dom.appendChild(dom.createElement(u"abc"))
404 string1 = repr(el)
405 string2 = str(el)
406 self.confirm(string1 == string2)
407 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000408
Collin Winterd28fcbc2007-03-28 23:34:06 +0000409 def testElementReprAndStrUnicodeNS(self):
410 dom = Document()
411 el = dom.appendChild(
412 dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
413 string1 = repr(el)
414 string2 = str(el)
415 self.confirm(string1 == string2)
Ezio Melotti187f93d2010-03-17 14:22:34 +0000416 self.confirm("slash:abc" in string1)
Collin Winterd28fcbc2007-03-28 23:34:06 +0000417 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000418
Collin Winterd28fcbc2007-03-28 23:34:06 +0000419 def testAttributeRepr(self):
420 dom = Document()
421 el = dom.appendChild(dom.createElement(u"abc"))
422 node = el.setAttribute("abc", "def")
423 self.confirm(str(node) == repr(node))
424 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000425
Collin Winterd28fcbc2007-03-28 23:34:06 +0000426 def testTextNodeRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000427
Collin Winterd28fcbc2007-03-28 23:34:06 +0000428 def testWriteXML(self):
429 str = '<?xml version="1.0" ?><a b="c"/>'
430 dom = parseString(str)
431 domstr = dom.toxml()
432 dom.unlink()
433 self.confirm(str == domstr)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000434
Collin Winterd28fcbc2007-03-28 23:34:06 +0000435 def testAltNewline(self):
436 str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
437 dom = parseString(str)
438 domstr = dom.toprettyxml(newl="\r\n")
439 dom.unlink()
440 self.confirm(domstr == str.replace("\n", "\r\n"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000441
Éric Araujo2710bc42011-10-05 02:35:09 +0200442 def test_toprettyxml_preserves_content_of_text_node(self):
R David Murrayc8faf9b2011-10-01 16:49:25 -0400443 str = '<A>B</A>'
444 dom = parseString(str)
445 dom2 = parseString(dom.toprettyxml())
446 self.assertEqual(dom.childNodes[0].childNodes[0].toxml(),
447 dom2.childNodes[0].childNodes[0].toxml())
448
Collin Winterd28fcbc2007-03-28 23:34:06 +0000449 def testProcessingInstruction(self):
450 dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
451 pi = dom.documentElement.firstChild
452 self.confirm(pi.target == "mypi"
453 and pi.data == "data \t\n "
454 and pi.nodeName == "mypi"
455 and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
456 and pi.attributes is None
457 and not pi.hasChildNodes()
458 and len(pi.childNodes) == 0
459 and pi.firstChild is None
460 and pi.lastChild is None
461 and pi.localName is None
462 and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000463
Collin Winterd28fcbc2007-03-28 23:34:06 +0000464 def testProcessingInstructionRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000465
Collin Winterd28fcbc2007-03-28 23:34:06 +0000466 def testTextRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000467
Collin Winterd28fcbc2007-03-28 23:34:06 +0000468 def testWriteText(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000469
Collin Winterd28fcbc2007-03-28 23:34:06 +0000470 def testDocumentElement(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000471
Collin Winterd28fcbc2007-03-28 23:34:06 +0000472 def testTooManyDocumentElements(self):
473 doc = parseString("<doc/>")
474 elem = doc.createElement("extra")
475 # Should raise an exception when adding an extra document element.
476 self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem)
477 elem.unlink()
478 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000479
Collin Winterd28fcbc2007-03-28 23:34:06 +0000480 def testCreateElementNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000481
Collin Winterd28fcbc2007-03-28 23:34:06 +0000482 def testCreateAttributeNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000483
Collin Winterd28fcbc2007-03-28 23:34:06 +0000484 def testParse(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000485
Collin Winterd28fcbc2007-03-28 23:34:06 +0000486 def testParseString(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000487
Collin Winterd28fcbc2007-03-28 23:34:06 +0000488 def testComment(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000489
Collin Winterd28fcbc2007-03-28 23:34:06 +0000490 def testAttrListItem(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000491
Collin Winterd28fcbc2007-03-28 23:34:06 +0000492 def testAttrListItems(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000493
Collin Winterd28fcbc2007-03-28 23:34:06 +0000494 def testAttrListItemNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000495
Collin Winterd28fcbc2007-03-28 23:34:06 +0000496 def testAttrListKeys(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000497
Collin Winterd28fcbc2007-03-28 23:34:06 +0000498 def testAttrListKeysNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000499
Collin Winterd28fcbc2007-03-28 23:34:06 +0000500 def testRemoveNamedItem(self):
501 doc = parseString("<doc a=''/>")
502 e = doc.documentElement
503 attrs = e.attributes
504 a1 = e.getAttributeNode("a")
505 a2 = attrs.removeNamedItem("a")
506 self.confirm(a1.isSameNode(a2))
507 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000508
Collin Winterd28fcbc2007-03-28 23:34:06 +0000509 def testRemoveNamedItemNS(self):
510 doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
511 e = doc.documentElement
512 attrs = e.attributes
513 a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
514 a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
515 self.confirm(a1.isSameNode(a2))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000516 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000517 "http://xml.python.org/", "b")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000518
Collin Winterd28fcbc2007-03-28 23:34:06 +0000519 def testAttrListValues(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000520
Collin Winterd28fcbc2007-03-28 23:34:06 +0000521 def testAttrListLength(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000522
Collin Winterd28fcbc2007-03-28 23:34:06 +0000523 def testAttrList__getitem__(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000524
Collin Winterd28fcbc2007-03-28 23:34:06 +0000525 def testAttrList__setitem__(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000526
Collin Winterd28fcbc2007-03-28 23:34:06 +0000527 def testSetAttrValueandNodeValue(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000528
Collin Winterd28fcbc2007-03-28 23:34:06 +0000529 def testParseElement(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000530
Collin Winterd28fcbc2007-03-28 23:34:06 +0000531 def testParseAttributes(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000532
Collin Winterd28fcbc2007-03-28 23:34:06 +0000533 def testParseElementNamespaces(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000534
Collin Winterd28fcbc2007-03-28 23:34:06 +0000535 def testParseAttributeNamespaces(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000536
Collin Winterd28fcbc2007-03-28 23:34:06 +0000537 def testParseProcessingInstructions(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000538
Collin Winterd28fcbc2007-03-28 23:34:06 +0000539 def testChildNodes(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000540
Collin Winterd28fcbc2007-03-28 23:34:06 +0000541 def testFirstChild(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000542
Collin Winterd28fcbc2007-03-28 23:34:06 +0000543 def testHasChildNodes(self): pass
544
545 def _testCloneElementCopiesAttributes(self, e1, e2, test):
546 attrs1 = e1.attributes
547 attrs2 = e2.attributes
548 keys1 = attrs1.keys()
549 keys2 = attrs2.keys()
550 keys1.sort()
551 keys2.sort()
552 self.confirm(keys1 == keys2, "clone of element has same attribute keys")
553 for i in range(len(keys1)):
554 a1 = attrs1.item(i)
555 a2 = attrs2.item(i)
556 self.confirm(a1 is not a2
557 and a1.value == a2.value
558 and a1.nodeValue == a2.nodeValue
559 and a1.namespaceURI == a2.namespaceURI
560 and a1.localName == a2.localName
561 , "clone of attribute node has proper attribute values")
562 self.confirm(a2.ownerElement is e2,
563 "clone of attribute node correctly owned")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000564
Collin Winterd28fcbc2007-03-28 23:34:06 +0000565 def _setupCloneElement(self, deep):
566 dom = parseString("<doc attr='value'><foo/></doc>")
567 root = dom.documentElement
568 clone = root.cloneNode(deep)
569 self._testCloneElementCopiesAttributes(
570 root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
571 # mutilate the original so shared data is detected
572 root.tagName = root.nodeName = "MODIFIED"
573 root.setAttribute("attr", "NEW VALUE")
574 root.setAttribute("added", "VALUE")
575 return dom, clone
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000576
Collin Winterd28fcbc2007-03-28 23:34:06 +0000577 def testCloneElementShallow(self):
578 dom, clone = self._setupCloneElement(0)
579 self.confirm(len(clone.childNodes) == 0
580 and clone.childNodes.length == 0
581 and clone.parentNode is None
582 and clone.toxml() == '<doc attr="value"/>'
583 , "testCloneElementShallow")
584 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000585
Collin Winterd28fcbc2007-03-28 23:34:06 +0000586 def testCloneElementDeep(self):
587 dom, clone = self._setupCloneElement(1)
588 self.confirm(len(clone.childNodes) == 1
589 and clone.childNodes.length == 1
590 and clone.parentNode is None
591 and clone.toxml() == '<doc attr="value"><foo/></doc>'
592 , "testCloneElementDeep")
593 dom.unlink()
594
595 def testCloneDocumentShallow(self):
596 doc = parseString("<?xml version='1.0'?>\n"
597 "<!-- comment -->"
598 "<!DOCTYPE doc [\n"
599 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
600 "]>\n"
601 "<doc attr='value'/>")
602 doc2 = doc.cloneNode(0)
603 self.confirm(doc2 is None,
604 "testCloneDocumentShallow:"
605 " shallow cloning of documents makes no sense!")
606
607 def testCloneDocumentDeep(self):
608 doc = parseString("<?xml version='1.0'?>\n"
609 "<!-- comment -->"
610 "<!DOCTYPE doc [\n"
611 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
612 "]>\n"
613 "<doc attr='value'/>")
614 doc2 = doc.cloneNode(1)
615 self.confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
616 "testCloneDocumentDeep: document objects not distinct")
617 self.confirm(len(doc.childNodes) == len(doc2.childNodes),
618 "testCloneDocumentDeep: wrong number of Document children")
619 self.confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
620 "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
621 self.confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
622 "testCloneDocumentDeep: documentElement owner is not new document")
623 self.confirm(not doc.documentElement.isSameNode(doc2.documentElement),
624 "testCloneDocumentDeep: documentElement should not be shared")
625 if doc.doctype is not None:
626 # check the doctype iff the original DOM maintained it
627 self.confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
628 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
629 self.confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
630 self.confirm(not doc.doctype.isSameNode(doc2.doctype))
631
632 def testCloneDocumentTypeDeepOk(self):
633 doctype = create_nonempty_doctype()
634 clone = doctype.cloneNode(1)
635 self.confirm(clone is not None
636 and clone.nodeName == doctype.nodeName
637 and clone.name == doctype.name
638 and clone.publicId == doctype.publicId
639 and clone.systemId == doctype.systemId
640 and len(clone.entities) == len(doctype.entities)
641 and clone.entities.item(len(clone.entities)) is None
642 and len(clone.notations) == len(doctype.notations)
643 and clone.notations.item(len(clone.notations)) is None
644 and len(clone.childNodes) == 0)
645 for i in range(len(doctype.entities)):
646 se = doctype.entities.item(i)
647 ce = clone.entities.item(i)
648 self.confirm((not se.isSameNode(ce))
649 and (not ce.isSameNode(se))
650 and ce.nodeName == se.nodeName
651 and ce.notationName == se.notationName
652 and ce.publicId == se.publicId
653 and ce.systemId == se.systemId
654 and ce.encoding == se.encoding
655 and ce.actualEncoding == se.actualEncoding
656 and ce.version == se.version)
657 for i in range(len(doctype.notations)):
658 sn = doctype.notations.item(i)
659 cn = clone.notations.item(i)
660 self.confirm((not sn.isSameNode(cn))
661 and (not cn.isSameNode(sn))
662 and cn.nodeName == sn.nodeName
663 and cn.publicId == sn.publicId
664 and cn.systemId == sn.systemId)
665
666 def testCloneDocumentTypeDeepNotOk(self):
667 doc = create_doc_with_doctype()
668 clone = doc.doctype.cloneNode(1)
669 self.confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
670
671 def testCloneDocumentTypeShallowOk(self):
672 doctype = create_nonempty_doctype()
673 clone = doctype.cloneNode(0)
674 self.confirm(clone is not None
675 and clone.nodeName == doctype.nodeName
676 and clone.name == doctype.name
677 and clone.publicId == doctype.publicId
678 and clone.systemId == doctype.systemId
679 and len(clone.entities) == 0
680 and clone.entities.item(0) is None
681 and len(clone.notations) == 0
682 and clone.notations.item(0) is None
683 and len(clone.childNodes) == 0)
684
685 def testCloneDocumentTypeShallowNotOk(self):
686 doc = create_doc_with_doctype()
687 clone = doc.doctype.cloneNode(0)
688 self.confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
689
690 def check_import_document(self, deep, testName):
691 doc1 = parseString("<doc/>")
692 doc2 = parseString("<doc/>")
693 self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000694
Collin Winterd28fcbc2007-03-28 23:34:06 +0000695 def testImportDocumentShallow(self):
696 self.check_import_document(0, "testImportDocumentShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000697
Collin Winterd28fcbc2007-03-28 23:34:06 +0000698 def testImportDocumentDeep(self):
699 self.check_import_document(1, "testImportDocumentDeep")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000700
Collin Winterd28fcbc2007-03-28 23:34:06 +0000701 def testImportDocumentTypeShallow(self):
702 src = create_doc_with_doctype()
703 target = create_doc_without_doctype()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000704 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000705 src.doctype, 0)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000706
Collin Winterd28fcbc2007-03-28 23:34:06 +0000707 def testImportDocumentTypeDeep(self):
708 src = create_doc_with_doctype()
709 target = create_doc_without_doctype()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000710 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000711 src.doctype, 1)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000712
Collin Winterd28fcbc2007-03-28 23:34:06 +0000713 # Testing attribute clones uses a helper, and should always be deep,
714 # even if the argument to cloneNode is false.
715 def check_clone_attribute(self, deep, testName):
716 doc = parseString("<doc attr='value'/>")
717 attr = doc.documentElement.getAttributeNode("attr")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000718 self.assertNotEqual(attr, None)
Collin Winterd28fcbc2007-03-28 23:34:06 +0000719 clone = attr.cloneNode(deep)
720 self.confirm(not clone.isSameNode(attr))
721 self.confirm(not attr.isSameNode(clone))
722 self.confirm(clone.ownerElement is None,
723 testName + ": ownerElement should be None")
724 self.confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
725 testName + ": ownerDocument does not match")
726 self.confirm(clone.specified,
727 testName + ": cloned attribute must have specified == True")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000728
Collin Winterd28fcbc2007-03-28 23:34:06 +0000729 def testCloneAttributeShallow(self):
730 self.check_clone_attribute(0, "testCloneAttributeShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000731
Collin Winterd28fcbc2007-03-28 23:34:06 +0000732 def testCloneAttributeDeep(self):
733 self.check_clone_attribute(1, "testCloneAttributeDeep")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000734
Collin Winterd28fcbc2007-03-28 23:34:06 +0000735 def check_clone_pi(self, deep, testName):
736 doc = parseString("<?target data?><doc/>")
737 pi = doc.firstChild
Ezio Melotti2623a372010-11-21 13:34:58 +0000738 self.assertEqual(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE)
Collin Winterd28fcbc2007-03-28 23:34:06 +0000739 clone = pi.cloneNode(deep)
740 self.confirm(clone.target == pi.target
741 and clone.data == pi.data)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000742
Collin Winterd28fcbc2007-03-28 23:34:06 +0000743 def testClonePIShallow(self):
744 self.check_clone_pi(0, "testClonePIShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000745
Collin Winterd28fcbc2007-03-28 23:34:06 +0000746 def testClonePIDeep(self):
747 self.check_clone_pi(1, "testClonePIDeep")
748
749 def testNormalize(self):
750 doc = parseString("<doc/>")
751 root = doc.documentElement
752 root.appendChild(doc.createTextNode("first"))
753 root.appendChild(doc.createTextNode("second"))
754 self.confirm(len(root.childNodes) == 2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000755 and root.childNodes.length == 2,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000756 "testNormalize -- preparation")
757 doc.normalize()
758 self.confirm(len(root.childNodes) == 1
759 and root.childNodes.length == 1
760 and root.firstChild is root.lastChild
761 and root.firstChild.data == "firstsecond"
762 , "testNormalize -- result")
763 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000764
Collin Winterd28fcbc2007-03-28 23:34:06 +0000765 doc = parseString("<doc/>")
766 root = doc.documentElement
767 root.appendChild(doc.createTextNode(""))
768 doc.normalize()
769 self.confirm(len(root.childNodes) == 0
770 and root.childNodes.length == 0,
771 "testNormalize -- single empty node removed")
772 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000773
R. David Murray0374a822009-04-09 21:54:50 +0000774 def testNormalizeCombineAndNextSibling(self):
775 doc = parseString("<doc/>")
776 root = doc.documentElement
777 root.appendChild(doc.createTextNode("first"))
778 root.appendChild(doc.createTextNode("second"))
779 root.appendChild(doc.createElement("i"))
780 self.confirm(len(root.childNodes) == 3
781 and root.childNodes.length == 3,
782 "testNormalizeCombineAndNextSibling -- preparation")
783 doc.normalize()
784 self.confirm(len(root.childNodes) == 2
785 and root.childNodes.length == 2
786 and root.firstChild.data == "firstsecond"
787 and root.firstChild is not root.lastChild
788 and root.firstChild.nextSibling is root.lastChild
789 and root.firstChild.previousSibling is None
790 and root.lastChild.previousSibling is root.firstChild
791 and root.lastChild.nextSibling is None
792 , "testNormalizeCombinedAndNextSibling -- result")
793 doc.unlink()
794
795 def testNormalizeDeleteWithPrevSibling(self):
796 doc = parseString("<doc/>")
797 root = doc.documentElement
798 root.appendChild(doc.createTextNode("first"))
799 root.appendChild(doc.createTextNode(""))
800 self.confirm(len(root.childNodes) == 2
801 and root.childNodes.length == 2,
802 "testNormalizeDeleteWithPrevSibling -- preparation")
803 doc.normalize()
804 self.confirm(len(root.childNodes) == 1
805 and root.childNodes.length == 1
806 and root.firstChild.data == "first"
807 and root.firstChild is root.lastChild
808 and root.firstChild.nextSibling is None
809 and root.firstChild.previousSibling is None
810 , "testNormalizeDeleteWithPrevSibling -- result")
811 doc.unlink()
812
813 def testNormalizeDeleteWithNextSibling(self):
814 doc = parseString("<doc/>")
815 root = doc.documentElement
816 root.appendChild(doc.createTextNode(""))
817 root.appendChild(doc.createTextNode("second"))
818 self.confirm(len(root.childNodes) == 2
819 and root.childNodes.length == 2,
820 "testNormalizeDeleteWithNextSibling -- preparation")
821 doc.normalize()
822 self.confirm(len(root.childNodes) == 1
823 and root.childNodes.length == 1
824 and root.firstChild.data == "second"
825 and root.firstChild is root.lastChild
826 and root.firstChild.nextSibling is None
827 and root.firstChild.previousSibling is None
828 , "testNormalizeDeleteWithNextSibling -- result")
829 doc.unlink()
830
831 def testNormalizeDeleteWithTwoNonTextSiblings(self):
832 doc = parseString("<doc/>")
833 root = doc.documentElement
834 root.appendChild(doc.createElement("i"))
835 root.appendChild(doc.createTextNode(""))
836 root.appendChild(doc.createElement("i"))
837 self.confirm(len(root.childNodes) == 3
838 and root.childNodes.length == 3,
839 "testNormalizeDeleteWithTwoSiblings -- preparation")
840 doc.normalize()
841 self.confirm(len(root.childNodes) == 2
842 and root.childNodes.length == 2
843 and root.firstChild is not root.lastChild
844 and root.firstChild.nextSibling is root.lastChild
845 and root.firstChild.previousSibling is None
846 and root.lastChild.previousSibling is root.firstChild
847 and root.lastChild.nextSibling is None
848 , "testNormalizeDeleteWithTwoSiblings -- result")
849 doc.unlink()
850
851 def testNormalizeDeleteAndCombine(self):
852 doc = parseString("<doc/>")
853 root = doc.documentElement
854 root.appendChild(doc.createTextNode(""))
855 root.appendChild(doc.createTextNode("second"))
856 root.appendChild(doc.createTextNode(""))
857 root.appendChild(doc.createTextNode("fourth"))
858 root.appendChild(doc.createTextNode(""))
859 self.confirm(len(root.childNodes) == 5
860 and root.childNodes.length == 5,
861 "testNormalizeDeleteAndCombine -- preparation")
862 doc.normalize()
863 self.confirm(len(root.childNodes) == 1
864 and root.childNodes.length == 1
865 and root.firstChild is root.lastChild
866 and root.firstChild.data == "secondfourth"
867 and root.firstChild.previousSibling is None
868 and root.firstChild.nextSibling is None
869 , "testNormalizeDeleteAndCombine -- result")
870 doc.unlink()
871
872 def testNormalizeRecursion(self):
873 doc = parseString("<doc>"
874 "<o>"
875 "<i/>"
876 "t"
877 #
878 #x
879 "</o>"
880 "<o>"
881 "<o>"
882 "t2"
883 #x2
884 "</o>"
885 "t3"
886 #x3
887 "</o>"
888 #
889 "</doc>")
890 root = doc.documentElement
891 root.childNodes[0].appendChild(doc.createTextNode(""))
892 root.childNodes[0].appendChild(doc.createTextNode("x"))
893 root.childNodes[1].childNodes[0].appendChild(doc.createTextNode("x2"))
894 root.childNodes[1].appendChild(doc.createTextNode("x3"))
895 root.appendChild(doc.createTextNode(""))
896 self.confirm(len(root.childNodes) == 3
897 and root.childNodes.length == 3
898 and len(root.childNodes[0].childNodes) == 4
899 and root.childNodes[0].childNodes.length == 4
900 and len(root.childNodes[1].childNodes) == 3
901 and root.childNodes[1].childNodes.length == 3
902 and len(root.childNodes[1].childNodes[0].childNodes) == 2
903 and root.childNodes[1].childNodes[0].childNodes.length == 2
904 , "testNormalize2 -- preparation")
905 doc.normalize()
906 self.confirm(len(root.childNodes) == 2
907 and root.childNodes.length == 2
908 and len(root.childNodes[0].childNodes) == 2
909 and root.childNodes[0].childNodes.length == 2
910 and len(root.childNodes[1].childNodes) == 2
911 and root.childNodes[1].childNodes.length == 2
912 and len(root.childNodes[1].childNodes[0].childNodes) == 1
913 and root.childNodes[1].childNodes[0].childNodes.length == 1
914 , "testNormalize2 -- childNodes lengths")
915 self.confirm(root.childNodes[0].childNodes[1].data == "tx"
916 and root.childNodes[1].childNodes[0].childNodes[0].data == "t2x2"
917 and root.childNodes[1].childNodes[1].data == "t3x3"
918 , "testNormalize2 -- joined text fields")
919 self.confirm(root.childNodes[0].childNodes[1].nextSibling is None
920 and root.childNodes[0].childNodes[1].previousSibling
921 is root.childNodes[0].childNodes[0]
922 and root.childNodes[0].childNodes[0].previousSibling is None
923 and root.childNodes[0].childNodes[0].nextSibling
924 is root.childNodes[0].childNodes[1]
925 and root.childNodes[1].childNodes[1].nextSibling is None
926 and root.childNodes[1].childNodes[1].previousSibling
927 is root.childNodes[1].childNodes[0]
928 and root.childNodes[1].childNodes[0].previousSibling is None
929 and root.childNodes[1].childNodes[0].nextSibling
930 is root.childNodes[1].childNodes[1]
931 , "testNormalize2 -- sibling pointers")
932 doc.unlink()
933
934
Andrew M. Kuchling53f94d02010-07-25 23:49:57 +0000935 def testBug0777884(self):
936 doc = parseString("<o>text</o>")
937 text = doc.documentElement.childNodes[0]
Ezio Melotti2623a372010-11-21 13:34:58 +0000938 self.assertEqual(text.nodeType, Node.TEXT_NODE)
Andrew M. Kuchling53f94d02010-07-25 23:49:57 +0000939 # Should run quietly, doing nothing.
940 text.normalize()
941 doc.unlink()
942
Andrew M. Kuchling19aff0c2008-02-23 17:10:46 +0000943 def testBug1433694(self):
944 doc = parseString("<o><i/>t</o>")
945 node = doc.documentElement
946 node.childNodes[1].nodeValue = ""
947 node.normalize()
Florent Xiclunabc27c6a2010-03-19 18:34:55 +0000948 self.confirm(node.childNodes[-1].nextSibling is None,
Andrew M. Kuchling19aff0c2008-02-23 17:10:46 +0000949 "Final child's .nextSibling should be None")
950
Collin Winterd28fcbc2007-03-28 23:34:06 +0000951 def testSiblings(self):
952 doc = parseString("<doc><?pi?>text?<elm/></doc>")
953 root = doc.documentElement
954 (pi, text, elm) = root.childNodes
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000955
Collin Winterd28fcbc2007-03-28 23:34:06 +0000956 self.confirm(pi.nextSibling is text and
957 pi.previousSibling is None and
958 text.nextSibling is elm and
959 text.previousSibling is pi and
960 elm.nextSibling is None and
961 elm.previousSibling is text, "testSiblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000962
Collin Winterd28fcbc2007-03-28 23:34:06 +0000963 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000964
Collin Winterd28fcbc2007-03-28 23:34:06 +0000965 def testParents(self):
966 doc = parseString(
967 "<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
968 root = doc.documentElement
969 elm1 = root.childNodes[0]
970 (elm2a, elm2b) = elm1.childNodes
971 elm3 = elm2b.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000972
Collin Winterd28fcbc2007-03-28 23:34:06 +0000973 self.confirm(root.parentNode is doc and
974 elm1.parentNode is root and
975 elm2a.parentNode is elm1 and
976 elm2b.parentNode is elm1 and
977 elm3.parentNode is elm2b, "testParents")
978 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000979
Collin Winterd28fcbc2007-03-28 23:34:06 +0000980 def testNodeListItem(self):
981 doc = parseString("<doc><e/><e/></doc>")
982 children = doc.childNodes
983 docelem = children[0]
984 self.confirm(children[0] is children.item(0)
985 and children.item(1) is None
986 and docelem.childNodes.item(0) is docelem.childNodes[0]
987 and docelem.childNodes.item(1) is docelem.childNodes[1]
988 and docelem.childNodes.item(0).childNodes.item(0) is None,
989 "test NodeList.item()")
990 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000991
Collin Winterd28fcbc2007-03-28 23:34:06 +0000992 def testSAX2DOM(self):
993 from xml.dom import pulldom
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000994
Collin Winterd28fcbc2007-03-28 23:34:06 +0000995 sax2dom = pulldom.SAX2DOM()
996 sax2dom.startDocument()
997 sax2dom.startElement("doc", {})
998 sax2dom.characters("text")
999 sax2dom.startElement("subelm", {})
1000 sax2dom.characters("text")
1001 sax2dom.endElement("subelm")
1002 sax2dom.characters("text")
1003 sax2dom.endElement("doc")
1004 sax2dom.endDocument()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001005
Collin Winterd28fcbc2007-03-28 23:34:06 +00001006 doc = sax2dom.document
1007 root = doc.documentElement
1008 (text1, elm1, text2) = root.childNodes
1009 text3 = elm1.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001010
Collin Winterd28fcbc2007-03-28 23:34:06 +00001011 self.confirm(text1.previousSibling is None and
1012 text1.nextSibling is elm1 and
1013 elm1.previousSibling is text1 and
1014 elm1.nextSibling is text2 and
1015 text2.previousSibling is elm1 and
1016 text2.nextSibling is None and
1017 text3.previousSibling is None and
1018 text3.nextSibling is None, "testSAX2DOM - siblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001019
Collin Winterd28fcbc2007-03-28 23:34:06 +00001020 self.confirm(root.parentNode is doc and
1021 text1.parentNode is root and
1022 elm1.parentNode is root and
1023 text2.parentNode is root and
1024 text3.parentNode is elm1, "testSAX2DOM - parents")
1025 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001026
Collin Winterd28fcbc2007-03-28 23:34:06 +00001027 def testEncodings(self):
1028 doc = parseString('<foo>&#x20ac;</foo>')
1029 self.confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001030 and doc.toxml('utf-8') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +00001031 '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001032 and doc.toxml('iso-8859-15') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +00001033 '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
1034 "testEncodings - encoding EURO SIGN")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001035
1036 # Verify that character decoding errors throw exceptions instead
Collin Winterd28fcbc2007-03-28 23:34:06 +00001037 # of crashing
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001038 self.assertRaises(UnicodeDecodeError, parseString,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001039 '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001040
Collin Winterd28fcbc2007-03-28 23:34:06 +00001041 doc.unlink()
1042
1043 class UserDataHandler:
1044 called = 0
1045 def handle(self, operation, key, data, src, dst):
1046 dst.setUserData(key, data + 1, self)
1047 src.setUserData(key, None, None)
1048 self.called = 1
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001049
Collin Winterd28fcbc2007-03-28 23:34:06 +00001050 def testUserData(self):
1051 dom = Document()
1052 n = dom.createElement('e')
1053 self.confirm(n.getUserData("foo") is None)
1054 n.setUserData("foo", None, None)
1055 self.confirm(n.getUserData("foo") is None)
1056 n.setUserData("foo", 12, 12)
1057 n.setUserData("bar", 13, 13)
1058 self.confirm(n.getUserData("foo") == 12)
1059 self.confirm(n.getUserData("bar") == 13)
1060 n.setUserData("foo", None, None)
1061 self.confirm(n.getUserData("foo") is None)
1062 self.confirm(n.getUserData("bar") == 13)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001063
Collin Winterd28fcbc2007-03-28 23:34:06 +00001064 handler = self.UserDataHandler()
1065 n.setUserData("bar", 12, handler)
1066 c = n.cloneNode(1)
1067 self.confirm(handler.called
1068 and n.getUserData("bar") is None
1069 and c.getUserData("bar") == 13)
1070 n.unlink()
1071 c.unlink()
1072 dom.unlink()
1073
1074 def checkRenameNodeSharedConstraints(self, doc, node):
1075 # Make sure illegal NS usage is detected:
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001076 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001077 "http://xml.python.org/ns", "xmlns:foo")
1078 doc2 = parseString("<doc/>")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001079 self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001080 xml.dom.EMPTY_NAMESPACE, "foo")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001081
Collin Winterd28fcbc2007-03-28 23:34:06 +00001082 def testRenameAttribute(self):
1083 doc = parseString("<doc a='v'/>")
1084 elem = doc.documentElement
1085 attrmap = elem.attributes
1086 attr = elem.attributes['a']
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001087
Collin Winterd28fcbc2007-03-28 23:34:06 +00001088 # Simple renaming
1089 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
1090 self.confirm(attr.name == "b"
1091 and attr.nodeName == "b"
1092 and attr.localName is None
1093 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
1094 and attr.prefix is None
1095 and attr.value == "v"
1096 and elem.getAttributeNode("a") is None
1097 and elem.getAttributeNode("b").isSameNode(attr)
1098 and attrmap["b"].isSameNode(attr)
1099 and attr.ownerDocument.isSameNode(doc)
1100 and attr.ownerElement.isSameNode(elem))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001101
Collin Winterd28fcbc2007-03-28 23:34:06 +00001102 # Rename to have a namespace, no prefix
1103 attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
1104 self.confirm(attr.name == "c"
1105 and attr.nodeName == "c"
1106 and attr.localName == "c"
1107 and attr.namespaceURI == "http://xml.python.org/ns"
1108 and attr.prefix is None
1109 and attr.value == "v"
1110 and elem.getAttributeNode("a") is None
1111 and elem.getAttributeNode("b") is None
1112 and elem.getAttributeNode("c").isSameNode(attr)
1113 and elem.getAttributeNodeNS(
1114 "http://xml.python.org/ns", "c").isSameNode(attr)
1115 and attrmap["c"].isSameNode(attr)
1116 and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001117
Collin Winterd28fcbc2007-03-28 23:34:06 +00001118 # Rename to have a namespace, with prefix
1119 attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
1120 self.confirm(attr.name == "p:d"
1121 and attr.nodeName == "p:d"
1122 and attr.localName == "d"
1123 and attr.namespaceURI == "http://xml.python.org/ns2"
1124 and attr.prefix == "p"
1125 and attr.value == "v"
1126 and elem.getAttributeNode("a") is None
1127 and elem.getAttributeNode("b") is None
1128 and elem.getAttributeNode("c") is None
1129 and elem.getAttributeNodeNS(
1130 "http://xml.python.org/ns", "c") is None
1131 and elem.getAttributeNode("p:d").isSameNode(attr)
1132 and elem.getAttributeNodeNS(
1133 "http://xml.python.org/ns2", "d").isSameNode(attr)
1134 and attrmap["p:d"].isSameNode(attr)
1135 and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001136
Collin Winterd28fcbc2007-03-28 23:34:06 +00001137 # Rename back to a simple non-NS node
1138 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
1139 self.confirm(attr.name == "e"
1140 and attr.nodeName == "e"
1141 and attr.localName is None
1142 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
1143 and attr.prefix is None
1144 and attr.value == "v"
1145 and elem.getAttributeNode("a") is None
1146 and elem.getAttributeNode("b") is None
1147 and elem.getAttributeNode("c") is None
1148 and elem.getAttributeNode("p:d") is None
1149 and elem.getAttributeNodeNS(
1150 "http://xml.python.org/ns", "c") is None
1151 and elem.getAttributeNode("e").isSameNode(attr)
1152 and attrmap["e"].isSameNode(attr))
1153
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001154 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001155 "http://xml.python.org/ns", "xmlns")
1156 self.checkRenameNodeSharedConstraints(doc, attr)
1157 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001158
Collin Winterd28fcbc2007-03-28 23:34:06 +00001159 def testRenameElement(self):
1160 doc = parseString("<doc/>")
1161 elem = doc.documentElement
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001162
Collin Winterd28fcbc2007-03-28 23:34:06 +00001163 # Simple renaming
1164 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
1165 self.confirm(elem.tagName == "a"
1166 and elem.nodeName == "a"
1167 and elem.localName is None
1168 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1169 and elem.prefix is None
1170 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001171
Collin Winterd28fcbc2007-03-28 23:34:06 +00001172 # Rename to have a namespace, no prefix
1173 elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
1174 self.confirm(elem.tagName == "b"
1175 and elem.nodeName == "b"
1176 and elem.localName == "b"
1177 and elem.namespaceURI == "http://xml.python.org/ns"
1178 and elem.prefix is None
1179 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001180
Collin Winterd28fcbc2007-03-28 23:34:06 +00001181 # Rename to have a namespace, with prefix
1182 elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
1183 self.confirm(elem.tagName == "p:c"
1184 and elem.nodeName == "p:c"
1185 and elem.localName == "c"
1186 and elem.namespaceURI == "http://xml.python.org/ns2"
1187 and elem.prefix == "p"
1188 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001189
Collin Winterd28fcbc2007-03-28 23:34:06 +00001190 # Rename back to a simple non-NS node
1191 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
1192 self.confirm(elem.tagName == "d"
1193 and elem.nodeName == "d"
1194 and elem.localName is None
1195 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1196 and elem.prefix is None
1197 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001198
Collin Winterd28fcbc2007-03-28 23:34:06 +00001199 self.checkRenameNodeSharedConstraints(doc, elem)
1200 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001201
Collin Winterd28fcbc2007-03-28 23:34:06 +00001202 def testRenameOther(self):
1203 # We have to create a comment node explicitly since not all DOM
1204 # builders used with minidom add comments to the DOM.
1205 doc = xml.dom.minidom.getDOMImplementation().createDocument(
1206 xml.dom.EMPTY_NAMESPACE, "e", None)
1207 node = doc.createComment("comment")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001208 self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001209 xml.dom.EMPTY_NAMESPACE, "foo")
1210 doc.unlink()
1211
1212 def testWholeText(self):
1213 doc = parseString("<doc>a</doc>")
1214 elem = doc.documentElement
1215 text = elem.childNodes[0]
Ezio Melotti2623a372010-11-21 13:34:58 +00001216 self.assertEqual(text.nodeType, Node.TEXT_NODE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001217
Collin Winterd28fcbc2007-03-28 23:34:06 +00001218 self.checkWholeText(text, "a")
1219 elem.appendChild(doc.createTextNode("b"))
1220 self.checkWholeText(text, "ab")
1221 elem.insertBefore(doc.createCDATASection("c"), text)
1222 self.checkWholeText(text, "cab")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001223
Collin Winterd28fcbc2007-03-28 23:34:06 +00001224 # make sure we don't cross other nodes
1225 splitter = doc.createComment("comment")
1226 elem.appendChild(splitter)
1227 text2 = doc.createTextNode("d")
1228 elem.appendChild(text2)
1229 self.checkWholeText(text, "cab")
1230 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001231
Collin Winterd28fcbc2007-03-28 23:34:06 +00001232 x = doc.createElement("x")
1233 elem.replaceChild(x, splitter)
1234 splitter = x
1235 self.checkWholeText(text, "cab")
1236 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001237
Collin Winterd28fcbc2007-03-28 23:34:06 +00001238 x = doc.createProcessingInstruction("y", "z")
1239 elem.replaceChild(x, splitter)
1240 splitter = x
1241 self.checkWholeText(text, "cab")
1242 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001243
Collin Winterd28fcbc2007-03-28 23:34:06 +00001244 elem.removeChild(splitter)
1245 self.checkWholeText(text, "cabd")
1246 self.checkWholeText(text2, "cabd")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001247
Collin Winterd28fcbc2007-03-28 23:34:06 +00001248 def testPatch1094164(self):
1249 doc = parseString("<doc><e/></doc>")
1250 elem = doc.documentElement
1251 e = elem.firstChild
1252 self.confirm(e.parentNode is elem, "Before replaceChild()")
1253 # Check that replacing a child with itself leaves the tree unchanged
1254 elem.replaceChild(e, e)
1255 self.confirm(e.parentNode is elem, "After replaceChild()")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001256
Collin Winterd28fcbc2007-03-28 23:34:06 +00001257 def testReplaceWholeText(self):
1258 def setup():
1259 doc = parseString("<doc>a<e/>d</doc>")
1260 elem = doc.documentElement
1261 text1 = elem.firstChild
1262 text2 = elem.lastChild
1263 splitter = text1.nextSibling
1264 elem.insertBefore(doc.createTextNode("b"), splitter)
1265 elem.insertBefore(doc.createCDATASection("c"), text1)
1266 return doc, elem, text1, splitter, text2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001267
Collin Winterd28fcbc2007-03-28 23:34:06 +00001268 doc, elem, text1, splitter, text2 = setup()
1269 text = text1.replaceWholeText("new content")
1270 self.checkWholeText(text, "new content")
1271 self.checkWholeText(text2, "d")
1272 self.confirm(len(elem.childNodes) == 3)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001273
Collin Winterd28fcbc2007-03-28 23:34:06 +00001274 doc, elem, text1, splitter, text2 = setup()
1275 text = text2.replaceWholeText("new content")
1276 self.checkWholeText(text, "new content")
1277 self.checkWholeText(text1, "cab")
1278 self.confirm(len(elem.childNodes) == 5)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001279
Collin Winterd28fcbc2007-03-28 23:34:06 +00001280 doc, elem, text1, splitter, text2 = setup()
1281 text = text1.replaceWholeText("")
1282 self.checkWholeText(text2, "d")
1283 self.confirm(text is None
1284 and len(elem.childNodes) == 2)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001285
Collin Winterd28fcbc2007-03-28 23:34:06 +00001286 def testSchemaType(self):
1287 doc = parseString(
1288 "<!DOCTYPE doc [\n"
1289 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
1290 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
1291 " <!ATTLIST doc id ID #IMPLIED \n"
1292 " ref IDREF #IMPLIED \n"
1293 " refs IDREFS #IMPLIED \n"
1294 " enum (a|b) #IMPLIED \n"
1295 " ent ENTITY #IMPLIED \n"
1296 " ents ENTITIES #IMPLIED \n"
1297 " nm NMTOKEN #IMPLIED \n"
1298 " nms NMTOKENS #IMPLIED \n"
1299 " text CDATA #IMPLIED \n"
1300 " >\n"
1301 "]><doc id='name' notid='name' text='splat!' enum='b'"
1302 " ref='name' refs='name name' ent='e1' ents='e1 e2'"
1303 " nm='123' nms='123 abc' />")
1304 elem = doc.documentElement
1305 # We don't want to rely on any specific loader at this point, so
1306 # just make sure we can get to all the names, and that the
1307 # DTD-based namespace is right. The names can vary by loader
1308 # since each supports a different level of DTD information.
1309 t = elem.schemaType
1310 self.confirm(t.name is None
1311 and t.namespace == xml.dom.EMPTY_NAMESPACE)
1312 names = "id notid text enum ref refs ent ents nm nms".split()
1313 for name in names:
1314 a = elem.getAttributeNode(name)
1315 t = a.schemaType
1316 self.confirm(hasattr(t, "name")
1317 and t.namespace == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001318
Collin Winterd28fcbc2007-03-28 23:34:06 +00001319 def testSetIdAttribute(self):
1320 doc = parseString("<doc a1='v' a2='w'/>")
1321 e = doc.documentElement
1322 a1 = e.getAttributeNode("a1")
1323 a2 = e.getAttributeNode("a2")
1324 self.confirm(doc.getElementById("v") is None
1325 and not a1.isId
1326 and not a2.isId)
1327 e.setIdAttribute("a1")
1328 self.confirm(e.isSameNode(doc.getElementById("v"))
1329 and a1.isId
1330 and not a2.isId)
1331 e.setIdAttribute("a2")
1332 self.confirm(e.isSameNode(doc.getElementById("v"))
1333 and e.isSameNode(doc.getElementById("w"))
1334 and a1.isId
1335 and a2.isId)
1336 # replace the a1 node; the new node should *not* be an ID
1337 a3 = doc.createAttribute("a1")
1338 a3.value = "v"
1339 e.setAttributeNode(a3)
1340 self.confirm(doc.getElementById("v") is None
1341 and e.isSameNode(doc.getElementById("w"))
1342 and not a1.isId
1343 and a2.isId
1344 and not a3.isId)
1345 # renaming an attribute should not affect its ID-ness:
1346 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1347 self.confirm(e.isSameNode(doc.getElementById("w"))
1348 and a2.isId)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001349
Collin Winterd28fcbc2007-03-28 23:34:06 +00001350 def testSetIdAttributeNS(self):
1351 NS1 = "http://xml.python.org/ns1"
1352 NS2 = "http://xml.python.org/ns2"
1353 doc = parseString("<doc"
1354 " xmlns:ns1='" + NS1 + "'"
1355 " xmlns:ns2='" + NS2 + "'"
1356 " ns1:a1='v' ns2:a2='w'/>")
1357 e = doc.documentElement
1358 a1 = e.getAttributeNodeNS(NS1, "a1")
1359 a2 = e.getAttributeNodeNS(NS2, "a2")
1360 self.confirm(doc.getElementById("v") is None
1361 and not a1.isId
1362 and not a2.isId)
1363 e.setIdAttributeNS(NS1, "a1")
1364 self.confirm(e.isSameNode(doc.getElementById("v"))
1365 and a1.isId
1366 and not a2.isId)
1367 e.setIdAttributeNS(NS2, "a2")
1368 self.confirm(e.isSameNode(doc.getElementById("v"))
1369 and e.isSameNode(doc.getElementById("w"))
1370 and a1.isId
1371 and a2.isId)
1372 # replace the a1 node; the new node should *not* be an ID
1373 a3 = doc.createAttributeNS(NS1, "a1")
1374 a3.value = "v"
1375 e.setAttributeNode(a3)
1376 self.confirm(e.isSameNode(doc.getElementById("w")))
1377 self.confirm(not a1.isId)
1378 self.confirm(a2.isId)
1379 self.confirm(not a3.isId)
1380 self.confirm(doc.getElementById("v") is None)
1381 # renaming an attribute should not affect its ID-ness:
1382 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1383 self.confirm(e.isSameNode(doc.getElementById("w"))
1384 and a2.isId)
1385
1386 def testSetIdAttributeNode(self):
1387 NS1 = "http://xml.python.org/ns1"
1388 NS2 = "http://xml.python.org/ns2"
1389 doc = parseString("<doc"
1390 " xmlns:ns1='" + NS1 + "'"
1391 " xmlns:ns2='" + NS2 + "'"
1392 " ns1:a1='v' ns2:a2='w'/>")
1393 e = doc.documentElement
1394 a1 = e.getAttributeNodeNS(NS1, "a1")
1395 a2 = e.getAttributeNodeNS(NS2, "a2")
1396 self.confirm(doc.getElementById("v") is None
1397 and not a1.isId
1398 and not a2.isId)
1399 e.setIdAttributeNode(a1)
1400 self.confirm(e.isSameNode(doc.getElementById("v"))
1401 and a1.isId
1402 and not a2.isId)
1403 e.setIdAttributeNode(a2)
1404 self.confirm(e.isSameNode(doc.getElementById("v"))
1405 and e.isSameNode(doc.getElementById("w"))
1406 and a1.isId
1407 and a2.isId)
1408 # replace the a1 node; the new node should *not* be an ID
1409 a3 = doc.createAttributeNS(NS1, "a1")
1410 a3.value = "v"
1411 e.setAttributeNode(a3)
1412 self.confirm(e.isSameNode(doc.getElementById("w")))
1413 self.confirm(not a1.isId)
1414 self.confirm(a2.isId)
1415 self.confirm(not a3.isId)
1416 self.confirm(doc.getElementById("v") is None)
1417 # renaming an attribute should not affect its ID-ness:
1418 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1419 self.confirm(e.isSameNode(doc.getElementById("w"))
1420 and a2.isId)
1421
1422 def testPickledDocument(self):
1423 doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
1424 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
1425 " 'http://xml.python.org/system' [\n"
1426 " <!ELEMENT e EMPTY>\n"
1427 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
1428 "]><doc attr='value'> text\n"
1429 "<?pi sample?> <!-- comment --> <e/> </doc>")
1430 s = pickle.dumps(doc)
1431 doc2 = pickle.loads(s)
1432 stack = [(doc, doc2)]
1433 while stack:
1434 n1, n2 = stack.pop()
1435 self.confirm(n1.nodeType == n2.nodeType
1436 and len(n1.childNodes) == len(n2.childNodes)
1437 and n1.nodeName == n2.nodeName
1438 and not n1.isSameNode(n2)
1439 and not n2.isSameNode(n1))
1440 if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
1441 len(n1.entities)
1442 len(n2.entities)
1443 len(n1.notations)
1444 len(n2.notations)
1445 self.confirm(len(n1.entities) == len(n2.entities)
1446 and len(n1.notations) == len(n2.notations))
1447 for i in range(len(n1.notations)):
Georg Brandlcd4a21b2010-02-06 23:34:10 +00001448 # XXX this loop body doesn't seem to be executed?
Collin Winterd28fcbc2007-03-28 23:34:06 +00001449 no1 = n1.notations.item(i)
1450 no2 = n1.notations.item(i)
1451 self.confirm(no1.name == no2.name
1452 and no1.publicId == no2.publicId
1453 and no1.systemId == no2.systemId)
Georg Brandlcd4a21b2010-02-06 23:34:10 +00001454 stack.append((no1, no2))
Collin Winterd28fcbc2007-03-28 23:34:06 +00001455 for i in range(len(n1.entities)):
1456 e1 = n1.entities.item(i)
1457 e2 = n2.entities.item(i)
1458 self.confirm(e1.notationName == e2.notationName
1459 and e1.publicId == e2.publicId
1460 and e1.systemId == e2.systemId)
1461 stack.append((e1, e2))
1462 if n1.nodeType != Node.DOCUMENT_NODE:
1463 self.confirm(n1.ownerDocument.isSameNode(doc)
1464 and n2.ownerDocument.isSameNode(doc2))
1465 for i in range(len(n1.childNodes)):
1466 stack.append((n1.childNodes[i], n2.childNodes[i]))
1467
Martin v. Löwis27e4a172008-05-23 15:18:28 +00001468 def testSerializeCommentNodeWithDoubleHyphen(self):
1469 doc = create_doc_without_doctype()
1470 doc.appendChild(doc.createComment("foo--bar"))
1471 self.assertRaises(ValueError, doc.toxml)
1472
Georg Brandl5ded7912010-11-26 07:35:31 +00001473 def testEmptyXMLNSValue(self):
1474 doc = parseString("<element xmlns=''>\n"
1475 "<foo/>\n</element>")
1476 doc2 = parseString(doc.toxml())
1477 self.confirm(doc2.namespaceURI == xml.dom.EMPTY_NAMESPACE)
1478
1479
Collin Winterd28fcbc2007-03-28 23:34:06 +00001480def test_main():
1481 run_unittest(MinidomTest)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001482
Collin Winterd28fcbc2007-03-28 23:34:06 +00001483if __name__ == "__main__":
1484 test_main()