blob: 3058b303068569cf849f91f442a0fbf0d26268f2 [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
Collin Winterd28fcbc2007-03-28 23:34:06 +0000794 def testSiblings(self):
795 doc = parseString("<doc><?pi?>text?<elm/></doc>")
796 root = doc.documentElement
797 (pi, text, elm) = root.childNodes
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000798
Collin Winterd28fcbc2007-03-28 23:34:06 +0000799 self.confirm(pi.nextSibling is text and
800 pi.previousSibling is None and
801 text.nextSibling is elm and
802 text.previousSibling is pi and
803 elm.nextSibling is None and
804 elm.previousSibling is text, "testSiblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000805
Collin Winterd28fcbc2007-03-28 23:34:06 +0000806 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000807
Collin Winterd28fcbc2007-03-28 23:34:06 +0000808 def testParents(self):
809 doc = parseString(
810 "<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
811 root = doc.documentElement
812 elm1 = root.childNodes[0]
813 (elm2a, elm2b) = elm1.childNodes
814 elm3 = elm2b.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000815
Collin Winterd28fcbc2007-03-28 23:34:06 +0000816 self.confirm(root.parentNode is doc and
817 elm1.parentNode is root and
818 elm2a.parentNode is elm1 and
819 elm2b.parentNode is elm1 and
820 elm3.parentNode is elm2b, "testParents")
821 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000822
Collin Winterd28fcbc2007-03-28 23:34:06 +0000823 def testNodeListItem(self):
824 doc = parseString("<doc><e/><e/></doc>")
825 children = doc.childNodes
826 docelem = children[0]
827 self.confirm(children[0] is children.item(0)
828 and children.item(1) is None
829 and docelem.childNodes.item(0) is docelem.childNodes[0]
830 and docelem.childNodes.item(1) is docelem.childNodes[1]
831 and docelem.childNodes.item(0).childNodes.item(0) is None,
832 "test NodeList.item()")
833 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000834
Collin Winterd28fcbc2007-03-28 23:34:06 +0000835 def testSAX2DOM(self):
836 from xml.dom import pulldom
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000837
Collin Winterd28fcbc2007-03-28 23:34:06 +0000838 sax2dom = pulldom.SAX2DOM()
839 sax2dom.startDocument()
840 sax2dom.startElement("doc", {})
841 sax2dom.characters("text")
842 sax2dom.startElement("subelm", {})
843 sax2dom.characters("text")
844 sax2dom.endElement("subelm")
845 sax2dom.characters("text")
846 sax2dom.endElement("doc")
847 sax2dom.endDocument()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000848
Collin Winterd28fcbc2007-03-28 23:34:06 +0000849 doc = sax2dom.document
850 root = doc.documentElement
851 (text1, elm1, text2) = root.childNodes
852 text3 = elm1.childNodes[0]
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000853
Collin Winterd28fcbc2007-03-28 23:34:06 +0000854 self.confirm(text1.previousSibling is None and
855 text1.nextSibling is elm1 and
856 elm1.previousSibling is text1 and
857 elm1.nextSibling is text2 and
858 text2.previousSibling is elm1 and
859 text2.nextSibling is None and
860 text3.previousSibling is None and
861 text3.nextSibling is None, "testSAX2DOM - siblings")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000862
Collin Winterd28fcbc2007-03-28 23:34:06 +0000863 self.confirm(root.parentNode is doc and
864 text1.parentNode is root and
865 elm1.parentNode is root and
866 text2.parentNode is root and
867 text3.parentNode is elm1, "testSAX2DOM - parents")
868 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000869
Collin Winterd28fcbc2007-03-28 23:34:06 +0000870 def testEncodings(self):
871 doc = parseString('<foo>&#x20ac;</foo>')
872 self.confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000873 and doc.toxml('utf-8') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000874 '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000875 and doc.toxml('iso-8859-15') ==
Collin Winterd28fcbc2007-03-28 23:34:06 +0000876 '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
877 "testEncodings - encoding EURO SIGN")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000878
879 # Verify that character decoding errors throw exceptions instead
Collin Winterd28fcbc2007-03-28 23:34:06 +0000880 # of crashing
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000881 self.assertRaises(UnicodeDecodeError, parseString,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000882 '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000883
Collin Winterd28fcbc2007-03-28 23:34:06 +0000884 doc.unlink()
885
886 class UserDataHandler:
887 called = 0
888 def handle(self, operation, key, data, src, dst):
889 dst.setUserData(key, data + 1, self)
890 src.setUserData(key, None, None)
891 self.called = 1
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000892
Collin Winterd28fcbc2007-03-28 23:34:06 +0000893 def testUserData(self):
894 dom = Document()
895 n = dom.createElement('e')
896 self.confirm(n.getUserData("foo") is None)
897 n.setUserData("foo", None, None)
898 self.confirm(n.getUserData("foo") is None)
899 n.setUserData("foo", 12, 12)
900 n.setUserData("bar", 13, 13)
901 self.confirm(n.getUserData("foo") == 12)
902 self.confirm(n.getUserData("bar") == 13)
903 n.setUserData("foo", None, None)
904 self.confirm(n.getUserData("foo") is None)
905 self.confirm(n.getUserData("bar") == 13)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000906
Collin Winterd28fcbc2007-03-28 23:34:06 +0000907 handler = self.UserDataHandler()
908 n.setUserData("bar", 12, handler)
909 c = n.cloneNode(1)
910 self.confirm(handler.called
911 and n.getUserData("bar") is None
912 and c.getUserData("bar") == 13)
913 n.unlink()
914 c.unlink()
915 dom.unlink()
916
917 def checkRenameNodeSharedConstraints(self, doc, node):
918 # Make sure illegal NS usage is detected:
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000919 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000920 "http://xml.python.org/ns", "xmlns:foo")
921 doc2 = parseString("<doc/>")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000922 self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000923 xml.dom.EMPTY_NAMESPACE, "foo")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000924
Collin Winterd28fcbc2007-03-28 23:34:06 +0000925 def testRenameAttribute(self):
926 doc = parseString("<doc a='v'/>")
927 elem = doc.documentElement
928 attrmap = elem.attributes
929 attr = elem.attributes['a']
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000930
Collin Winterd28fcbc2007-03-28 23:34:06 +0000931 # Simple renaming
932 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
933 self.confirm(attr.name == "b"
934 and attr.nodeName == "b"
935 and attr.localName is None
936 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
937 and attr.prefix is None
938 and attr.value == "v"
939 and elem.getAttributeNode("a") is None
940 and elem.getAttributeNode("b").isSameNode(attr)
941 and attrmap["b"].isSameNode(attr)
942 and attr.ownerDocument.isSameNode(doc)
943 and attr.ownerElement.isSameNode(elem))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000944
Collin Winterd28fcbc2007-03-28 23:34:06 +0000945 # Rename to have a namespace, no prefix
946 attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
947 self.confirm(attr.name == "c"
948 and attr.nodeName == "c"
949 and attr.localName == "c"
950 and attr.namespaceURI == "http://xml.python.org/ns"
951 and attr.prefix is None
952 and attr.value == "v"
953 and elem.getAttributeNode("a") is None
954 and elem.getAttributeNode("b") is None
955 and elem.getAttributeNode("c").isSameNode(attr)
956 and elem.getAttributeNodeNS(
957 "http://xml.python.org/ns", "c").isSameNode(attr)
958 and attrmap["c"].isSameNode(attr)
959 and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000960
Collin Winterd28fcbc2007-03-28 23:34:06 +0000961 # Rename to have a namespace, with prefix
962 attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
963 self.confirm(attr.name == "p:d"
964 and attr.nodeName == "p:d"
965 and attr.localName == "d"
966 and attr.namespaceURI == "http://xml.python.org/ns2"
967 and attr.prefix == "p"
968 and attr.value == "v"
969 and elem.getAttributeNode("a") is None
970 and elem.getAttributeNode("b") is None
971 and elem.getAttributeNode("c") is None
972 and elem.getAttributeNodeNS(
973 "http://xml.python.org/ns", "c") is None
974 and elem.getAttributeNode("p:d").isSameNode(attr)
975 and elem.getAttributeNodeNS(
976 "http://xml.python.org/ns2", "d").isSameNode(attr)
977 and attrmap["p:d"].isSameNode(attr)
978 and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000979
Collin Winterd28fcbc2007-03-28 23:34:06 +0000980 # Rename back to a simple non-NS node
981 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
982 self.confirm(attr.name == "e"
983 and attr.nodeName == "e"
984 and attr.localName is None
985 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
986 and attr.prefix is None
987 and attr.value == "v"
988 and elem.getAttributeNode("a") is None
989 and elem.getAttributeNode("b") is None
990 and elem.getAttributeNode("c") is None
991 and elem.getAttributeNode("p:d") is None
992 and elem.getAttributeNodeNS(
993 "http://xml.python.org/ns", "c") is None
994 and elem.getAttributeNode("e").isSameNode(attr)
995 and attrmap["e"].isSameNode(attr))
996
Neal Norwitz0d4c06e2007-04-25 06:30:05 +0000997 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr,
Collin Winterd28fcbc2007-03-28 23:34:06 +0000998 "http://xml.python.org/ns", "xmlns")
999 self.checkRenameNodeSharedConstraints(doc, attr)
1000 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001001
Collin Winterd28fcbc2007-03-28 23:34:06 +00001002 def testRenameElement(self):
1003 doc = parseString("<doc/>")
1004 elem = doc.documentElement
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001005
Collin Winterd28fcbc2007-03-28 23:34:06 +00001006 # Simple renaming
1007 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
1008 self.confirm(elem.tagName == "a"
1009 and elem.nodeName == "a"
1010 and elem.localName is None
1011 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1012 and elem.prefix is None
1013 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001014
Collin Winterd28fcbc2007-03-28 23:34:06 +00001015 # Rename to have a namespace, no prefix
1016 elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
1017 self.confirm(elem.tagName == "b"
1018 and elem.nodeName == "b"
1019 and elem.localName == "b"
1020 and elem.namespaceURI == "http://xml.python.org/ns"
1021 and elem.prefix is None
1022 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001023
Collin Winterd28fcbc2007-03-28 23:34:06 +00001024 # Rename to have a namespace, with prefix
1025 elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
1026 self.confirm(elem.tagName == "p:c"
1027 and elem.nodeName == "p:c"
1028 and elem.localName == "c"
1029 and elem.namespaceURI == "http://xml.python.org/ns2"
1030 and elem.prefix == "p"
1031 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001032
Collin Winterd28fcbc2007-03-28 23:34:06 +00001033 # Rename back to a simple non-NS node
1034 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
1035 self.confirm(elem.tagName == "d"
1036 and elem.nodeName == "d"
1037 and elem.localName is None
1038 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
1039 and elem.prefix is None
1040 and elem.ownerDocument.isSameNode(doc))
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001041
Collin Winterd28fcbc2007-03-28 23:34:06 +00001042 self.checkRenameNodeSharedConstraints(doc, elem)
1043 doc.unlink()
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001044
Collin Winterd28fcbc2007-03-28 23:34:06 +00001045 def testRenameOther(self):
1046 # We have to create a comment node explicitly since not all DOM
1047 # builders used with minidom add comments to the DOM.
1048 doc = xml.dom.minidom.getDOMImplementation().createDocument(
1049 xml.dom.EMPTY_NAMESPACE, "e", None)
1050 node = doc.createComment("comment")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001051 self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node,
Collin Winterd28fcbc2007-03-28 23:34:06 +00001052 xml.dom.EMPTY_NAMESPACE, "foo")
1053 doc.unlink()
1054
1055 def testWholeText(self):
1056 doc = parseString("<doc>a</doc>")
1057 elem = doc.documentElement
1058 text = elem.childNodes[0]
1059 self.assertEquals(text.nodeType, Node.TEXT_NODE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001060
Collin Winterd28fcbc2007-03-28 23:34:06 +00001061 self.checkWholeText(text, "a")
1062 elem.appendChild(doc.createTextNode("b"))
1063 self.checkWholeText(text, "ab")
1064 elem.insertBefore(doc.createCDATASection("c"), text)
1065 self.checkWholeText(text, "cab")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001066
Collin Winterd28fcbc2007-03-28 23:34:06 +00001067 # make sure we don't cross other nodes
1068 splitter = doc.createComment("comment")
1069 elem.appendChild(splitter)
1070 text2 = doc.createTextNode("d")
1071 elem.appendChild(text2)
1072 self.checkWholeText(text, "cab")
1073 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001074
Collin Winterd28fcbc2007-03-28 23:34:06 +00001075 x = doc.createElement("x")
1076 elem.replaceChild(x, splitter)
1077 splitter = x
1078 self.checkWholeText(text, "cab")
1079 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001080
Collin Winterd28fcbc2007-03-28 23:34:06 +00001081 x = doc.createProcessingInstruction("y", "z")
1082 elem.replaceChild(x, splitter)
1083 splitter = x
1084 self.checkWholeText(text, "cab")
1085 self.checkWholeText(text2, "d")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001086
Collin Winterd28fcbc2007-03-28 23:34:06 +00001087 elem.removeChild(splitter)
1088 self.checkWholeText(text, "cabd")
1089 self.checkWholeText(text2, "cabd")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001090
Collin Winterd28fcbc2007-03-28 23:34:06 +00001091 def testPatch1094164(self):
1092 doc = parseString("<doc><e/></doc>")
1093 elem = doc.documentElement
1094 e = elem.firstChild
1095 self.confirm(e.parentNode is elem, "Before replaceChild()")
1096 # Check that replacing a child with itself leaves the tree unchanged
1097 elem.replaceChild(e, e)
1098 self.confirm(e.parentNode is elem, "After replaceChild()")
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001099
Collin Winterd28fcbc2007-03-28 23:34:06 +00001100 def testReplaceWholeText(self):
1101 def setup():
1102 doc = parseString("<doc>a<e/>d</doc>")
1103 elem = doc.documentElement
1104 text1 = elem.firstChild
1105 text2 = elem.lastChild
1106 splitter = text1.nextSibling
1107 elem.insertBefore(doc.createTextNode("b"), splitter)
1108 elem.insertBefore(doc.createCDATASection("c"), text1)
1109 return doc, elem, text1, splitter, text2
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001110
Collin Winterd28fcbc2007-03-28 23:34:06 +00001111 doc, elem, text1, splitter, text2 = setup()
1112 text = text1.replaceWholeText("new content")
1113 self.checkWholeText(text, "new content")
1114 self.checkWholeText(text2, "d")
1115 self.confirm(len(elem.childNodes) == 3)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001116
Collin Winterd28fcbc2007-03-28 23:34:06 +00001117 doc, elem, text1, splitter, text2 = setup()
1118 text = text2.replaceWholeText("new content")
1119 self.checkWholeText(text, "new content")
1120 self.checkWholeText(text1, "cab")
1121 self.confirm(len(elem.childNodes) == 5)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001122
Collin Winterd28fcbc2007-03-28 23:34:06 +00001123 doc, elem, text1, splitter, text2 = setup()
1124 text = text1.replaceWholeText("")
1125 self.checkWholeText(text2, "d")
1126 self.confirm(text is None
1127 and len(elem.childNodes) == 2)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001128
Collin Winterd28fcbc2007-03-28 23:34:06 +00001129 def testSchemaType(self):
1130 doc = parseString(
1131 "<!DOCTYPE doc [\n"
1132 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
1133 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
1134 " <!ATTLIST doc id ID #IMPLIED \n"
1135 " ref IDREF #IMPLIED \n"
1136 " refs IDREFS #IMPLIED \n"
1137 " enum (a|b) #IMPLIED \n"
1138 " ent ENTITY #IMPLIED \n"
1139 " ents ENTITIES #IMPLIED \n"
1140 " nm NMTOKEN #IMPLIED \n"
1141 " nms NMTOKENS #IMPLIED \n"
1142 " text CDATA #IMPLIED \n"
1143 " >\n"
1144 "]><doc id='name' notid='name' text='splat!' enum='b'"
1145 " ref='name' refs='name name' ent='e1' ents='e1 e2'"
1146 " nm='123' nms='123 abc' />")
1147 elem = doc.documentElement
1148 # We don't want to rely on any specific loader at this point, so
1149 # just make sure we can get to all the names, and that the
1150 # DTD-based namespace is right. The names can vary by loader
1151 # since each supports a different level of DTD information.
1152 t = elem.schemaType
1153 self.confirm(t.name is None
1154 and t.namespace == xml.dom.EMPTY_NAMESPACE)
1155 names = "id notid text enum ref refs ent ents nm nms".split()
1156 for name in names:
1157 a = elem.getAttributeNode(name)
1158 t = a.schemaType
1159 self.confirm(hasattr(t, "name")
1160 and t.namespace == xml.dom.EMPTY_NAMESPACE)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001161
Collin Winterd28fcbc2007-03-28 23:34:06 +00001162 def testSetIdAttribute(self):
1163 doc = parseString("<doc a1='v' a2='w'/>")
1164 e = doc.documentElement
1165 a1 = e.getAttributeNode("a1")
1166 a2 = e.getAttributeNode("a2")
1167 self.confirm(doc.getElementById("v") is None
1168 and not a1.isId
1169 and not a2.isId)
1170 e.setIdAttribute("a1")
1171 self.confirm(e.isSameNode(doc.getElementById("v"))
1172 and a1.isId
1173 and not a2.isId)
1174 e.setIdAttribute("a2")
1175 self.confirm(e.isSameNode(doc.getElementById("v"))
1176 and e.isSameNode(doc.getElementById("w"))
1177 and a1.isId
1178 and a2.isId)
1179 # replace the a1 node; the new node should *not* be an ID
1180 a3 = doc.createAttribute("a1")
1181 a3.value = "v"
1182 e.setAttributeNode(a3)
1183 self.confirm(doc.getElementById("v") is None
1184 and e.isSameNode(doc.getElementById("w"))
1185 and not a1.isId
1186 and a2.isId
1187 and not a3.isId)
1188 # renaming an attribute should not affect its ID-ness:
1189 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1190 self.confirm(e.isSameNode(doc.getElementById("w"))
1191 and a2.isId)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001192
Collin Winterd28fcbc2007-03-28 23:34:06 +00001193 def testSetIdAttributeNS(self):
1194 NS1 = "http://xml.python.org/ns1"
1195 NS2 = "http://xml.python.org/ns2"
1196 doc = parseString("<doc"
1197 " xmlns:ns1='" + NS1 + "'"
1198 " xmlns:ns2='" + NS2 + "'"
1199 " ns1:a1='v' ns2:a2='w'/>")
1200 e = doc.documentElement
1201 a1 = e.getAttributeNodeNS(NS1, "a1")
1202 a2 = e.getAttributeNodeNS(NS2, "a2")
1203 self.confirm(doc.getElementById("v") is None
1204 and not a1.isId
1205 and not a2.isId)
1206 e.setIdAttributeNS(NS1, "a1")
1207 self.confirm(e.isSameNode(doc.getElementById("v"))
1208 and a1.isId
1209 and not a2.isId)
1210 e.setIdAttributeNS(NS2, "a2")
1211 self.confirm(e.isSameNode(doc.getElementById("v"))
1212 and e.isSameNode(doc.getElementById("w"))
1213 and a1.isId
1214 and a2.isId)
1215 # replace the a1 node; the new node should *not* be an ID
1216 a3 = doc.createAttributeNS(NS1, "a1")
1217 a3.value = "v"
1218 e.setAttributeNode(a3)
1219 self.confirm(e.isSameNode(doc.getElementById("w")))
1220 self.confirm(not a1.isId)
1221 self.confirm(a2.isId)
1222 self.confirm(not a3.isId)
1223 self.confirm(doc.getElementById("v") is None)
1224 # renaming an attribute should not affect its ID-ness:
1225 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1226 self.confirm(e.isSameNode(doc.getElementById("w"))
1227 and a2.isId)
1228
1229 def testSetIdAttributeNode(self):
1230 NS1 = "http://xml.python.org/ns1"
1231 NS2 = "http://xml.python.org/ns2"
1232 doc = parseString("<doc"
1233 " xmlns:ns1='" + NS1 + "'"
1234 " xmlns:ns2='" + NS2 + "'"
1235 " ns1:a1='v' ns2:a2='w'/>")
1236 e = doc.documentElement
1237 a1 = e.getAttributeNodeNS(NS1, "a1")
1238 a2 = e.getAttributeNodeNS(NS2, "a2")
1239 self.confirm(doc.getElementById("v") is None
1240 and not a1.isId
1241 and not a2.isId)
1242 e.setIdAttributeNode(a1)
1243 self.confirm(e.isSameNode(doc.getElementById("v"))
1244 and a1.isId
1245 and not a2.isId)
1246 e.setIdAttributeNode(a2)
1247 self.confirm(e.isSameNode(doc.getElementById("v"))
1248 and e.isSameNode(doc.getElementById("w"))
1249 and a1.isId
1250 and a2.isId)
1251 # replace the a1 node; the new node should *not* be an ID
1252 a3 = doc.createAttributeNS(NS1, "a1")
1253 a3.value = "v"
1254 e.setAttributeNode(a3)
1255 self.confirm(e.isSameNode(doc.getElementById("w")))
1256 self.confirm(not a1.isId)
1257 self.confirm(a2.isId)
1258 self.confirm(not a3.isId)
1259 self.confirm(doc.getElementById("v") is None)
1260 # renaming an attribute should not affect its ID-ness:
1261 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
1262 self.confirm(e.isSameNode(doc.getElementById("w"))
1263 and a2.isId)
1264
1265 def testPickledDocument(self):
1266 doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
1267 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
1268 " 'http://xml.python.org/system' [\n"
1269 " <!ELEMENT e EMPTY>\n"
1270 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
1271 "]><doc attr='value'> text\n"
1272 "<?pi sample?> <!-- comment --> <e/> </doc>")
1273 s = pickle.dumps(doc)
1274 doc2 = pickle.loads(s)
1275 stack = [(doc, doc2)]
1276 while stack:
1277 n1, n2 = stack.pop()
1278 self.confirm(n1.nodeType == n2.nodeType
1279 and len(n1.childNodes) == len(n2.childNodes)
1280 and n1.nodeName == n2.nodeName
1281 and not n1.isSameNode(n2)
1282 and not n2.isSameNode(n1))
1283 if n1.nodeType == Node.DOCUMENT_TYPE_NODE:
1284 len(n1.entities)
1285 len(n2.entities)
1286 len(n1.notations)
1287 len(n2.notations)
1288 self.confirm(len(n1.entities) == len(n2.entities)
1289 and len(n1.notations) == len(n2.notations))
1290 for i in range(len(n1.notations)):
1291 no1 = n1.notations.item(i)
1292 no2 = n1.notations.item(i)
1293 self.confirm(no1.name == no2.name
1294 and no1.publicId == no2.publicId
1295 and no1.systemId == no2.systemId)
1296 statck.append((no1, no2))
1297 for i in range(len(n1.entities)):
1298 e1 = n1.entities.item(i)
1299 e2 = n2.entities.item(i)
1300 self.confirm(e1.notationName == e2.notationName
1301 and e1.publicId == e2.publicId
1302 and e1.systemId == e2.systemId)
1303 stack.append((e1, e2))
1304 if n1.nodeType != Node.DOCUMENT_NODE:
1305 self.confirm(n1.ownerDocument.isSameNode(doc)
1306 and n2.ownerDocument.isSameNode(doc2))
1307 for i in range(len(n1.childNodes)):
1308 stack.append((n1.childNodes[i], n2.childNodes[i]))
1309
1310def test_main():
1311 run_unittest(MinidomTest)
Neal Norwitz0d4c06e2007-04-25 06:30:05 +00001312
Collin Winterd28fcbc2007-03-28 23:34:06 +00001313if __name__ == "__main__":
1314 test_main()