blob: 060c1a550d0e09c66c7e2b4011c6f9d9a6f6c818 [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
Ezio Melotti93bbb6a2011-11-18 17:30:28 +0200442 def test_toprettyxml_with_text_nodes(self):
443 # see issue #4147, text nodes are not indented
444 decl = '<?xml version="1.0" ?>\n'
445 self.assertEqual(parseString('<B>A</B>').toprettyxml(),
446 decl + '<B>A</B>\n')
447 self.assertEqual(parseString('<C>A<B>A</B></C>').toprettyxml(),
448 decl + '<C>\n\tA\n\t<B>A</B>\n</C>\n')
449 self.assertEqual(parseString('<C><B>A</B>A</C>').toprettyxml(),
450 decl + '<C>\n\t<B>A</B>\n\tA\n</C>\n')
451 self.assertEqual(parseString('<C><B>A</B><B>A</B></C>').toprettyxml(),
452 decl + '<C>\n\t<B>A</B>\n\t<B>A</B>\n</C>\n')
453 self.assertEqual(parseString('<C><B>A</B>A<B>A</B></C>').toprettyxml(),
454 decl + '<C>\n\t<B>A</B>\n\tA\n\t<B>A</B>\n</C>\n')
455
456 def test_toprettyxml_with_adjacent_text_nodes(self):
457 # see issue #4147, adjacent text nodes are indented normally
458 dom = Document()
459 elem = dom.createElement(u'elem')
460 elem.appendChild(dom.createTextNode(u'TEXT'))
461 elem.appendChild(dom.createTextNode(u'TEXT'))
462 dom.appendChild(elem)
463 decl = '<?xml version="1.0" ?>\n'
464 self.assertEqual(dom.toprettyxml(),
465 decl + '<elem>\n\tTEXT\n\tTEXT\n</elem>\n')
466
Éric Araujo2710bc42011-10-05 02:35:09 +0200467 def test_toprettyxml_preserves_content_of_text_node(self):
Ezio Melotti93bbb6a2011-11-18 17:30:28 +0200468 # see issue #4147
469 for str in ('<B>A</B>', '<A><B>C</B></A>'):
470 dom = parseString(str)
471 dom2 = parseString(dom.toprettyxml())
472 self.assertEqual(
473 dom.getElementsByTagName('B')[0].childNodes[0].toxml(),
474 dom2.getElementsByTagName('B')[0].childNodes[0].toxml())
R David Murrayc8faf9b2011-10-01 16:49:25 -0400475
Collin Winterd28fcbc2007-03-28 23:34:06 +0000476 def testProcessingInstruction(self):
477 dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
478 pi = dom.documentElement.firstChild
479 self.confirm(pi.target == "mypi"
480 and pi.data == "data \t\n "
481 and pi.nodeName == "mypi"
482 and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
483 and pi.attributes is None
484 and not pi.hasChildNodes()
485 and len(pi.childNodes) == 0
486 and pi.firstChild is None
487 and pi.lastChild is None
488 and pi.localName is None
489 and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000490
Collin Winterd28fcbc2007-03-28 23:34:06 +0000491 def testProcessingInstructionRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000492
Collin Winterd28fcbc2007-03-28 23:34:06 +0000493 def testTextRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000494
Collin Winterd28fcbc2007-03-28 23:34:06 +0000495 def testWriteText(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000496
Collin Winterd28fcbc2007-03-28 23:34:06 +0000497 def testDocumentElement(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000498
Collin Winterd28fcbc2007-03-28 23:34:06 +0000499 def testTooManyDocumentElements(self):
500 doc = parseString("<doc/>")
501 elem = doc.createElement("extra")
502 # Should raise an exception when adding an extra document element.
503 self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem)
504 elem.unlink()
505 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000506
Collin Winterd28fcbc2007-03-28 23:34:06 +0000507 def testCreateElementNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000508
Collin Winterd28fcbc2007-03-28 23:34:06 +0000509 def testCreateAttributeNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000510
Collin Winterd28fcbc2007-03-28 23:34:06 +0000511 def testParse(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000512
Collin Winterd28fcbc2007-03-28 23:34:06 +0000513 def testParseString(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000514
Collin Winterd28fcbc2007-03-28 23:34:06 +0000515 def testComment(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000516
Collin Winterd28fcbc2007-03-28 23:34:06 +0000517 def testAttrListItem(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000518
Collin Winterd28fcbc2007-03-28 23:34:06 +0000519 def testAttrListItems(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000520
Collin Winterd28fcbc2007-03-28 23:34:06 +0000521 def testAttrListItemNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000522
Collin Winterd28fcbc2007-03-28 23:34:06 +0000523 def testAttrListKeys(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000524
Collin Winterd28fcbc2007-03-28 23:34:06 +0000525 def testAttrListKeysNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000526
Collin Winterd28fcbc2007-03-28 23:34:06 +0000527 def testRemoveNamedItem(self):
528 doc = parseString("<doc a=''/>")
529 e = doc.documentElement
530 attrs = e.attributes
531 a1 = e.getAttributeNode("a")
532 a2 = attrs.removeNamedItem("a")
533 self.confirm(a1.isSameNode(a2))
534 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000535
Collin Winterd28fcbc2007-03-28 23:34:06 +0000536 def testRemoveNamedItemNS(self):
537 doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
538 e = doc.documentElement
539 attrs = e.attributes
540 a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
541 a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
542 self.confirm(a1.isSameNode(a2))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000543 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000544 "http://xml.python.org/", "b")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000545
Collin Winterd28fcbc2007-03-28 23:34:06 +0000546 def testAttrListValues(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000547
Collin Winterd28fcbc2007-03-28 23:34:06 +0000548 def testAttrListLength(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000549
Collin Winterd28fcbc2007-03-28 23:34:06 +0000550 def testAttrList__getitem__(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000551
Collin Winterd28fcbc2007-03-28 23:34:06 +0000552 def testAttrList__setitem__(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000553
Collin Winterd28fcbc2007-03-28 23:34:06 +0000554 def testSetAttrValueandNodeValue(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000555
Collin Winterd28fcbc2007-03-28 23:34:06 +0000556 def testParseElement(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000557
Collin Winterd28fcbc2007-03-28 23:34:06 +0000558 def testParseAttributes(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000559
Collin Winterd28fcbc2007-03-28 23:34:06 +0000560 def testParseElementNamespaces(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000561
Collin Winterd28fcbc2007-03-28 23:34:06 +0000562 def testParseAttributeNamespaces(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000563
Collin Winterd28fcbc2007-03-28 23:34:06 +0000564 def testParseProcessingInstructions(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000565
Collin Winterd28fcbc2007-03-28 23:34:06 +0000566 def testChildNodes(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000567
Collin Winterd28fcbc2007-03-28 23:34:06 +0000568 def testFirstChild(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000569
Collin Winterd28fcbc2007-03-28 23:34:06 +0000570 def testHasChildNodes(self): pass
571
572 def _testCloneElementCopiesAttributes(self, e1, e2, test):
573 attrs1 = e1.attributes
574 attrs2 = e2.attributes
575 keys1 = attrs1.keys()
576 keys2 = attrs2.keys()
577 keys1.sort()
578 keys2.sort()
579 self.confirm(keys1 == keys2, "clone of element has same attribute keys")
580 for i in range(len(keys1)):
581 a1 = attrs1.item(i)
582 a2 = attrs2.item(i)
583 self.confirm(a1 is not a2
584 and a1.value == a2.value
585 and a1.nodeValue == a2.nodeValue
586 and a1.namespaceURI == a2.namespaceURI
587 and a1.localName == a2.localName
588 , "clone of attribute node has proper attribute values")
589 self.confirm(a2.ownerElement is e2,
590 "clone of attribute node correctly owned")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000591
Collin Winterd28fcbc2007-03-28 23:34:06 +0000592 def _setupCloneElement(self, deep):
593 dom = parseString("<doc attr='value'><foo/></doc>")
594 root = dom.documentElement
595 clone = root.cloneNode(deep)
596 self._testCloneElementCopiesAttributes(
597 root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
598 # mutilate the original so shared data is detected
599 root.tagName = root.nodeName = "MODIFIED"
600 root.setAttribute("attr", "NEW VALUE")
601 root.setAttribute("added", "VALUE")
602 return dom, clone
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000603
Collin Winterd28fcbc2007-03-28 23:34:06 +0000604 def testCloneElementShallow(self):
605 dom, clone = self._setupCloneElement(0)
606 self.confirm(len(clone.childNodes) == 0
607 and clone.childNodes.length == 0
608 and clone.parentNode is None
609 and clone.toxml() == '<doc attr="value"/>'
610 , "testCloneElementShallow")
611 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000612
Collin Winterd28fcbc2007-03-28 23:34:06 +0000613 def testCloneElementDeep(self):
614 dom, clone = self._setupCloneElement(1)
615 self.confirm(len(clone.childNodes) == 1
616 and clone.childNodes.length == 1
617 and clone.parentNode is None
618 and clone.toxml() == '<doc attr="value"><foo/></doc>'
619 , "testCloneElementDeep")
620 dom.unlink()
621
622 def testCloneDocumentShallow(self):
623 doc = parseString("<?xml version='1.0'?>\n"
624 "<!-- comment -->"
625 "<!DOCTYPE doc [\n"
626 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
627 "]>\n"
628 "<doc attr='value'/>")
629 doc2 = doc.cloneNode(0)
630 self.confirm(doc2 is None,
631 "testCloneDocumentShallow:"
632 " shallow cloning of documents makes no sense!")
633
634 def testCloneDocumentDeep(self):
635 doc = parseString("<?xml version='1.0'?>\n"
636 "<!-- comment -->"
637 "<!DOCTYPE doc [\n"
638 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
639 "]>\n"
640 "<doc attr='value'/>")
641 doc2 = doc.cloneNode(1)
642 self.confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
643 "testCloneDocumentDeep: document objects not distinct")
644 self.confirm(len(doc.childNodes) == len(doc2.childNodes),
645 "testCloneDocumentDeep: wrong number of Document children")
646 self.confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
647 "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
648 self.confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
649 "testCloneDocumentDeep: documentElement owner is not new document")
650 self.confirm(not doc.documentElement.isSameNode(doc2.documentElement),
651 "testCloneDocumentDeep: documentElement should not be shared")
652 if doc.doctype is not None:
653 # check the doctype iff the original DOM maintained it
654 self.confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
655 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
656 self.confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
657 self.confirm(not doc.doctype.isSameNode(doc2.doctype))
658
659 def testCloneDocumentTypeDeepOk(self):
660 doctype = create_nonempty_doctype()
661 clone = doctype.cloneNode(1)
662 self.confirm(clone is not None
663 and clone.nodeName == doctype.nodeName
664 and clone.name == doctype.name
665 and clone.publicId == doctype.publicId
666 and clone.systemId == doctype.systemId
667 and len(clone.entities) == len(doctype.entities)
668 and clone.entities.item(len(clone.entities)) is None
669 and len(clone.notations) == len(doctype.notations)
670 and clone.notations.item(len(clone.notations)) is None
671 and len(clone.childNodes) == 0)
672 for i in range(len(doctype.entities)):
673 se = doctype.entities.item(i)
674 ce = clone.entities.item(i)
675 self.confirm((not se.isSameNode(ce))
676 and (not ce.isSameNode(se))
677 and ce.nodeName == se.nodeName
678 and ce.notationName == se.notationName
679 and ce.publicId == se.publicId
680 and ce.systemId == se.systemId
681 and ce.encoding == se.encoding
682 and ce.actualEncoding == se.actualEncoding
683 and ce.version == se.version)
684 for i in range(len(doctype.notations)):
685 sn = doctype.notations.item(i)
686 cn = clone.notations.item(i)
687 self.confirm((not sn.isSameNode(cn))
688 and (not cn.isSameNode(sn))
689 and cn.nodeName == sn.nodeName
690 and cn.publicId == sn.publicId
691 and cn.systemId == sn.systemId)
692
693 def testCloneDocumentTypeDeepNotOk(self):
694 doc = create_doc_with_doctype()
695 clone = doc.doctype.cloneNode(1)
696 self.confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
697
698 def testCloneDocumentTypeShallowOk(self):
699 doctype = create_nonempty_doctype()
700 clone = doctype.cloneNode(0)
701 self.confirm(clone is not None
702 and clone.nodeName == doctype.nodeName
703 and clone.name == doctype.name
704 and clone.publicId == doctype.publicId
705 and clone.systemId == doctype.systemId
706 and len(clone.entities) == 0
707 and clone.entities.item(0) is None
708 and len(clone.notations) == 0
709 and clone.notations.item(0) is None
710 and len(clone.childNodes) == 0)
711
712 def testCloneDocumentTypeShallowNotOk(self):
713 doc = create_doc_with_doctype()
714 clone = doc.doctype.cloneNode(0)
715 self.confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
716
717 def check_import_document(self, deep, testName):
718 doc1 = parseString("<doc/>")
719 doc2 = parseString("<doc/>")
720 self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000721
Collin Winterd28fcbc2007-03-28 23:34:06 +0000722 def testImportDocumentShallow(self):
723 self.check_import_document(0, "testImportDocumentShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000724
Collin Winterd28fcbc2007-03-28 23:34:06 +0000725 def testImportDocumentDeep(self):
726 self.check_import_document(1, "testImportDocumentDeep")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000727
Collin Winterd28fcbc2007-03-28 23:34:06 +0000728 def testImportDocumentTypeShallow(self):
729 src = create_doc_with_doctype()
730 target = create_doc_without_doctype()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000731 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000732 src.doctype, 0)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000733
Collin Winterd28fcbc2007-03-28 23:34:06 +0000734 def testImportDocumentTypeDeep(self):
735 src = create_doc_with_doctype()
736 target = create_doc_without_doctype()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000737 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000738 src.doctype, 1)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000739
Collin Winterd28fcbc2007-03-28 23:34:06 +0000740 # Testing attribute clones uses a helper, and should always be deep,
741 # even if the argument to cloneNode is false.
742 def check_clone_attribute(self, deep, testName):
743 doc = parseString("<doc attr='value'/>")
744 attr = doc.documentElement.getAttributeNode("attr")
Benjamin Peterson5c8da862009-06-30 22:57:08 +0000745 self.assertNotEqual(attr, None)
Collin Winterd28fcbc2007-03-28 23:34:06 +0000746 clone = attr.cloneNode(deep)
747 self.confirm(not clone.isSameNode(attr))
748 self.confirm(not attr.isSameNode(clone))
749 self.confirm(clone.ownerElement is None,
750 testName + ": ownerElement should be None")
751 self.confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
752 testName + ": ownerDocument does not match")
753 self.confirm(clone.specified,
754 testName + ": cloned attribute must have specified == True")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000755
Collin Winterd28fcbc2007-03-28 23:34:06 +0000756 def testCloneAttributeShallow(self):
757 self.check_clone_attribute(0, "testCloneAttributeShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000758
Collin Winterd28fcbc2007-03-28 23:34:06 +0000759 def testCloneAttributeDeep(self):
760 self.check_clone_attribute(1, "testCloneAttributeDeep")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000761
Collin Winterd28fcbc2007-03-28 23:34:06 +0000762 def check_clone_pi(self, deep, testName):
763 doc = parseString("<?target data?><doc/>")
764 pi = doc.firstChild
Ezio Melotti2623a372010-11-21 13:34:58 +0000765 self.assertEqual(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE)
Collin Winterd28fcbc2007-03-28 23:34:06 +0000766 clone = pi.cloneNode(deep)
767 self.confirm(clone.target == pi.target
768 and clone.data == pi.data)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000769
Collin Winterd28fcbc2007-03-28 23:34:06 +0000770 def testClonePIShallow(self):
771 self.check_clone_pi(0, "testClonePIShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000772
Collin Winterd28fcbc2007-03-28 23:34:06 +0000773 def testClonePIDeep(self):
774 self.check_clone_pi(1, "testClonePIDeep")
775
776 def testNormalize(self):
777 doc = parseString("<doc/>")
778 root = doc.documentElement
779 root.appendChild(doc.createTextNode("first"))
780 root.appendChild(doc.createTextNode("second"))
781 self.confirm(len(root.childNodes) == 2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000782 and root.childNodes.length == 2,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000783 "testNormalize -- preparation")
784 doc.normalize()
785 self.confirm(len(root.childNodes) == 1
786 and root.childNodes.length == 1
787 and root.firstChild is root.lastChild
788 and root.firstChild.data == "firstsecond"
789 , "testNormalize -- result")
790 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000791
Collin Winterd28fcbc2007-03-28 23:34:06 +0000792 doc = parseString("<doc/>")
793 root = doc.documentElement
794 root.appendChild(doc.createTextNode(""))
795 doc.normalize()
796 self.confirm(len(root.childNodes) == 0
797 and root.childNodes.length == 0,
798 "testNormalize -- single empty node removed")
799 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000800
R. David Murray0374a822009-04-09 21:54:50 +0000801 def testNormalizeCombineAndNextSibling(self):
802 doc = parseString("<doc/>")
803 root = doc.documentElement
804 root.appendChild(doc.createTextNode("first"))
805 root.appendChild(doc.createTextNode("second"))
806 root.appendChild(doc.createElement("i"))
807 self.confirm(len(root.childNodes) == 3
808 and root.childNodes.length == 3,
809 "testNormalizeCombineAndNextSibling -- preparation")
810 doc.normalize()
811 self.confirm(len(root.childNodes) == 2
812 and root.childNodes.length == 2
813 and root.firstChild.data == "firstsecond"
814 and root.firstChild is not root.lastChild
815 and root.firstChild.nextSibling is root.lastChild
816 and root.firstChild.previousSibling is None
817 and root.lastChild.previousSibling is root.firstChild
818 and root.lastChild.nextSibling is None
819 , "testNormalizeCombinedAndNextSibling -- result")
820 doc.unlink()
821
822 def testNormalizeDeleteWithPrevSibling(self):
823 doc = parseString("<doc/>")
824 root = doc.documentElement
825 root.appendChild(doc.createTextNode("first"))
826 root.appendChild(doc.createTextNode(""))
827 self.confirm(len(root.childNodes) == 2
828 and root.childNodes.length == 2,
829 "testNormalizeDeleteWithPrevSibling -- preparation")
830 doc.normalize()
831 self.confirm(len(root.childNodes) == 1
832 and root.childNodes.length == 1
833 and root.firstChild.data == "first"
834 and root.firstChild is root.lastChild
835 and root.firstChild.nextSibling is None
836 and root.firstChild.previousSibling is None
837 , "testNormalizeDeleteWithPrevSibling -- result")
838 doc.unlink()
839
840 def testNormalizeDeleteWithNextSibling(self):
841 doc = parseString("<doc/>")
842 root = doc.documentElement
843 root.appendChild(doc.createTextNode(""))
844 root.appendChild(doc.createTextNode("second"))
845 self.confirm(len(root.childNodes) == 2
846 and root.childNodes.length == 2,
847 "testNormalizeDeleteWithNextSibling -- preparation")
848 doc.normalize()
849 self.confirm(len(root.childNodes) == 1
850 and root.childNodes.length == 1
851 and root.firstChild.data == "second"
852 and root.firstChild is root.lastChild
853 and root.firstChild.nextSibling is None
854 and root.firstChild.previousSibling is None
855 , "testNormalizeDeleteWithNextSibling -- result")
856 doc.unlink()
857
858 def testNormalizeDeleteWithTwoNonTextSiblings(self):
859 doc = parseString("<doc/>")
860 root = doc.documentElement
861 root.appendChild(doc.createElement("i"))
862 root.appendChild(doc.createTextNode(""))
863 root.appendChild(doc.createElement("i"))
864 self.confirm(len(root.childNodes) == 3
865 and root.childNodes.length == 3,
866 "testNormalizeDeleteWithTwoSiblings -- preparation")
867 doc.normalize()
868 self.confirm(len(root.childNodes) == 2
869 and root.childNodes.length == 2
870 and root.firstChild is not root.lastChild
871 and root.firstChild.nextSibling is root.lastChild
872 and root.firstChild.previousSibling is None
873 and root.lastChild.previousSibling is root.firstChild
874 and root.lastChild.nextSibling is None
875 , "testNormalizeDeleteWithTwoSiblings -- result")
876 doc.unlink()
877
878 def testNormalizeDeleteAndCombine(self):
879 doc = parseString("<doc/>")
880 root = doc.documentElement
881 root.appendChild(doc.createTextNode(""))
882 root.appendChild(doc.createTextNode("second"))
883 root.appendChild(doc.createTextNode(""))
884 root.appendChild(doc.createTextNode("fourth"))
885 root.appendChild(doc.createTextNode(""))
886 self.confirm(len(root.childNodes) == 5
887 and root.childNodes.length == 5,
888 "testNormalizeDeleteAndCombine -- preparation")
889 doc.normalize()
890 self.confirm(len(root.childNodes) == 1
891 and root.childNodes.length == 1
892 and root.firstChild is root.lastChild
893 and root.firstChild.data == "secondfourth"
894 and root.firstChild.previousSibling is None
895 and root.firstChild.nextSibling is None
896 , "testNormalizeDeleteAndCombine -- result")
897 doc.unlink()
898
899 def testNormalizeRecursion(self):
900 doc = parseString("<doc>"
901 "<o>"
902 "<i/>"
903 "t"
904 #
905 #x
906 "</o>"
907 "<o>"
908 "<o>"
909 "t2"
910 #x2
911 "</o>"
912 "t3"
913 #x3
914 "</o>"
915 #
916 "</doc>")
917 root = doc.documentElement
918 root.childNodes[0].appendChild(doc.createTextNode(""))
919 root.childNodes[0].appendChild(doc.createTextNode("x"))
920 root.childNodes[1].childNodes[0].appendChild(doc.createTextNode("x2"))
921 root.childNodes[1].appendChild(doc.createTextNode("x3"))
922 root.appendChild(doc.createTextNode(""))
923 self.confirm(len(root.childNodes) == 3
924 and root.childNodes.length == 3
925 and len(root.childNodes[0].childNodes) == 4
926 and root.childNodes[0].childNodes.length == 4
927 and len(root.childNodes[1].childNodes) == 3
928 and root.childNodes[1].childNodes.length == 3
929 and len(root.childNodes[1].childNodes[0].childNodes) == 2
930 and root.childNodes[1].childNodes[0].childNodes.length == 2
931 , "testNormalize2 -- preparation")
932 doc.normalize()
933 self.confirm(len(root.childNodes) == 2
934 and root.childNodes.length == 2
935 and len(root.childNodes[0].childNodes) == 2
936 and root.childNodes[0].childNodes.length == 2
937 and len(root.childNodes[1].childNodes) == 2
938 and root.childNodes[1].childNodes.length == 2
939 and len(root.childNodes[1].childNodes[0].childNodes) == 1
940 and root.childNodes[1].childNodes[0].childNodes.length == 1
941 , "testNormalize2 -- childNodes lengths")
942 self.confirm(root.childNodes[0].childNodes[1].data == "tx"
943 and root.childNodes[1].childNodes[0].childNodes[0].data == "t2x2"
944 and root.childNodes[1].childNodes[1].data == "t3x3"
945 , "testNormalize2 -- joined text fields")
946 self.confirm(root.childNodes[0].childNodes[1].nextSibling is None
947 and root.childNodes[0].childNodes[1].previousSibling
948 is root.childNodes[0].childNodes[0]
949 and root.childNodes[0].childNodes[0].previousSibling is None
950 and root.childNodes[0].childNodes[0].nextSibling
951 is root.childNodes[0].childNodes[1]
952 and root.childNodes[1].childNodes[1].nextSibling is None
953 and root.childNodes[1].childNodes[1].previousSibling
954 is root.childNodes[1].childNodes[0]
955 and root.childNodes[1].childNodes[0].previousSibling is None
956 and root.childNodes[1].childNodes[0].nextSibling
957 is root.childNodes[1].childNodes[1]
958 , "testNormalize2 -- sibling pointers")
959 doc.unlink()
960
961
Andrew M. Kuchling53f94d02010-07-25 23:49:57 +0000962 def testBug0777884(self):
963 doc = parseString("<o>text</o>")
964 text = doc.documentElement.childNodes[0]
Ezio Melotti2623a372010-11-21 13:34:58 +0000965 self.assertEqual(text.nodeType, Node.TEXT_NODE)
Andrew M. Kuchling53f94d02010-07-25 23:49:57 +0000966 # Should run quietly, doing nothing.
967 text.normalize()
968 doc.unlink()
969
Andrew M. Kuchling19aff0c2008-02-23 17:10:46 +0000970 def testBug1433694(self):
971 doc = parseString("<o><i/>t</o>")
972 node = doc.documentElement
973 node.childNodes[1].nodeValue = ""
974 node.normalize()
Florent Xiclunabc27c6a2010-03-19 18:34:55 +0000975 self.confirm(node.childNodes[-1].nextSibling is None,
Andrew M. Kuchling19aff0c2008-02-23 17:10:46 +0000976 "Final child's .nextSibling should be None")
977
Collin Winterd28fcbc2007-03-28 23:34:06 +0000978 def testSiblings(self):
979 doc = parseString("<doc><?pi?>text?<elm/></doc>")
980 root = doc.documentElement
981 (pi, text, elm) = root.childNodes
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000982
Collin Winterd28fcbc2007-03-28 23:34:06 +0000983 self.confirm(pi.nextSibling is text and
984 pi.previousSibling is None and
985 text.nextSibling is elm and
986 text.previousSibling is pi and
987 elm.nextSibling is None and
988 elm.previousSibling is text, "testSiblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000989
Collin Winterd28fcbc2007-03-28 23:34:06 +0000990 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000991
Collin Winterd28fcbc2007-03-28 23:34:06 +0000992 def testParents(self):
993 doc = parseString(
994 "<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
995 root = doc.documentElement
996 elm1 = root.childNodes[0]
997 (elm2a, elm2b) = elm1.childNodes
998 elm3 = elm2b.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000999
Collin Winterd28fcbc2007-03-28 23:34:06 +00001000 self.confirm(root.parentNode is doc and
1001 elm1.parentNode is root and
1002 elm2a.parentNode is elm1 and
1003 elm2b.parentNode is elm1 and
1004 elm3.parentNode is elm2b, "testParents")
1005 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001006
Collin Winterd28fcbc2007-03-28 23:34:06 +00001007 def testNodeListItem(self):
1008 doc = parseString("<doc><e/><e/></doc>")
1009 children = doc.childNodes
1010 docelem = children[0]
1011 self.confirm(children[0] is children.item(0)
1012 and children.item(1) is None
1013 and docelem.childNodes.item(0) is docelem.childNodes[0]
1014 and docelem.childNodes.item(1) is docelem.childNodes[1]
1015 and docelem.childNodes.item(0).childNodes.item(0) is None,
1016 "test NodeList.item()")
1017 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001018
Collin Winterd28fcbc2007-03-28 23:34:06 +00001019 def testSAX2DOM(self):
1020 from xml.dom import pulldom
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001021
Collin Winterd28fcbc2007-03-28 23:34:06 +00001022 sax2dom = pulldom.SAX2DOM()
1023 sax2dom.startDocument()
1024 sax2dom.startElement("doc", {})
1025 sax2dom.characters("text")
1026 sax2dom.startElement("subelm", {})
1027 sax2dom.characters("text")
1028 sax2dom.endElement("subelm")
1029 sax2dom.characters("text")
1030 sax2dom.endElement("doc")
1031 sax2dom.endDocument()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001032
Collin Winterd28fcbc2007-03-28 23:34:06 +00001033 doc = sax2dom.document
1034 root = doc.documentElement
1035 (text1, elm1, text2) = root.childNodes
1036 text3 = elm1.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001037
Collin Winterd28fcbc2007-03-28 23:34:06 +00001038 self.confirm(text1.previousSibling is None and
1039 text1.nextSibling is elm1 and
1040 elm1.previousSibling is text1 and
1041 elm1.nextSibling is text2 and
1042 text2.previousSibling is elm1 and
1043 text2.nextSibling is None and
1044 text3.previousSibling is None and
1045 text3.nextSibling is None, "testSAX2DOM - siblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001046
Collin Winterd28fcbc2007-03-28 23:34:06 +00001047 self.confirm(root.parentNode is doc and
1048 text1.parentNode is root and
1049 elm1.parentNode is root and
1050 text2.parentNode is root and
1051 text3.parentNode is elm1, "testSAX2DOM - parents")
1052 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001053
Collin Winterd28fcbc2007-03-28 23:34:06 +00001054 def testEncodings(self):
1055 doc = parseString('<foo>&#x20ac;</foo>')
1056 self.confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001057 and doc.toxml('utf-8') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +00001058 '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001059 and doc.toxml('iso-8859-15') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +00001060 '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
1061 "testEncodings - encoding EURO SIGN")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001062
1063 # Verify that character decoding errors throw exceptions instead
Collin Winterd28fcbc2007-03-28 23:34:06 +00001064 # of crashing
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001065 self.assertRaises(UnicodeDecodeError, parseString,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001066 '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001067
Collin Winterd28fcbc2007-03-28 23:34:06 +00001068 doc.unlink()
1069
1070 class UserDataHandler:
1071 called = 0
1072 def handle(self, operation, key, data, src, dst):
1073 dst.setUserData(key, data + 1, self)
1074 src.setUserData(key, None, None)
1075 self.called = 1
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001076
Collin Winterd28fcbc2007-03-28 23:34:06 +00001077 def testUserData(self):
1078 dom = Document()
1079 n = dom.createElement('e')
1080 self.confirm(n.getUserData("foo") is None)
1081 n.setUserData("foo", None, None)
1082 self.confirm(n.getUserData("foo") is None)
1083 n.setUserData("foo", 12, 12)
1084 n.setUserData("bar", 13, 13)
1085 self.confirm(n.getUserData("foo") == 12)
1086 self.confirm(n.getUserData("bar") == 13)
1087 n.setUserData("foo", None, None)
1088 self.confirm(n.getUserData("foo") is None)
1089 self.confirm(n.getUserData("bar") == 13)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001090
Collin Winterd28fcbc2007-03-28 23:34:06 +00001091 handler = self.UserDataHandler()
1092 n.setUserData("bar", 12, handler)
1093 c = n.cloneNode(1)
1094 self.confirm(handler.called
1095 and n.getUserData("bar") is None
1096 and c.getUserData("bar") == 13)
1097 n.unlink()
1098 c.unlink()
1099 dom.unlink()
1100
1101 def checkRenameNodeSharedConstraints(self, doc, node):
1102 # Make sure illegal NS usage is detected:
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001103 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001104 "http://xml.python.org/ns", "xmlns:foo")
1105 doc2 = parseString("<doc/>")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001106 self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001107 xml.dom.EMPTY_NAMESPACE, "foo")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001108
Collin Winterd28fcbc2007-03-28 23:34:06 +00001109 def testRenameAttribute(self):
1110 doc = parseString("<doc a='v'/>")
1111 elem = doc.documentElement
1112 attrmap = elem.attributes
1113 attr = elem.attributes['a']
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001114
Collin Winterd28fcbc2007-03-28 23:34:06 +00001115 # Simple renaming
1116 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
1117 self.confirm(attr.name == "b"
1118 and attr.nodeName == "b"
1119 and attr.localName is None
1120 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
1121 and attr.prefix is None
1122 and attr.value == "v"
1123 and elem.getAttributeNode("a") is None
1124 and elem.getAttributeNode("b").isSameNode(attr)
1125 and attrmap["b"].isSameNode(attr)
1126 and attr.ownerDocument.isSameNode(doc)
1127 and attr.ownerElement.isSameNode(elem))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001128
Collin Winterd28fcbc2007-03-28 23:34:06 +00001129 # Rename to have a namespace, no prefix
1130 attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
1131 self.confirm(attr.name == "c"
1132 and attr.nodeName == "c"
1133 and attr.localName == "c"
1134 and attr.namespaceURI == "http://xml.python.org/ns"
1135 and attr.prefix is None
1136 and attr.value == "v"
1137 and elem.getAttributeNode("a") is None
1138 and elem.getAttributeNode("b") is None
1139 and elem.getAttributeNode("c").isSameNode(attr)
1140 and elem.getAttributeNodeNS(
1141 "http://xml.python.org/ns", "c").isSameNode(attr)
1142 and attrmap["c"].isSameNode(attr)
1143 and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001144
Collin Winterd28fcbc2007-03-28 23:34:06 +00001145 # Rename to have a namespace, with prefix
1146 attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
1147 self.confirm(attr.name == "p:d"
1148 and attr.nodeName == "p:d"
1149 and attr.localName == "d"
1150 and attr.namespaceURI == "http://xml.python.org/ns2"
1151 and attr.prefix == "p"
1152 and attr.value == "v"
1153 and elem.getAttributeNode("a") is None
1154 and elem.getAttributeNode("b") is None
1155 and elem.getAttributeNode("c") is None
1156 and elem.getAttributeNodeNS(
1157 "http://xml.python.org/ns", "c") is None
1158 and elem.getAttributeNode("p:d").isSameNode(attr)
1159 and elem.getAttributeNodeNS(
1160 "http://xml.python.org/ns2", "d").isSameNode(attr)
1161 and attrmap["p:d"].isSameNode(attr)
1162 and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001163
Collin Winterd28fcbc2007-03-28 23:34:06 +00001164 # Rename back to a simple non-NS node
1165 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
1166 self.confirm(attr.name == "e"
1167 and attr.nodeName == "e"
1168 and attr.localName is None
1169 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
1170 and attr.prefix is None
1171 and attr.value == "v"
1172 and elem.getAttributeNode("a") is None
1173 and elem.getAttributeNode("b") is None
1174 and elem.getAttributeNode("c") is None
1175 and elem.getAttributeNode("p:d") is None
1176 and elem.getAttributeNodeNS(
1177 "http://xml.python.org/ns", "c") is None
1178 and elem.getAttributeNode("e").isSameNode(attr)
1179 and attrmap["e"].isSameNode(attr))
1180
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001181 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001182 "http://xml.python.org/ns", "xmlns")
1183 self.checkRenameNodeSharedConstraints(doc, attr)
1184 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001185
Collin Winterd28fcbc2007-03-28 23:34:06 +00001186 def testRenameElement(self):
1187 doc = parseString("<doc/>")
1188 elem = doc.documentElement
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001189
Collin Winterd28fcbc2007-03-28 23:34:06 +00001190 # Simple renaming
1191 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
1192 self.confirm(elem.tagName == "a"
1193 and elem.nodeName == "a"
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 # Rename to have a namespace, no prefix
1200 elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
1201 self.confirm(elem.tagName == "b"
1202 and elem.nodeName == "b"
1203 and elem.localName == "b"
1204 and elem.namespaceURI == "http://xml.python.org/ns"
1205 and elem.prefix is None
1206 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001207
Collin Winterd28fcbc2007-03-28 23:34:06 +00001208 # Rename to have a namespace, with prefix
1209 elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
1210 self.confirm(elem.tagName == "p:c"
1211 and elem.nodeName == "p:c"
1212 and elem.localName == "c"
1213 and elem.namespaceURI == "http://xml.python.org/ns2"
1214 and elem.prefix == "p"
1215 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001216
Collin Winterd28fcbc2007-03-28 23:34:06 +00001217 # Rename back to a simple non-NS node
1218 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
1219 self.confirm(elem.tagName == "d"
1220 and elem.nodeName == "d"
1221 and elem.localName is None
1222 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1223 and elem.prefix is None
1224 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001225
Collin Winterd28fcbc2007-03-28 23:34:06 +00001226 self.checkRenameNodeSharedConstraints(doc, elem)
1227 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001228
Collin Winterd28fcbc2007-03-28 23:34:06 +00001229 def testRenameOther(self):
1230 # We have to create a comment node explicitly since not all DOM
1231 # builders used with minidom add comments to the DOM.
1232 doc = xml.dom.minidom.getDOMImplementation().createDocument(
1233 xml.dom.EMPTY_NAMESPACE, "e", None)
1234 node = doc.createComment("comment")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001235 self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001236 xml.dom.EMPTY_NAMESPACE, "foo")
1237 doc.unlink()
1238
1239 def testWholeText(self):
1240 doc = parseString("<doc>a</doc>")
1241 elem = doc.documentElement
1242 text = elem.childNodes[0]
Ezio Melotti2623a372010-11-21 13:34:58 +00001243 self.assertEqual(text.nodeType, Node.TEXT_NODE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001244
Collin Winterd28fcbc2007-03-28 23:34:06 +00001245 self.checkWholeText(text, "a")
1246 elem.appendChild(doc.createTextNode("b"))
1247 self.checkWholeText(text, "ab")
1248 elem.insertBefore(doc.createCDATASection("c"), text)
1249 self.checkWholeText(text, "cab")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001250
Collin Winterd28fcbc2007-03-28 23:34:06 +00001251 # make sure we don't cross other nodes
1252 splitter = doc.createComment("comment")
1253 elem.appendChild(splitter)
1254 text2 = doc.createTextNode("d")
1255 elem.appendChild(text2)
1256 self.checkWholeText(text, "cab")
1257 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001258
Collin Winterd28fcbc2007-03-28 23:34:06 +00001259 x = doc.createElement("x")
1260 elem.replaceChild(x, splitter)
1261 splitter = x
1262 self.checkWholeText(text, "cab")
1263 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001264
Collin Winterd28fcbc2007-03-28 23:34:06 +00001265 x = doc.createProcessingInstruction("y", "z")
1266 elem.replaceChild(x, splitter)
1267 splitter = x
1268 self.checkWholeText(text, "cab")
1269 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001270
Collin Winterd28fcbc2007-03-28 23:34:06 +00001271 elem.removeChild(splitter)
1272 self.checkWholeText(text, "cabd")
1273 self.checkWholeText(text2, "cabd")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001274
Collin Winterd28fcbc2007-03-28 23:34:06 +00001275 def testPatch1094164(self):
1276 doc = parseString("<doc><e/></doc>")
1277 elem = doc.documentElement
1278 e = elem.firstChild
1279 self.confirm(e.parentNode is elem, "Before replaceChild()")
1280 # Check that replacing a child with itself leaves the tree unchanged
1281 elem.replaceChild(e, e)
1282 self.confirm(e.parentNode is elem, "After replaceChild()")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001283
Collin Winterd28fcbc2007-03-28 23:34:06 +00001284 def testReplaceWholeText(self):
1285 def setup():
1286 doc = parseString("<doc>a<e/>d</doc>")
1287 elem = doc.documentElement
1288 text1 = elem.firstChild
1289 text2 = elem.lastChild
1290 splitter = text1.nextSibling
1291 elem.insertBefore(doc.createTextNode("b"), splitter)
1292 elem.insertBefore(doc.createCDATASection("c"), text1)
1293 return doc, elem, text1, splitter, text2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001294
Collin Winterd28fcbc2007-03-28 23:34:06 +00001295 doc, elem, text1, splitter, text2 = setup()
1296 text = text1.replaceWholeText("new content")
1297 self.checkWholeText(text, "new content")
1298 self.checkWholeText(text2, "d")
1299 self.confirm(len(elem.childNodes) == 3)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001300
Collin Winterd28fcbc2007-03-28 23:34:06 +00001301 doc, elem, text1, splitter, text2 = setup()
1302 text = text2.replaceWholeText("new content")
1303 self.checkWholeText(text, "new content")
1304 self.checkWholeText(text1, "cab")
1305 self.confirm(len(elem.childNodes) == 5)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001306
Collin Winterd28fcbc2007-03-28 23:34:06 +00001307 doc, elem, text1, splitter, text2 = setup()
1308 text = text1.replaceWholeText("")
1309 self.checkWholeText(text2, "d")
1310 self.confirm(text is None
1311 and len(elem.childNodes) == 2)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001312
Collin Winterd28fcbc2007-03-28 23:34:06 +00001313 def testSchemaType(self):
1314 doc = parseString(
1315 "<!DOCTYPE doc [\n"
1316 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
1317 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
1318 " <!ATTLIST doc id ID #IMPLIED \n"
1319 " ref IDREF #IMPLIED \n"
1320 " refs IDREFS #IMPLIED \n"
1321 " enum (a|b) #IMPLIED \n"
1322 " ent ENTITY #IMPLIED \n"
1323 " ents ENTITIES #IMPLIED \n"
1324 " nm NMTOKEN #IMPLIED \n"
1325 " nms NMTOKENS #IMPLIED \n"
1326 " text CDATA #IMPLIED \n"
1327 " >\n"
1328 "]><doc id='name' notid='name' text='splat!' enum='b'"
1329 " ref='name' refs='name name' ent='e1' ents='e1 e2'"
1330 " nm='123' nms='123 abc' />")
1331 elem = doc.documentElement
1332 # We don't want to rely on any specific loader at this point, so
1333 # just make sure we can get to all the names, and that the
1334 # DTD-based namespace is right. The names can vary by loader
1335 # since each supports a different level of DTD information.
1336 t = elem.schemaType
1337 self.confirm(t.name is None
1338 and t.namespace == xml.dom.EMPTY_NAMESPACE)
1339 names = "id notid text enum ref refs ent ents nm nms".split()
1340 for name in names:
1341 a = elem.getAttributeNode(name)
1342 t = a.schemaType
1343 self.confirm(hasattr(t, "name")
1344 and t.namespace == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001345
Collin Winterd28fcbc2007-03-28 23:34:06 +00001346 def testSetIdAttribute(self):
1347 doc = parseString("<doc a1='v' a2='w'/>")
1348 e = doc.documentElement
1349 a1 = e.getAttributeNode("a1")
1350 a2 = e.getAttributeNode("a2")
1351 self.confirm(doc.getElementById("v") is None
1352 and not a1.isId
1353 and not a2.isId)
1354 e.setIdAttribute("a1")
1355 self.confirm(e.isSameNode(doc.getElementById("v"))
1356 and a1.isId
1357 and not a2.isId)
1358 e.setIdAttribute("a2")
1359 self.confirm(e.isSameNode(doc.getElementById("v"))
1360 and e.isSameNode(doc.getElementById("w"))
1361 and a1.isId
1362 and a2.isId)
1363 # replace the a1 node; the new node should *not* be an ID
1364 a3 = doc.createAttribute("a1")
1365 a3.value = "v"
1366 e.setAttributeNode(a3)
1367 self.confirm(doc.getElementById("v") is None
1368 and e.isSameNode(doc.getElementById("w"))
1369 and not a1.isId
1370 and a2.isId
1371 and not a3.isId)
1372 # renaming an attribute should not affect its ID-ness:
1373 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1374 self.confirm(e.isSameNode(doc.getElementById("w"))
1375 and a2.isId)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001376
Collin Winterd28fcbc2007-03-28 23:34:06 +00001377 def testSetIdAttributeNS(self):
1378 NS1 = "http://xml.python.org/ns1"
1379 NS2 = "http://xml.python.org/ns2"
1380 doc = parseString("<doc"
1381 " xmlns:ns1='" + NS1 + "'"
1382 " xmlns:ns2='" + NS2 + "'"
1383 " ns1:a1='v' ns2:a2='w'/>")
1384 e = doc.documentElement
1385 a1 = e.getAttributeNodeNS(NS1, "a1")
1386 a2 = e.getAttributeNodeNS(NS2, "a2")
1387 self.confirm(doc.getElementById("v") is None
1388 and not a1.isId
1389 and not a2.isId)
1390 e.setIdAttributeNS(NS1, "a1")
1391 self.confirm(e.isSameNode(doc.getElementById("v"))
1392 and a1.isId
1393 and not a2.isId)
1394 e.setIdAttributeNS(NS2, "a2")
1395 self.confirm(e.isSameNode(doc.getElementById("v"))
1396 and e.isSameNode(doc.getElementById("w"))
1397 and a1.isId
1398 and a2.isId)
1399 # replace the a1 node; the new node should *not* be an ID
1400 a3 = doc.createAttributeNS(NS1, "a1")
1401 a3.value = "v"
1402 e.setAttributeNode(a3)
1403 self.confirm(e.isSameNode(doc.getElementById("w")))
1404 self.confirm(not a1.isId)
1405 self.confirm(a2.isId)
1406 self.confirm(not a3.isId)
1407 self.confirm(doc.getElementById("v") is None)
1408 # renaming an attribute should not affect its ID-ness:
1409 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1410 self.confirm(e.isSameNode(doc.getElementById("w"))
1411 and a2.isId)
1412
1413 def testSetIdAttributeNode(self):
1414 NS1 = "http://xml.python.org/ns1"
1415 NS2 = "http://xml.python.org/ns2"
1416 doc = parseString("<doc"
1417 " xmlns:ns1='" + NS1 + "'"
1418 " xmlns:ns2='" + NS2 + "'"
1419 " ns1:a1='v' ns2:a2='w'/>")
1420 e = doc.documentElement
1421 a1 = e.getAttributeNodeNS(NS1, "a1")
1422 a2 = e.getAttributeNodeNS(NS2, "a2")
1423 self.confirm(doc.getElementById("v") is None
1424 and not a1.isId
1425 and not a2.isId)
1426 e.setIdAttributeNode(a1)
1427 self.confirm(e.isSameNode(doc.getElementById("v"))
1428 and a1.isId
1429 and not a2.isId)
1430 e.setIdAttributeNode(a2)
1431 self.confirm(e.isSameNode(doc.getElementById("v"))
1432 and e.isSameNode(doc.getElementById("w"))
1433 and a1.isId
1434 and a2.isId)
1435 # replace the a1 node; the new node should *not* be an ID
1436 a3 = doc.createAttributeNS(NS1, "a1")
1437 a3.value = "v"
1438 e.setAttributeNode(a3)
1439 self.confirm(e.isSameNode(doc.getElementById("w")))
1440 self.confirm(not a1.isId)
1441 self.confirm(a2.isId)
1442 self.confirm(not a3.isId)
1443 self.confirm(doc.getElementById("v") is None)
1444 # renaming an attribute should not affect its ID-ness:
1445 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1446 self.confirm(e.isSameNode(doc.getElementById("w"))
1447 and a2.isId)
1448
1449 def testPickledDocument(self):
1450 doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
1451 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
1452 " 'http://xml.python.org/system' [\n"
1453 " <!ELEMENT e EMPTY>\n"
1454 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
1455 "]><doc attr='value'> text\n"
1456 "<?pi sample?> <!-- comment --> <e/> </doc>")
1457 s = pickle.dumps(doc)
1458 doc2 = pickle.loads(s)
1459 stack = [(doc, doc2)]
1460 while stack:
1461 n1, n2 = stack.pop()
1462 self.confirm(n1.nodeType == n2.nodeType
1463 and len(n1.childNodes) == len(n2.childNodes)
1464 and n1.nodeName == n2.nodeName
1465 and not n1.isSameNode(n2)
1466 and not n2.isSameNode(n1))
1467 if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
1468 len(n1.entities)
1469 len(n2.entities)
1470 len(n1.notations)
1471 len(n2.notations)
1472 self.confirm(len(n1.entities) == len(n2.entities)
1473 and len(n1.notations) == len(n2.notations))
1474 for i in range(len(n1.notations)):
Georg Brandlcd4a21b2010-02-06 23:34:10 +00001475 # XXX this loop body doesn't seem to be executed?
Collin Winterd28fcbc2007-03-28 23:34:06 +00001476 no1 = n1.notations.item(i)
1477 no2 = n1.notations.item(i)
1478 self.confirm(no1.name == no2.name
1479 and no1.publicId == no2.publicId
1480 and no1.systemId == no2.systemId)
Georg Brandlcd4a21b2010-02-06 23:34:10 +00001481 stack.append((no1, no2))
Collin Winterd28fcbc2007-03-28 23:34:06 +00001482 for i in range(len(n1.entities)):
1483 e1 = n1.entities.item(i)
1484 e2 = n2.entities.item(i)
1485 self.confirm(e1.notationName == e2.notationName
1486 and e1.publicId == e2.publicId
1487 and e1.systemId == e2.systemId)
1488 stack.append((e1, e2))
1489 if n1.nodeType != Node.DOCUMENT_NODE:
1490 self.confirm(n1.ownerDocument.isSameNode(doc)
1491 and n2.ownerDocument.isSameNode(doc2))
1492 for i in range(len(n1.childNodes)):
1493 stack.append((n1.childNodes[i], n2.childNodes[i]))
1494
Martin v. Löwis27e4a172008-05-23 15:18:28 +00001495 def testSerializeCommentNodeWithDoubleHyphen(self):
1496 doc = create_doc_without_doctype()
1497 doc.appendChild(doc.createComment("foo--bar"))
1498 self.assertRaises(ValueError, doc.toxml)
1499
Georg Brandl5ded7912010-11-26 07:35:31 +00001500 def testEmptyXMLNSValue(self):
1501 doc = parseString("<element xmlns=''>\n"
1502 "<foo/>\n</element>")
1503 doc2 = parseString(doc.toxml())
1504 self.confirm(doc2.namespaceURI == xml.dom.EMPTY_NAMESPACE)
1505
1506
Collin Winterd28fcbc2007-03-28 23:34:06 +00001507def test_main():
1508 run_unittest(MinidomTest)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001509
Collin Winterd28fcbc2007-03-28 23:34:06 +00001510if __name__ == "__main__":
1511 test_main()