blob: fcc4c8fec3728426da657185f74a691fe1eba207 [file] [log] [blame]
Fred Drakefbdeaad2006-07-29 16:56:15 +00001# test for xml.dom.minidom
Paul Prescod7993bcc2000-07-01 14:54:16 +00002
Guido van Rossume2ae77b2001-10-24 20:42:55 +00003import os
Fred Drake17647f52000-07-03 16:37:42 +00004import sys
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +00005import pickle
Fred Drake17647f52000-07-03 16:37:42 +00006import traceback
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +00007from StringIO import StringIO
Collin Winterd28fcbc2007-03-28 23:34:06 +00008from test.test_support import verbose, run_unittest, TestSkipped
9import unittest
Fred Drake17647f52000-07-03 16:37:42 +000010
Fred Drakefbdeaad2006-07-29 16:56:15 +000011import xml.dom
12import xml.dom.minidom
13import xml.parsers.expat
Fred Drakec441f7b2002-07-19 22:16:41 +000014
Fred Drakefbdeaad2006-07-29 16:56:15 +000015from xml.dom.minidom import parse, Node, Document, parseString
16from xml.dom.minidom import getDOMImplementation
Martin v. Löwisfd6aaa12003-01-25 22:02:52 +000017
Fred Drakec441f7b2002-07-19 22:16:41 +000018
Fred Drake17647f52000-07-03 16:37:42 +000019if __name__ == "__main__":
20 base = sys.argv[0]
21else:
22 base = __file__
Guido van Rossume2ae77b2001-10-24 20:42:55 +000023tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml")
Fred Drake17647f52000-07-03 16:37:42 +000024del base
Paul Prescod7993bcc2000-07-01 14:54:16 +000025
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000026# The tests of DocumentType importing use these helpers to construct
27# the documents to work with, since not all DOM builders actually
28# create the DocumentType nodes.
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000029def create_doc_without_doctype(doctype=None):
30 return getDOMImplementation().createDocument(None, "doc", doctype)
31
32def create_nonempty_doctype():
33 doctype = getDOMImplementation().createDocumentType("doc", None, None)
34 doctype.entities._seq = []
35 doctype.notations._seq = []
Fred Drakefbdeaad2006-07-29 16:56:15 +000036 notation = xml.dom.minidom.Notation("my-notation", None,
37 "http://xml.python.org/notations/my")
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000038 doctype.notations._seq.append(notation)
Fred Drakefbdeaad2006-07-29 16:56:15 +000039 entity = xml.dom.minidom.Entity("my-entity", None,
40 "http://xml.python.org/entities/my",
41 "my-notation")
Martin v. Löwisaa5af8d2003-01-25 21:39:09 +000042 entity.version = "1.0"
43 entity.encoding = "utf-8"
44 entity.actualEncoding = "us-ascii"
45 doctype.entities._seq.append(entity)
46 return doctype
47
48def create_doc_with_doctype():
49 doctype = create_nonempty_doctype()
50 doc = create_doc_without_doctype(doctype)
51 doctype.entities.item(0).ownerDocument = doc
52 doctype.notations.item(0).ownerDocument = doc
53 return doc
54
Collin Winterd28fcbc2007-03-28 23:34:06 +000055class MinidomTest(unittest.TestCase):
56 def tearDown(self):
Paul Prescod7993bcc2000-07-01 14:54:16 +000057 try:
Collin Winterd28fcbc2007-03-28 23:34:06 +000058 Node.allnodes
59 except AttributeError:
60 # We don't actually have the minidom from the standard library,
61 # but are picking up the PyXML version from site-packages.
62 pass
63 else:
64 self.confirm(len(Node.allnodes) == 0,
65 "assertion: len(Node.allnodes) == 0")
66 if len(Node.allnodes):
67 print "Garbage left over:"
68 if verbose:
69 print Node.allnodes.items()[0:10]
70 else:
71 # Don't print specific nodes if repeatable results
72 # are needed
73 print len(Node.allnodes)
Jeremy Hylton3b0c6002000-10-12 17:31:36 +000074 Node.allnodes = {}
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000075
Collin Winterd28fcbc2007-03-28 23:34:06 +000076 def confirm(self, test, testname = "Test"):
77 self.assertTrue(test, testname)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000078
Collin Winterd28fcbc2007-03-28 23:34:06 +000079 def checkWholeText(self, node, s):
80 t = node.wholeText
81 self.confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000082
Collin Winterd28fcbc2007-03-28 23:34:06 +000083 def testParseFromFile(self):
84 dom = parse(StringIO(open(tstfile).read()))
85 dom.unlink()
86 self.confirm(isinstance(dom,Document))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000087
Collin Winterd28fcbc2007-03-28 23:34:06 +000088 def testGetElementsByTagName(self):
89 dom = parse(tstfile)
90 self.confirm(dom.getElementsByTagName("LI") == \
91 dom.documentElement.getElementsByTagName("LI"))
92 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +000093
Collin Winterd28fcbc2007-03-28 23:34:06 +000094 def testInsertBefore(self):
95 dom = parseString("<doc><foo/></doc>")
96 root = dom.documentElement
97 elem = root.childNodes[0]
98 nelem = dom.createElement("element")
99 root.insertBefore(nelem, elem)
100 self.confirm(len(root.childNodes) == 2
101 and root.childNodes.length == 2
102 and root.childNodes[0] is nelem
103 and root.childNodes.item(0) is nelem
104 and root.childNodes[1] is elem
105 and root.childNodes.item(1) is elem
106 and root.firstChild is nelem
107 and root.lastChild is elem
108 and root.toxml() == "<doc><element/><foo/></doc>"
109 , "testInsertBefore -- node properly placed in tree")
110 nelem = dom.createElement("element")
111 root.insertBefore(nelem, None)
112 self.confirm(len(root.childNodes) == 3
113 and root.childNodes.length == 3
114 and root.childNodes[1] is elem
115 and root.childNodes.item(1) is elem
116 and root.childNodes[2] is nelem
117 and root.childNodes.item(2) is nelem
118 and root.lastChild is nelem
119 and nelem.previousSibling is elem
120 and root.toxml() == "<doc><element/><foo/><element/></doc>"
121 , "testInsertBefore -- node properly placed in tree")
122 nelem2 = dom.createElement("bar")
123 root.insertBefore(nelem2, nelem)
124 self.confirm(len(root.childNodes) == 4
125 and root.childNodes.length == 4
126 and root.childNodes[2] is nelem2
127 and root.childNodes.item(2) is nelem2
128 and root.childNodes[3] is nelem
129 and root.childNodes.item(3) is nelem
130 and nelem2.nextSibling is nelem
131 and nelem.previousSibling is nelem2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000132 and root.toxml() ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000133 "<doc><element/><foo/><bar/><element/></doc>"
134 , "testInsertBefore -- node properly placed in tree")
135 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000136
Collin Winterd28fcbc2007-03-28 23:34:06 +0000137 def _create_fragment_test_nodes(self):
138 dom = parseString("<doc/>")
139 orig = dom.createTextNode("original")
140 c1 = dom.createTextNode("foo")
141 c2 = dom.createTextNode("bar")
142 c3 = dom.createTextNode("bat")
143 dom.documentElement.appendChild(orig)
144 frag = dom.createDocumentFragment()
145 frag.appendChild(c1)
146 frag.appendChild(c2)
147 frag.appendChild(c3)
148 return dom, orig, c1, c2, c3, frag
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000149
Collin Winterd28fcbc2007-03-28 23:34:06 +0000150 def testInsertBeforeFragment(self):
151 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
152 dom.documentElement.insertBefore(frag, None)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000153 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000154 (orig, c1, c2, c3),
155 "insertBefore(<fragment>, None)")
156 frag.unlink()
157 dom.unlink()
Paul Prescod10d27662000-09-18 19:07:26 +0000158
Collin Winterd28fcbc2007-03-28 23:34:06 +0000159 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
160 dom.documentElement.insertBefore(frag, orig)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000161 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000162 (c1, c2, c3, orig),
163 "insertBefore(<fragment>, orig)")
164 frag.unlink()
165 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000166
Collin Winterd28fcbc2007-03-28 23:34:06 +0000167 def testAppendChild(self):
168 dom = parse(tstfile)
169 dom.documentElement.appendChild(dom.createComment(u"Hello"))
170 self.confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
171 self.confirm(dom.documentElement.childNodes[-1].data == "Hello")
172 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000173
Collin Winterd28fcbc2007-03-28 23:34:06 +0000174 def testAppendChildFragment(self):
175 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
176 dom.documentElement.appendChild(frag)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000177 self.confirm(tuple(dom.documentElement.childNodes) ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000178 (orig, c1, c2, c3),
179 "appendChild(<fragment>)")
180 frag.unlink()
181 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000182
Collin Winterd28fcbc2007-03-28 23:34:06 +0000183 def testReplaceChildFragment(self):
184 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
185 dom.documentElement.replaceChild(frag, orig)
186 orig.unlink()
187 self.confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
188 "replaceChild(<fragment>)")
189 frag.unlink()
190 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000191
Collin Winterd28fcbc2007-03-28 23:34:06 +0000192 def testLegalChildren(self):
193 dom = Document()
194 elem = dom.createElement('element')
195 text = dom.createTextNode('text')
196 self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000197
Collin Winterd28fcbc2007-03-28 23:34:06 +0000198 dom.appendChild(elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000199 self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000200 elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000201 self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000202 elem)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000203
Collin Winterd28fcbc2007-03-28 23:34:06 +0000204 nodemap = elem.attributes
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000205 self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000206 text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000207 self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000208 text)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000209
Collin Winterd28fcbc2007-03-28 23:34:06 +0000210 elem.appendChild(text)
211 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000212
Collin Winterd28fcbc2007-03-28 23:34:06 +0000213 def testNamedNodeMapSetItem(self):
214 dom = Document()
215 elem = dom.createElement('element')
216 attrs = elem.attributes
217 attrs["foo"] = "bar"
218 a = attrs.item(0)
219 self.confirm(a.ownerDocument is dom,
220 "NamedNodeMap.__setitem__() sets ownerDocument")
221 self.confirm(a.ownerElement is elem,
222 "NamedNodeMap.__setitem__() sets ownerElement")
223 self.confirm(a.value == "bar",
224 "NamedNodeMap.__setitem__() sets value")
225 self.confirm(a.nodeValue == "bar",
226 "NamedNodeMap.__setitem__() sets nodeValue")
227 elem.unlink()
228 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000229
Collin Winterd28fcbc2007-03-28 23:34:06 +0000230 def testNonZero(self):
231 dom = parse(tstfile)
232 self.confirm(dom)# should not be zero
233 dom.appendChild(dom.createComment("foo"))
234 self.confirm(not dom.childNodes[-1].childNodes)
235 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000236
Collin Winterd28fcbc2007-03-28 23:34:06 +0000237 def testUnlink(self):
238 dom = parse(tstfile)
239 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000240
Collin Winterd28fcbc2007-03-28 23:34:06 +0000241 def testElement(self):
242 dom = Document()
243 dom.appendChild(dom.createElement("abc"))
244 self.confirm(dom.documentElement)
245 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000246
Collin Winterd28fcbc2007-03-28 23:34:06 +0000247 def testAAA(self):
248 dom = parseString("<abc/>")
249 el = dom.documentElement
250 el.setAttribute("spam", "jam2")
251 self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
252 a = el.getAttributeNode("spam")
253 self.confirm(a.ownerDocument is dom,
254 "setAttribute() sets ownerDocument")
255 self.confirm(a.ownerElement is dom.documentElement,
256 "setAttribute() sets ownerElement")
257 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000258
Collin Winterd28fcbc2007-03-28 23:34:06 +0000259 def testAAB(self):
260 dom = parseString("<abc/>")
261 el = dom.documentElement
262 el.setAttribute("spam", "jam")
263 el.setAttribute("spam", "jam2")
264 self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
265 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000266
Collin Winterd28fcbc2007-03-28 23:34:06 +0000267 def testAddAttr(self):
268 dom = Document()
269 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000270
Collin Winterd28fcbc2007-03-28 23:34:06 +0000271 child.setAttribute("def", "ghi")
272 self.confirm(child.getAttribute("def") == "ghi")
273 self.confirm(child.attributes["def"].value == "ghi")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000274
Collin Winterd28fcbc2007-03-28 23:34:06 +0000275 child.setAttribute("jkl", "mno")
276 self.confirm(child.getAttribute("jkl") == "mno")
277 self.confirm(child.attributes["jkl"].value == "mno")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000278
Collin Winterd28fcbc2007-03-28 23:34:06 +0000279 self.confirm(len(child.attributes) == 2)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000280
Collin Winterd28fcbc2007-03-28 23:34:06 +0000281 child.setAttribute("def", "newval")
282 self.confirm(child.getAttribute("def") == "newval")
283 self.confirm(child.attributes["def"].value == "newval")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000284
Collin Winterd28fcbc2007-03-28 23:34:06 +0000285 self.confirm(len(child.attributes) == 2)
286 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000287
Collin Winterd28fcbc2007-03-28 23:34:06 +0000288 def testDeleteAttr(self):
289 dom = Document()
290 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000291
Collin Winterd28fcbc2007-03-28 23:34:06 +0000292 self.confirm(len(child.attributes) == 0)
293 child.setAttribute("def", "ghi")
294 self.confirm(len(child.attributes) == 1)
295 del child.attributes["def"]
296 self.confirm(len(child.attributes) == 0)
297 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000298
Collin Winterd28fcbc2007-03-28 23:34:06 +0000299 def testRemoveAttr(self):
300 dom = Document()
301 child = dom.appendChild(dom.createElement("abc"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000302
Collin Winterd28fcbc2007-03-28 23:34:06 +0000303 child.setAttribute("def", "ghi")
304 self.confirm(len(child.attributes) == 1)
305 child.removeAttribute("def")
306 self.confirm(len(child.attributes) == 0)
307 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000308
Collin Winterd28fcbc2007-03-28 23:34:06 +0000309 def testRemoveAttrNS(self):
310 dom = Document()
311 child = dom.appendChild(
312 dom.createElementNS("http://www.python.org", "python:abc"))
313 child.setAttributeNS("http://www.w3.org", "xmlns:python",
314 "http://www.python.org")
315 child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
316 self.confirm(len(child.attributes) == 2)
317 child.removeAttributeNS("http://www.python.org", "abcattr")
318 self.confirm(len(child.attributes) == 1)
319 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000320
Collin Winterd28fcbc2007-03-28 23:34:06 +0000321 def testRemoveAttributeNode(self):
322 dom = Document()
323 child = dom.appendChild(dom.createElement("foo"))
324 child.setAttribute("spam", "jam")
325 self.confirm(len(child.attributes) == 1)
326 node = child.getAttributeNode("spam")
327 child.removeAttributeNode(node)
328 self.confirm(len(child.attributes) == 0
329 and child.getAttributeNode("spam") is None)
330 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000331
Collin Winterd28fcbc2007-03-28 23:34:06 +0000332 def testChangeAttr(self):
333 dom = parseString("<abc/>")
334 el = dom.documentElement
335 el.setAttribute("spam", "jam")
336 self.confirm(len(el.attributes) == 1)
337 el.setAttribute("spam", "bam")
338 # Set this attribute to be an ID and make sure that doesn't change
339 # when changing the value:
340 el.setIdAttribute("spam")
341 self.confirm(len(el.attributes) == 1
342 and el.attributes["spam"].value == "bam"
343 and el.attributes["spam"].nodeValue == "bam"
344 and el.getAttribute("spam") == "bam"
345 and el.getAttributeNode("spam").isId)
346 el.attributes["spam"] = "ham"
347 self.confirm(len(el.attributes) == 1
348 and el.attributes["spam"].value == "ham"
349 and el.attributes["spam"].nodeValue == "ham"
350 and el.getAttribute("spam") == "ham"
351 and el.attributes["spam"].isId)
352 el.setAttribute("spam2", "bam")
353 self.confirm(len(el.attributes) == 2
354 and el.attributes["spam"].value == "ham"
355 and el.attributes["spam"].nodeValue == "ham"
356 and el.getAttribute("spam") == "ham"
357 and el.attributes["spam2"].value == "bam"
358 and el.attributes["spam2"].nodeValue == "bam"
359 and el.getAttribute("spam2") == "bam")
360 el.attributes["spam2"] = "bam2"
361 self.confirm(len(el.attributes) == 2
362 and el.attributes["spam"].value == "ham"
363 and el.attributes["spam"].nodeValue == "ham"
364 and el.getAttribute("spam") == "ham"
365 and el.attributes["spam2"].value == "bam2"
366 and el.attributes["spam2"].nodeValue == "bam2"
367 and el.getAttribute("spam2") == "bam2")
368 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000369
Collin Winterd28fcbc2007-03-28 23:34:06 +0000370 def testGetAttrList(self):
371 pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000372
Collin Winterd28fcbc2007-03-28 23:34:06 +0000373 def testGetAttrValues(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000374
Collin Winterd28fcbc2007-03-28 23:34:06 +0000375 def testGetAttrLength(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000376
Collin Winterd28fcbc2007-03-28 23:34:06 +0000377 def testGetAttribute(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000378
Collin Winterd28fcbc2007-03-28 23:34:06 +0000379 def testGetAttributeNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000380
Collin Winterd28fcbc2007-03-28 23:34:06 +0000381 def testGetAttributeNode(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000382
Collin Winterd28fcbc2007-03-28 23:34:06 +0000383 def testGetElementsByTagNameNS(self):
384 d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
385 <minidom:myelem/>
386 </foo>"""
387 dom = parseString(d)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000388 elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom",
Collin Winterd28fcbc2007-03-28 23:34:06 +0000389 "myelem")
390 self.confirm(len(elems) == 1
391 and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"
392 and elems[0].localName == "myelem"
393 and elems[0].prefix == "minidom"
394 and elems[0].tagName == "minidom:myelem"
395 and elems[0].nodeName == "minidom:myelem")
396 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000397
398 def get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000399 lname):
400 nodelist = doc.getElementsByTagNameNS(nsuri, lname)
401 self.confirm(len(nodelist) == 0)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000402
Collin Winterd28fcbc2007-03-28 23:34:06 +0000403 def testGetEmptyNodeListFromElementsByTagNameNS(self):
404 doc = parseString('<doc/>')
405 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
406 doc, 'http://xml.python.org/namespaces/a', 'localname')
407 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
408 doc, '*', 'splat')
409 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
410 doc, 'http://xml.python.org/namespaces/a', '*')
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000411
Collin Winterd28fcbc2007-03-28 23:34:06 +0000412 doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
413 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
414 doc, "http://xml.python.org/splat", "not-there")
415 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
416 doc, "*", "not-there")
417 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
418 doc, "http://somewhere.else.net/not-there", "e")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000419
Collin Winterd28fcbc2007-03-28 23:34:06 +0000420 def testElementReprAndStr(self):
421 dom = Document()
422 el = dom.appendChild(dom.createElement("abc"))
423 string1 = repr(el)
424 string2 = str(el)
425 self.confirm(string1 == string2)
426 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000427
Collin Winterd28fcbc2007-03-28 23:34:06 +0000428 def testElementReprAndStrUnicode(self):
429 dom = Document()
430 el = dom.appendChild(dom.createElement(u"abc"))
431 string1 = repr(el)
432 string2 = str(el)
433 self.confirm(string1 == string2)
434 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000435
Collin Winterd28fcbc2007-03-28 23:34:06 +0000436 def testElementReprAndStrUnicodeNS(self):
437 dom = Document()
438 el = dom.appendChild(
439 dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
440 string1 = repr(el)
441 string2 = str(el)
442 self.confirm(string1 == string2)
443 self.confirm(string1.find("slash:abc") != -1)
444 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000445
Collin Winterd28fcbc2007-03-28 23:34:06 +0000446 def testAttributeRepr(self):
447 dom = Document()
448 el = dom.appendChild(dom.createElement(u"abc"))
449 node = el.setAttribute("abc", "def")
450 self.confirm(str(node) == repr(node))
451 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000452
Collin Winterd28fcbc2007-03-28 23:34:06 +0000453 def testTextNodeRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000454
Collin Winterd28fcbc2007-03-28 23:34:06 +0000455 def testWriteXML(self):
456 str = '<?xml version="1.0" ?><a b="c"/>'
457 dom = parseString(str)
458 domstr = dom.toxml()
459 dom.unlink()
460 self.confirm(str == domstr)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000461
Collin Winterd28fcbc2007-03-28 23:34:06 +0000462 def testAltNewline(self):
463 str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
464 dom = parseString(str)
465 domstr = dom.toprettyxml(newl="\r\n")
466 dom.unlink()
467 self.confirm(domstr == str.replace("\n", "\r\n"))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000468
Collin Winterd28fcbc2007-03-28 23:34:06 +0000469 def testProcessingInstruction(self):
470 dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
471 pi = dom.documentElement.firstChild
472 self.confirm(pi.target == "mypi"
473 and pi.data == "data \t\n "
474 and pi.nodeName == "mypi"
475 and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
476 and pi.attributes is None
477 and not pi.hasChildNodes()
478 and len(pi.childNodes) == 0
479 and pi.firstChild is None
480 and pi.lastChild is None
481 and pi.localName is None
482 and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000483
Collin Winterd28fcbc2007-03-28 23:34:06 +0000484 def testProcessingInstructionRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000485
Collin Winterd28fcbc2007-03-28 23:34:06 +0000486 def testTextRepr(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000487
Collin Winterd28fcbc2007-03-28 23:34:06 +0000488 def testWriteText(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000489
Collin Winterd28fcbc2007-03-28 23:34:06 +0000490 def testDocumentElement(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000491
Collin Winterd28fcbc2007-03-28 23:34:06 +0000492 def testTooManyDocumentElements(self):
493 doc = parseString("<doc/>")
494 elem = doc.createElement("extra")
495 # Should raise an exception when adding an extra document element.
496 self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem)
497 elem.unlink()
498 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000499
Collin Winterd28fcbc2007-03-28 23:34:06 +0000500 def testCreateElementNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000501
Collin Winterd28fcbc2007-03-28 23:34:06 +0000502 def testCreateAttributeNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000503
Collin Winterd28fcbc2007-03-28 23:34:06 +0000504 def testParse(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000505
Collin Winterd28fcbc2007-03-28 23:34:06 +0000506 def testParseString(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000507
Collin Winterd28fcbc2007-03-28 23:34:06 +0000508 def testComment(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000509
Collin Winterd28fcbc2007-03-28 23:34:06 +0000510 def testAttrListItem(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000511
Collin Winterd28fcbc2007-03-28 23:34:06 +0000512 def testAttrListItems(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000513
Collin Winterd28fcbc2007-03-28 23:34:06 +0000514 def testAttrListItemNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000515
Collin Winterd28fcbc2007-03-28 23:34:06 +0000516 def testAttrListKeys(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000517
Collin Winterd28fcbc2007-03-28 23:34:06 +0000518 def testAttrListKeysNS(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000519
Collin Winterd28fcbc2007-03-28 23:34:06 +0000520 def testRemoveNamedItem(self):
521 doc = parseString("<doc a=''/>")
522 e = doc.documentElement
523 attrs = e.attributes
524 a1 = e.getAttributeNode("a")
525 a2 = attrs.removeNamedItem("a")
526 self.confirm(a1.isSameNode(a2))
527 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000528
Collin Winterd28fcbc2007-03-28 23:34:06 +0000529 def testRemoveNamedItemNS(self):
530 doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
531 e = doc.documentElement
532 attrs = e.attributes
533 a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
534 a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
535 self.confirm(a1.isSameNode(a2))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000536 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000537 "http://xml.python.org/", "b")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000538
Collin Winterd28fcbc2007-03-28 23:34:06 +0000539 def testAttrListValues(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000540
Collin Winterd28fcbc2007-03-28 23:34:06 +0000541 def testAttrListLength(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000542
Collin Winterd28fcbc2007-03-28 23:34:06 +0000543 def testAttrList__getitem__(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000544
Collin Winterd28fcbc2007-03-28 23:34:06 +0000545 def testAttrList__setitem__(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000546
Collin Winterd28fcbc2007-03-28 23:34:06 +0000547 def testSetAttrValueandNodeValue(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000548
Collin Winterd28fcbc2007-03-28 23:34:06 +0000549 def testParseElement(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000550
Collin Winterd28fcbc2007-03-28 23:34:06 +0000551 def testParseAttributes(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000552
Collin Winterd28fcbc2007-03-28 23:34:06 +0000553 def testParseElementNamespaces(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000554
Collin Winterd28fcbc2007-03-28 23:34:06 +0000555 def testParseAttributeNamespaces(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000556
Collin Winterd28fcbc2007-03-28 23:34:06 +0000557 def testParseProcessingInstructions(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000558
Collin Winterd28fcbc2007-03-28 23:34:06 +0000559 def testChildNodes(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000560
Collin Winterd28fcbc2007-03-28 23:34:06 +0000561 def testFirstChild(self): pass
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000562
Collin Winterd28fcbc2007-03-28 23:34:06 +0000563 def testHasChildNodes(self): pass
564
565 def _testCloneElementCopiesAttributes(self, e1, e2, test):
566 attrs1 = e1.attributes
567 attrs2 = e2.attributes
568 keys1 = attrs1.keys()
569 keys2 = attrs2.keys()
570 keys1.sort()
571 keys2.sort()
572 self.confirm(keys1 == keys2, "clone of element has same attribute keys")
573 for i in range(len(keys1)):
574 a1 = attrs1.item(i)
575 a2 = attrs2.item(i)
576 self.confirm(a1 is not a2
577 and a1.value == a2.value
578 and a1.nodeValue == a2.nodeValue
579 and a1.namespaceURI == a2.namespaceURI
580 and a1.localName == a2.localName
581 , "clone of attribute node has proper attribute values")
582 self.confirm(a2.ownerElement is e2,
583 "clone of attribute node correctly owned")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000584
Collin Winterd28fcbc2007-03-28 23:34:06 +0000585 def _setupCloneElement(self, deep):
586 dom = parseString("<doc attr='value'><foo/></doc>")
587 root = dom.documentElement
588 clone = root.cloneNode(deep)
589 self._testCloneElementCopiesAttributes(
590 root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
591 # mutilate the original so shared data is detected
592 root.tagName = root.nodeName = "MODIFIED"
593 root.setAttribute("attr", "NEW VALUE")
594 root.setAttribute("added", "VALUE")
595 return dom, clone
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000596
Collin Winterd28fcbc2007-03-28 23:34:06 +0000597 def testCloneElementShallow(self):
598 dom, clone = self._setupCloneElement(0)
599 self.confirm(len(clone.childNodes) == 0
600 and clone.childNodes.length == 0
601 and clone.parentNode is None
602 and clone.toxml() == '<doc attr="value"/>'
603 , "testCloneElementShallow")
604 dom.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000605
Collin Winterd28fcbc2007-03-28 23:34:06 +0000606 def testCloneElementDeep(self):
607 dom, clone = self._setupCloneElement(1)
608 self.confirm(len(clone.childNodes) == 1
609 and clone.childNodes.length == 1
610 and clone.parentNode is None
611 and clone.toxml() == '<doc attr="value"><foo/></doc>'
612 , "testCloneElementDeep")
613 dom.unlink()
614
615 def testCloneDocumentShallow(self):
616 doc = parseString("<?xml version='1.0'?>\n"
617 "<!-- comment -->"
618 "<!DOCTYPE doc [\n"
619 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
620 "]>\n"
621 "<doc attr='value'/>")
622 doc2 = doc.cloneNode(0)
623 self.confirm(doc2 is None,
624 "testCloneDocumentShallow:"
625 " shallow cloning of documents makes no sense!")
626
627 def testCloneDocumentDeep(self):
628 doc = parseString("<?xml version='1.0'?>\n"
629 "<!-- comment -->"
630 "<!DOCTYPE doc [\n"
631 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
632 "]>\n"
633 "<doc attr='value'/>")
634 doc2 = doc.cloneNode(1)
635 self.confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
636 "testCloneDocumentDeep: document objects not distinct")
637 self.confirm(len(doc.childNodes) == len(doc2.childNodes),
638 "testCloneDocumentDeep: wrong number of Document children")
639 self.confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
640 "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
641 self.confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
642 "testCloneDocumentDeep: documentElement owner is not new document")
643 self.confirm(not doc.documentElement.isSameNode(doc2.documentElement),
644 "testCloneDocumentDeep: documentElement should not be shared")
645 if doc.doctype is not None:
646 # check the doctype iff the original DOM maintained it
647 self.confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
648 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
649 self.confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
650 self.confirm(not doc.doctype.isSameNode(doc2.doctype))
651
652 def testCloneDocumentTypeDeepOk(self):
653 doctype = create_nonempty_doctype()
654 clone = doctype.cloneNode(1)
655 self.confirm(clone is not None
656 and clone.nodeName == doctype.nodeName
657 and clone.name == doctype.name
658 and clone.publicId == doctype.publicId
659 and clone.systemId == doctype.systemId
660 and len(clone.entities) == len(doctype.entities)
661 and clone.entities.item(len(clone.entities)) is None
662 and len(clone.notations) == len(doctype.notations)
663 and clone.notations.item(len(clone.notations)) is None
664 and len(clone.childNodes) == 0)
665 for i in range(len(doctype.entities)):
666 se = doctype.entities.item(i)
667 ce = clone.entities.item(i)
668 self.confirm((not se.isSameNode(ce))
669 and (not ce.isSameNode(se))
670 and ce.nodeName == se.nodeName
671 and ce.notationName == se.notationName
672 and ce.publicId == se.publicId
673 and ce.systemId == se.systemId
674 and ce.encoding == se.encoding
675 and ce.actualEncoding == se.actualEncoding
676 and ce.version == se.version)
677 for i in range(len(doctype.notations)):
678 sn = doctype.notations.item(i)
679 cn = clone.notations.item(i)
680 self.confirm((not sn.isSameNode(cn))
681 and (not cn.isSameNode(sn))
682 and cn.nodeName == sn.nodeName
683 and cn.publicId == sn.publicId
684 and cn.systemId == sn.systemId)
685
686 def testCloneDocumentTypeDeepNotOk(self):
687 doc = create_doc_with_doctype()
688 clone = doc.doctype.cloneNode(1)
689 self.confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
690
691 def testCloneDocumentTypeShallowOk(self):
692 doctype = create_nonempty_doctype()
693 clone = doctype.cloneNode(0)
694 self.confirm(clone is not None
695 and clone.nodeName == doctype.nodeName
696 and clone.name == doctype.name
697 and clone.publicId == doctype.publicId
698 and clone.systemId == doctype.systemId
699 and len(clone.entities) == 0
700 and clone.entities.item(0) is None
701 and len(clone.notations) == 0
702 and clone.notations.item(0) is None
703 and len(clone.childNodes) == 0)
704
705 def testCloneDocumentTypeShallowNotOk(self):
706 doc = create_doc_with_doctype()
707 clone = doc.doctype.cloneNode(0)
708 self.confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
709
710 def check_import_document(self, deep, testName):
711 doc1 = parseString("<doc/>")
712 doc2 = parseString("<doc/>")
713 self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000714
Collin Winterd28fcbc2007-03-28 23:34:06 +0000715 def testImportDocumentShallow(self):
716 self.check_import_document(0, "testImportDocumentShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000717
Collin Winterd28fcbc2007-03-28 23:34:06 +0000718 def testImportDocumentDeep(self):
719 self.check_import_document(1, "testImportDocumentDeep")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000720
Collin Winterd28fcbc2007-03-28 23:34:06 +0000721 def testImportDocumentTypeShallow(self):
722 src = create_doc_with_doctype()
723 target = create_doc_without_doctype()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000724 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000725 src.doctype, 0)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000726
Collin Winterd28fcbc2007-03-28 23:34:06 +0000727 def testImportDocumentTypeDeep(self):
728 src = create_doc_with_doctype()
729 target = create_doc_without_doctype()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000730 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000731 src.doctype, 1)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000732
Collin Winterd28fcbc2007-03-28 23:34:06 +0000733 # Testing attribute clones uses a helper, and should always be deep,
734 # even if the argument to cloneNode is false.
735 def check_clone_attribute(self, deep, testName):
736 doc = parseString("<doc attr='value'/>")
737 attr = doc.documentElement.getAttributeNode("attr")
738 self.failIfEqual(attr, None)
739 clone = attr.cloneNode(deep)
740 self.confirm(not clone.isSameNode(attr))
741 self.confirm(not attr.isSameNode(clone))
742 self.confirm(clone.ownerElement is None,
743 testName + ": ownerElement should be None")
744 self.confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
745 testName + ": ownerDocument does not match")
746 self.confirm(clone.specified,
747 testName + ": cloned attribute must have specified == True")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000748
Collin Winterd28fcbc2007-03-28 23:34:06 +0000749 def testCloneAttributeShallow(self):
750 self.check_clone_attribute(0, "testCloneAttributeShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000751
Collin Winterd28fcbc2007-03-28 23:34:06 +0000752 def testCloneAttributeDeep(self):
753 self.check_clone_attribute(1, "testCloneAttributeDeep")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000754
Collin Winterd28fcbc2007-03-28 23:34:06 +0000755 def check_clone_pi(self, deep, testName):
756 doc = parseString("<?target data?><doc/>")
757 pi = doc.firstChild
758 self.assertEquals(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE)
759 clone = pi.cloneNode(deep)
760 self.confirm(clone.target == pi.target
761 and clone.data == pi.data)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000762
Collin Winterd28fcbc2007-03-28 23:34:06 +0000763 def testClonePIShallow(self):
764 self.check_clone_pi(0, "testClonePIShallow")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000765
Collin Winterd28fcbc2007-03-28 23:34:06 +0000766 def testClonePIDeep(self):
767 self.check_clone_pi(1, "testClonePIDeep")
768
769 def testNormalize(self):
770 doc = parseString("<doc/>")
771 root = doc.documentElement
772 root.appendChild(doc.createTextNode("first"))
773 root.appendChild(doc.createTextNode("second"))
774 self.confirm(len(root.childNodes) == 2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000775 and root.childNodes.length == 2,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000776 "testNormalize -- preparation")
777 doc.normalize()
778 self.confirm(len(root.childNodes) == 1
779 and root.childNodes.length == 1
780 and root.firstChild is root.lastChild
781 and root.firstChild.data == "firstsecond"
782 , "testNormalize -- result")
783 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000784
Collin Winterd28fcbc2007-03-28 23:34:06 +0000785 doc = parseString("<doc/>")
786 root = doc.documentElement
787 root.appendChild(doc.createTextNode(""))
788 doc.normalize()
789 self.confirm(len(root.childNodes) == 0
790 and root.childNodes.length == 0,
791 "testNormalize -- single empty node removed")
792 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000793
Andrew M. Kuchling19aff0c2008-02-23 17:10:46 +0000794 def testBug1433694(self):
795 doc = parseString("<o><i/>t</o>")
796 node = doc.documentElement
797 node.childNodes[1].nodeValue = ""
798 node.normalize()
799 self.confirm(node.childNodes[-1].nextSibling == None,
800 "Final child's .nextSibling should be None")
801
Collin Winterd28fcbc2007-03-28 23:34:06 +0000802 def testSiblings(self):
803 doc = parseString("<doc><?pi?>text?<elm/></doc>")
804 root = doc.documentElement
805 (pi, text, elm) = root.childNodes
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000806
Collin Winterd28fcbc2007-03-28 23:34:06 +0000807 self.confirm(pi.nextSibling is text and
808 pi.previousSibling is None and
809 text.nextSibling is elm and
810 text.previousSibling is pi and
811 elm.nextSibling is None and
812 elm.previousSibling is text, "testSiblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000813
Collin Winterd28fcbc2007-03-28 23:34:06 +0000814 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000815
Collin Winterd28fcbc2007-03-28 23:34:06 +0000816 def testParents(self):
817 doc = parseString(
818 "<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
819 root = doc.documentElement
820 elm1 = root.childNodes[0]
821 (elm2a, elm2b) = elm1.childNodes
822 elm3 = elm2b.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000823
Collin Winterd28fcbc2007-03-28 23:34:06 +0000824 self.confirm(root.parentNode is doc and
825 elm1.parentNode is root and
826 elm2a.parentNode is elm1 and
827 elm2b.parentNode is elm1 and
828 elm3.parentNode is elm2b, "testParents")
829 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000830
Collin Winterd28fcbc2007-03-28 23:34:06 +0000831 def testNodeListItem(self):
832 doc = parseString("<doc><e/><e/></doc>")
833 children = doc.childNodes
834 docelem = children[0]
835 self.confirm(children[0] is children.item(0)
836 and children.item(1) is None
837 and docelem.childNodes.item(0) is docelem.childNodes[0]
838 and docelem.childNodes.item(1) is docelem.childNodes[1]
839 and docelem.childNodes.item(0).childNodes.item(0) is None,
840 "test NodeList.item()")
841 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000842
Collin Winterd28fcbc2007-03-28 23:34:06 +0000843 def testSAX2DOM(self):
844 from xml.dom import pulldom
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000845
Collin Winterd28fcbc2007-03-28 23:34:06 +0000846 sax2dom = pulldom.SAX2DOM()
847 sax2dom.startDocument()
848 sax2dom.startElement("doc", {})
849 sax2dom.characters("text")
850 sax2dom.startElement("subelm", {})
851 sax2dom.characters("text")
852 sax2dom.endElement("subelm")
853 sax2dom.characters("text")
854 sax2dom.endElement("doc")
855 sax2dom.endDocument()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000856
Collin Winterd28fcbc2007-03-28 23:34:06 +0000857 doc = sax2dom.document
858 root = doc.documentElement
859 (text1, elm1, text2) = root.childNodes
860 text3 = elm1.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000861
Collin Winterd28fcbc2007-03-28 23:34:06 +0000862 self.confirm(text1.previousSibling is None and
863 text1.nextSibling is elm1 and
864 elm1.previousSibling is text1 and
865 elm1.nextSibling is text2 and
866 text2.previousSibling is elm1 and
867 text2.nextSibling is None and
868 text3.previousSibling is None and
869 text3.nextSibling is None, "testSAX2DOM - siblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000870
Collin Winterd28fcbc2007-03-28 23:34:06 +0000871 self.confirm(root.parentNode is doc and
872 text1.parentNode is root and
873 elm1.parentNode is root and
874 text2.parentNode is root and
875 text3.parentNode is elm1, "testSAX2DOM - parents")
876 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000877
Collin Winterd28fcbc2007-03-28 23:34:06 +0000878 def testEncodings(self):
879 doc = parseString('<foo>&#x20ac;</foo>')
880 self.confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000881 and doc.toxml('utf-8') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000882 '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000883 and doc.toxml('iso-8859-15') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000884 '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
885 "testEncodings - encoding EURO SIGN")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000886
887 # Verify that character decoding errors throw exceptions instead
Collin Winterd28fcbc2007-03-28 23:34:06 +0000888 # of crashing
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000889 self.assertRaises(UnicodeDecodeError, parseString,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000890 '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000891
Collin Winterd28fcbc2007-03-28 23:34:06 +0000892 doc.unlink()
893
894 class UserDataHandler:
895 called = 0
896 def handle(self, operation, key, data, src, dst):
897 dst.setUserData(key, data + 1, self)
898 src.setUserData(key, None, None)
899 self.called = 1
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000900
Collin Winterd28fcbc2007-03-28 23:34:06 +0000901 def testUserData(self):
902 dom = Document()
903 n = dom.createElement('e')
904 self.confirm(n.getUserData("foo") is None)
905 n.setUserData("foo", None, None)
906 self.confirm(n.getUserData("foo") is None)
907 n.setUserData("foo", 12, 12)
908 n.setUserData("bar", 13, 13)
909 self.confirm(n.getUserData("foo") == 12)
910 self.confirm(n.getUserData("bar") == 13)
911 n.setUserData("foo", None, None)
912 self.confirm(n.getUserData("foo") is None)
913 self.confirm(n.getUserData("bar") == 13)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000914
Collin Winterd28fcbc2007-03-28 23:34:06 +0000915 handler = self.UserDataHandler()
916 n.setUserData("bar", 12, handler)
917 c = n.cloneNode(1)
918 self.confirm(handler.called
919 and n.getUserData("bar") is None
920 and c.getUserData("bar") == 13)
921 n.unlink()
922 c.unlink()
923 dom.unlink()
924
925 def checkRenameNodeSharedConstraints(self, doc, node):
926 # Make sure illegal NS usage is detected:
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000927 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000928 "http://xml.python.org/ns", "xmlns:foo")
929 doc2 = parseString("<doc/>")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000930 self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000931 xml.dom.EMPTY_NAMESPACE, "foo")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000932
Collin Winterd28fcbc2007-03-28 23:34:06 +0000933 def testRenameAttribute(self):
934 doc = parseString("<doc a='v'/>")
935 elem = doc.documentElement
936 attrmap = elem.attributes
937 attr = elem.attributes['a']
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000938
Collin Winterd28fcbc2007-03-28 23:34:06 +0000939 # Simple renaming
940 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
941 self.confirm(attr.name == "b"
942 and attr.nodeName == "b"
943 and attr.localName is None
944 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
945 and attr.prefix is None
946 and attr.value == "v"
947 and elem.getAttributeNode("a") is None
948 and elem.getAttributeNode("b").isSameNode(attr)
949 and attrmap["b"].isSameNode(attr)
950 and attr.ownerDocument.isSameNode(doc)
951 and attr.ownerElement.isSameNode(elem))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000952
Collin Winterd28fcbc2007-03-28 23:34:06 +0000953 # Rename to have a namespace, no prefix
954 attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
955 self.confirm(attr.name == "c"
956 and attr.nodeName == "c"
957 and attr.localName == "c"
958 and attr.namespaceURI == "http://xml.python.org/ns"
959 and attr.prefix is None
960 and attr.value == "v"
961 and elem.getAttributeNode("a") is None
962 and elem.getAttributeNode("b") is None
963 and elem.getAttributeNode("c").isSameNode(attr)
964 and elem.getAttributeNodeNS(
965 "http://xml.python.org/ns", "c").isSameNode(attr)
966 and attrmap["c"].isSameNode(attr)
967 and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000968
Collin Winterd28fcbc2007-03-28 23:34:06 +0000969 # Rename to have a namespace, with prefix
970 attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
971 self.confirm(attr.name == "p:d"
972 and attr.nodeName == "p:d"
973 and attr.localName == "d"
974 and attr.namespaceURI == "http://xml.python.org/ns2"
975 and attr.prefix == "p"
976 and attr.value == "v"
977 and elem.getAttributeNode("a") is None
978 and elem.getAttributeNode("b") is None
979 and elem.getAttributeNode("c") is None
980 and elem.getAttributeNodeNS(
981 "http://xml.python.org/ns", "c") is None
982 and elem.getAttributeNode("p:d").isSameNode(attr)
983 and elem.getAttributeNodeNS(
984 "http://xml.python.org/ns2", "d").isSameNode(attr)
985 and attrmap["p:d"].isSameNode(attr)
986 and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000987
Collin Winterd28fcbc2007-03-28 23:34:06 +0000988 # Rename back to a simple non-NS node
989 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
990 self.confirm(attr.name == "e"
991 and attr.nodeName == "e"
992 and attr.localName is None
993 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
994 and attr.prefix is None
995 and attr.value == "v"
996 and elem.getAttributeNode("a") is None
997 and elem.getAttributeNode("b") is None
998 and elem.getAttributeNode("c") is None
999 and elem.getAttributeNode("p:d") is None
1000 and elem.getAttributeNodeNS(
1001 "http://xml.python.org/ns", "c") is None
1002 and elem.getAttributeNode("e").isSameNode(attr)
1003 and attrmap["e"].isSameNode(attr))
1004
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001005 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001006 "http://xml.python.org/ns", "xmlns")
1007 self.checkRenameNodeSharedConstraints(doc, attr)
1008 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001009
Collin Winterd28fcbc2007-03-28 23:34:06 +00001010 def testRenameElement(self):
1011 doc = parseString("<doc/>")
1012 elem = doc.documentElement
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001013
Collin Winterd28fcbc2007-03-28 23:34:06 +00001014 # Simple renaming
1015 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
1016 self.confirm(elem.tagName == "a"
1017 and elem.nodeName == "a"
1018 and elem.localName is None
1019 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1020 and elem.prefix is None
1021 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001022
Collin Winterd28fcbc2007-03-28 23:34:06 +00001023 # Rename to have a namespace, no prefix
1024 elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
1025 self.confirm(elem.tagName == "b"
1026 and elem.nodeName == "b"
1027 and elem.localName == "b"
1028 and elem.namespaceURI == "http://xml.python.org/ns"
1029 and elem.prefix is None
1030 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001031
Collin Winterd28fcbc2007-03-28 23:34:06 +00001032 # Rename to have a namespace, with prefix
1033 elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
1034 self.confirm(elem.tagName == "p:c"
1035 and elem.nodeName == "p:c"
1036 and elem.localName == "c"
1037 and elem.namespaceURI == "http://xml.python.org/ns2"
1038 and elem.prefix == "p"
1039 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001040
Collin Winterd28fcbc2007-03-28 23:34:06 +00001041 # Rename back to a simple non-NS node
1042 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
1043 self.confirm(elem.tagName == "d"
1044 and elem.nodeName == "d"
1045 and elem.localName is None
1046 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1047 and elem.prefix is None
1048 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001049
Collin Winterd28fcbc2007-03-28 23:34:06 +00001050 self.checkRenameNodeSharedConstraints(doc, elem)
1051 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001052
Collin Winterd28fcbc2007-03-28 23:34:06 +00001053 def testRenameOther(self):
1054 # We have to create a comment node explicitly since not all DOM
1055 # builders used with minidom add comments to the DOM.
1056 doc = xml.dom.minidom.getDOMImplementation().createDocument(
1057 xml.dom.EMPTY_NAMESPACE, "e", None)
1058 node = doc.createComment("comment")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001059 self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001060 xml.dom.EMPTY_NAMESPACE, "foo")
1061 doc.unlink()
1062
1063 def testWholeText(self):
1064 doc = parseString("<doc>a</doc>")
1065 elem = doc.documentElement
1066 text = elem.childNodes[0]
1067 self.assertEquals(text.nodeType, Node.TEXT_NODE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001068
Collin Winterd28fcbc2007-03-28 23:34:06 +00001069 self.checkWholeText(text, "a")
1070 elem.appendChild(doc.createTextNode("b"))
1071 self.checkWholeText(text, "ab")
1072 elem.insertBefore(doc.createCDATASection("c"), text)
1073 self.checkWholeText(text, "cab")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001074
Collin Winterd28fcbc2007-03-28 23:34:06 +00001075 # make sure we don't cross other nodes
1076 splitter = doc.createComment("comment")
1077 elem.appendChild(splitter)
1078 text2 = doc.createTextNode("d")
1079 elem.appendChild(text2)
1080 self.checkWholeText(text, "cab")
1081 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001082
Collin Winterd28fcbc2007-03-28 23:34:06 +00001083 x = doc.createElement("x")
1084 elem.replaceChild(x, splitter)
1085 splitter = x
1086 self.checkWholeText(text, "cab")
1087 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001088
Collin Winterd28fcbc2007-03-28 23:34:06 +00001089 x = doc.createProcessingInstruction("y", "z")
1090 elem.replaceChild(x, splitter)
1091 splitter = x
1092 self.checkWholeText(text, "cab")
1093 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001094
Collin Winterd28fcbc2007-03-28 23:34:06 +00001095 elem.removeChild(splitter)
1096 self.checkWholeText(text, "cabd")
1097 self.checkWholeText(text2, "cabd")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001098
Collin Winterd28fcbc2007-03-28 23:34:06 +00001099 def testPatch1094164(self):
1100 doc = parseString("<doc><e/></doc>")
1101 elem = doc.documentElement
1102 e = elem.firstChild
1103 self.confirm(e.parentNode is elem, "Before replaceChild()")
1104 # Check that replacing a child with itself leaves the tree unchanged
1105 elem.replaceChild(e, e)
1106 self.confirm(e.parentNode is elem, "After replaceChild()")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001107
Collin Winterd28fcbc2007-03-28 23:34:06 +00001108 def testReplaceWholeText(self):
1109 def setup():
1110 doc = parseString("<doc>a<e/>d</doc>")
1111 elem = doc.documentElement
1112 text1 = elem.firstChild
1113 text2 = elem.lastChild
1114 splitter = text1.nextSibling
1115 elem.insertBefore(doc.createTextNode("b"), splitter)
1116 elem.insertBefore(doc.createCDATASection("c"), text1)
1117 return doc, elem, text1, splitter, text2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001118
Collin Winterd28fcbc2007-03-28 23:34:06 +00001119 doc, elem, text1, splitter, text2 = setup()
1120 text = text1.replaceWholeText("new content")
1121 self.checkWholeText(text, "new content")
1122 self.checkWholeText(text2, "d")
1123 self.confirm(len(elem.childNodes) == 3)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001124
Collin Winterd28fcbc2007-03-28 23:34:06 +00001125 doc, elem, text1, splitter, text2 = setup()
1126 text = text2.replaceWholeText("new content")
1127 self.checkWholeText(text, "new content")
1128 self.checkWholeText(text1, "cab")
1129 self.confirm(len(elem.childNodes) == 5)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001130
Collin Winterd28fcbc2007-03-28 23:34:06 +00001131 doc, elem, text1, splitter, text2 = setup()
1132 text = text1.replaceWholeText("")
1133 self.checkWholeText(text2, "d")
1134 self.confirm(text is None
1135 and len(elem.childNodes) == 2)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001136
Collin Winterd28fcbc2007-03-28 23:34:06 +00001137 def testSchemaType(self):
1138 doc = parseString(
1139 "<!DOCTYPE doc [\n"
1140 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
1141 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
1142 " <!ATTLIST doc id ID #IMPLIED \n"
1143 " ref IDREF #IMPLIED \n"
1144 " refs IDREFS #IMPLIED \n"
1145 " enum (a|b) #IMPLIED \n"
1146 " ent ENTITY #IMPLIED \n"
1147 " ents ENTITIES #IMPLIED \n"
1148 " nm NMTOKEN #IMPLIED \n"
1149 " nms NMTOKENS #IMPLIED \n"
1150 " text CDATA #IMPLIED \n"
1151 " >\n"
1152 "]><doc id='name' notid='name' text='splat!' enum='b'"
1153 " ref='name' refs='name name' ent='e1' ents='e1 e2'"
1154 " nm='123' nms='123 abc' />")
1155 elem = doc.documentElement
1156 # We don't want to rely on any specific loader at this point, so
1157 # just make sure we can get to all the names, and that the
1158 # DTD-based namespace is right. The names can vary by loader
1159 # since each supports a different level of DTD information.
1160 t = elem.schemaType
1161 self.confirm(t.name is None
1162 and t.namespace == xml.dom.EMPTY_NAMESPACE)
1163 names = "id notid text enum ref refs ent ents nm nms".split()
1164 for name in names:
1165 a = elem.getAttributeNode(name)
1166 t = a.schemaType
1167 self.confirm(hasattr(t, "name")
1168 and t.namespace == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001169
Collin Winterd28fcbc2007-03-28 23:34:06 +00001170 def testSetIdAttribute(self):
1171 doc = parseString("<doc a1='v' a2='w'/>")
1172 e = doc.documentElement
1173 a1 = e.getAttributeNode("a1")
1174 a2 = e.getAttributeNode("a2")
1175 self.confirm(doc.getElementById("v") is None
1176 and not a1.isId
1177 and not a2.isId)
1178 e.setIdAttribute("a1")
1179 self.confirm(e.isSameNode(doc.getElementById("v"))
1180 and a1.isId
1181 and not a2.isId)
1182 e.setIdAttribute("a2")
1183 self.confirm(e.isSameNode(doc.getElementById("v"))
1184 and e.isSameNode(doc.getElementById("w"))
1185 and a1.isId
1186 and a2.isId)
1187 # replace the a1 node; the new node should *not* be an ID
1188 a3 = doc.createAttribute("a1")
1189 a3.value = "v"
1190 e.setAttributeNode(a3)
1191 self.confirm(doc.getElementById("v") is None
1192 and e.isSameNode(doc.getElementById("w"))
1193 and not a1.isId
1194 and a2.isId
1195 and not a3.isId)
1196 # renaming an attribute should not affect its ID-ness:
1197 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1198 self.confirm(e.isSameNode(doc.getElementById("w"))
1199 and a2.isId)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001200
Collin Winterd28fcbc2007-03-28 23:34:06 +00001201 def testSetIdAttributeNS(self):
1202 NS1 = "http://xml.python.org/ns1"
1203 NS2 = "http://xml.python.org/ns2"
1204 doc = parseString("<doc"
1205 " xmlns:ns1='" + NS1 + "'"
1206 " xmlns:ns2='" + NS2 + "'"
1207 " ns1:a1='v' ns2:a2='w'/>")
1208 e = doc.documentElement
1209 a1 = e.getAttributeNodeNS(NS1, "a1")
1210 a2 = e.getAttributeNodeNS(NS2, "a2")
1211 self.confirm(doc.getElementById("v") is None
1212 and not a1.isId
1213 and not a2.isId)
1214 e.setIdAttributeNS(NS1, "a1")
1215 self.confirm(e.isSameNode(doc.getElementById("v"))
1216 and a1.isId
1217 and not a2.isId)
1218 e.setIdAttributeNS(NS2, "a2")
1219 self.confirm(e.isSameNode(doc.getElementById("v"))
1220 and e.isSameNode(doc.getElementById("w"))
1221 and a1.isId
1222 and a2.isId)
1223 # replace the a1 node; the new node should *not* be an ID
1224 a3 = doc.createAttributeNS(NS1, "a1")
1225 a3.value = "v"
1226 e.setAttributeNode(a3)
1227 self.confirm(e.isSameNode(doc.getElementById("w")))
1228 self.confirm(not a1.isId)
1229 self.confirm(a2.isId)
1230 self.confirm(not a3.isId)
1231 self.confirm(doc.getElementById("v") is None)
1232 # renaming an attribute should not affect its ID-ness:
1233 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1234 self.confirm(e.isSameNode(doc.getElementById("w"))
1235 and a2.isId)
1236
1237 def testSetIdAttributeNode(self):
1238 NS1 = "http://xml.python.org/ns1"
1239 NS2 = "http://xml.python.org/ns2"
1240 doc = parseString("<doc"
1241 " xmlns:ns1='" + NS1 + "'"
1242 " xmlns:ns2='" + NS2 + "'"
1243 " ns1:a1='v' ns2:a2='w'/>")
1244 e = doc.documentElement
1245 a1 = e.getAttributeNodeNS(NS1, "a1")
1246 a2 = e.getAttributeNodeNS(NS2, "a2")
1247 self.confirm(doc.getElementById("v") is None
1248 and not a1.isId
1249 and not a2.isId)
1250 e.setIdAttributeNode(a1)
1251 self.confirm(e.isSameNode(doc.getElementById("v"))
1252 and a1.isId
1253 and not a2.isId)
1254 e.setIdAttributeNode(a2)
1255 self.confirm(e.isSameNode(doc.getElementById("v"))
1256 and e.isSameNode(doc.getElementById("w"))
1257 and a1.isId
1258 and a2.isId)
1259 # replace the a1 node; the new node should *not* be an ID
1260 a3 = doc.createAttributeNS(NS1, "a1")
1261 a3.value = "v"
1262 e.setAttributeNode(a3)
1263 self.confirm(e.isSameNode(doc.getElementById("w")))
1264 self.confirm(not a1.isId)
1265 self.confirm(a2.isId)
1266 self.confirm(not a3.isId)
1267 self.confirm(doc.getElementById("v") is None)
1268 # renaming an attribute should not affect its ID-ness:
1269 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1270 self.confirm(e.isSameNode(doc.getElementById("w"))
1271 and a2.isId)
1272
1273 def testPickledDocument(self):
1274 doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
1275 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
1276 " 'http://xml.python.org/system' [\n"
1277 " <!ELEMENT e EMPTY>\n"
1278 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
1279 "]><doc attr='value'> text\n"
1280 "<?pi sample?> <!-- comment --> <e/> </doc>")
1281 s = pickle.dumps(doc)
1282 doc2 = pickle.loads(s)
1283 stack = [(doc, doc2)]
1284 while stack:
1285 n1, n2 = stack.pop()
1286 self.confirm(n1.nodeType == n2.nodeType
1287 and len(n1.childNodes) == len(n2.childNodes)
1288 and n1.nodeName == n2.nodeName
1289 and not n1.isSameNode(n2)
1290 and not n2.isSameNode(n1))
1291 if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
1292 len(n1.entities)
1293 len(n2.entities)
1294 len(n1.notations)
1295 len(n2.notations)
1296 self.confirm(len(n1.entities) == len(n2.entities)
1297 and len(n1.notations) == len(n2.notations))
1298 for i in range(len(n1.notations)):
1299 no1 = n1.notations.item(i)
1300 no2 = n1.notations.item(i)
1301 self.confirm(no1.name == no2.name
1302 and no1.publicId == no2.publicId
1303 and no1.systemId == no2.systemId)
1304 statck.append((no1, no2))
1305 for i in range(len(n1.entities)):
1306 e1 = n1.entities.item(i)
1307 e2 = n2.entities.item(i)
1308 self.confirm(e1.notationName == e2.notationName
1309 and e1.publicId == e2.publicId
1310 and e1.systemId == e2.systemId)
1311 stack.append((e1, e2))
1312 if n1.nodeType != Node.DOCUMENT_NODE:
1313 self.confirm(n1.ownerDocument.isSameNode(doc)
1314 and n2.ownerDocument.isSameNode(doc2))
1315 for i in range(len(n1.childNodes)):
1316 stack.append((n1.childNodes[i], n2.childNodes[i]))
1317
1318def test_main():
1319 run_unittest(MinidomTest)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001320
Collin Winterd28fcbc2007-03-28 23:34:06 +00001321if __name__ == "__main__":
1322 test_main()