]> git.proxmox.com Git - mirror_edk2.git/blame - AppPkg/Applications/Python/Python-2.7.2/Lib/test/test_minidom.py
EmbeddedPkg: Extend NvVarStoreFormattedLib LIBRARY_CLASS
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / test / test_minidom.py
CommitLineData
4710c53d 1# test for xml.dom.minidom\r
2\r
3import pickle\r
4from StringIO import StringIO\r
5from test.test_support import verbose, run_unittest, findfile\r
6import unittest\r
7\r
8import xml.dom\r
9import xml.dom.minidom\r
10import xml.parsers.expat\r
11\r
12from xml.dom.minidom import parse, Node, Document, parseString\r
13from xml.dom.minidom import getDOMImplementation\r
14\r
15\r
16tstfile = findfile("test.xml", subdir="xmltestdata")\r
17\r
18\r
19# The tests of DocumentType importing use these helpers to construct\r
20# the documents to work with, since not all DOM builders actually\r
21# create the DocumentType nodes.\r
22def create_doc_without_doctype(doctype=None):\r
23 return getDOMImplementation().createDocument(None, "doc", doctype)\r
24\r
25def create_nonempty_doctype():\r
26 doctype = getDOMImplementation().createDocumentType("doc", None, None)\r
27 doctype.entities._seq = []\r
28 doctype.notations._seq = []\r
29 notation = xml.dom.minidom.Notation("my-notation", None,\r
30 "http://xml.python.org/notations/my")\r
31 doctype.notations._seq.append(notation)\r
32 entity = xml.dom.minidom.Entity("my-entity", None,\r
33 "http://xml.python.org/entities/my",\r
34 "my-notation")\r
35 entity.version = "1.0"\r
36 entity.encoding = "utf-8"\r
37 entity.actualEncoding = "us-ascii"\r
38 doctype.entities._seq.append(entity)\r
39 return doctype\r
40\r
41def create_doc_with_doctype():\r
42 doctype = create_nonempty_doctype()\r
43 doc = create_doc_without_doctype(doctype)\r
44 doctype.entities.item(0).ownerDocument = doc\r
45 doctype.notations.item(0).ownerDocument = doc\r
46 return doc\r
47\r
48class MinidomTest(unittest.TestCase):\r
49 def confirm(self, test, testname = "Test"):\r
50 self.assertTrue(test, testname)\r
51\r
52 def checkWholeText(self, node, s):\r
53 t = node.wholeText\r
54 self.confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))\r
55\r
56 def testParseFromFile(self):\r
57 dom = parse(StringIO(open(tstfile).read()))\r
58 dom.unlink()\r
59 self.confirm(isinstance(dom,Document))\r
60\r
61 def testGetElementsByTagName(self):\r
62 dom = parse(tstfile)\r
63 self.confirm(dom.getElementsByTagName("LI") == \\r
64 dom.documentElement.getElementsByTagName("LI"))\r
65 dom.unlink()\r
66\r
67 def testInsertBefore(self):\r
68 dom = parseString("<doc><foo/></doc>")\r
69 root = dom.documentElement\r
70 elem = root.childNodes[0]\r
71 nelem = dom.createElement("element")\r
72 root.insertBefore(nelem, elem)\r
73 self.confirm(len(root.childNodes) == 2\r
74 and root.childNodes.length == 2\r
75 and root.childNodes[0] is nelem\r
76 and root.childNodes.item(0) is nelem\r
77 and root.childNodes[1] is elem\r
78 and root.childNodes.item(1) is elem\r
79 and root.firstChild is nelem\r
80 and root.lastChild is elem\r
81 and root.toxml() == "<doc><element/><foo/></doc>"\r
82 , "testInsertBefore -- node properly placed in tree")\r
83 nelem = dom.createElement("element")\r
84 root.insertBefore(nelem, None)\r
85 self.confirm(len(root.childNodes) == 3\r
86 and root.childNodes.length == 3\r
87 and root.childNodes[1] is elem\r
88 and root.childNodes.item(1) is elem\r
89 and root.childNodes[2] is nelem\r
90 and root.childNodes.item(2) is nelem\r
91 and root.lastChild is nelem\r
92 and nelem.previousSibling is elem\r
93 and root.toxml() == "<doc><element/><foo/><element/></doc>"\r
94 , "testInsertBefore -- node properly placed in tree")\r
95 nelem2 = dom.createElement("bar")\r
96 root.insertBefore(nelem2, nelem)\r
97 self.confirm(len(root.childNodes) == 4\r
98 and root.childNodes.length == 4\r
99 and root.childNodes[2] is nelem2\r
100 and root.childNodes.item(2) is nelem2\r
101 and root.childNodes[3] is nelem\r
102 and root.childNodes.item(3) is nelem\r
103 and nelem2.nextSibling is nelem\r
104 and nelem.previousSibling is nelem2\r
105 and root.toxml() ==\r
106 "<doc><element/><foo/><bar/><element/></doc>"\r
107 , "testInsertBefore -- node properly placed in tree")\r
108 dom.unlink()\r
109\r
110 def _create_fragment_test_nodes(self):\r
111 dom = parseString("<doc/>")\r
112 orig = dom.createTextNode("original")\r
113 c1 = dom.createTextNode("foo")\r
114 c2 = dom.createTextNode("bar")\r
115 c3 = dom.createTextNode("bat")\r
116 dom.documentElement.appendChild(orig)\r
117 frag = dom.createDocumentFragment()\r
118 frag.appendChild(c1)\r
119 frag.appendChild(c2)\r
120 frag.appendChild(c3)\r
121 return dom, orig, c1, c2, c3, frag\r
122\r
123 def testInsertBeforeFragment(self):\r
124 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()\r
125 dom.documentElement.insertBefore(frag, None)\r
126 self.confirm(tuple(dom.documentElement.childNodes) ==\r
127 (orig, c1, c2, c3),\r
128 "insertBefore(<fragment>, None)")\r
129 frag.unlink()\r
130 dom.unlink()\r
131\r
132 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()\r
133 dom.documentElement.insertBefore(frag, orig)\r
134 self.confirm(tuple(dom.documentElement.childNodes) ==\r
135 (c1, c2, c3, orig),\r
136 "insertBefore(<fragment>, orig)")\r
137 frag.unlink()\r
138 dom.unlink()\r
139\r
140 def testAppendChild(self):\r
141 dom = parse(tstfile)\r
142 dom.documentElement.appendChild(dom.createComment(u"Hello"))\r
143 self.confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")\r
144 self.confirm(dom.documentElement.childNodes[-1].data == "Hello")\r
145 dom.unlink()\r
146\r
147 def testAppendChildFragment(self):\r
148 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()\r
149 dom.documentElement.appendChild(frag)\r
150 self.confirm(tuple(dom.documentElement.childNodes) ==\r
151 (orig, c1, c2, c3),\r
152 "appendChild(<fragment>)")\r
153 frag.unlink()\r
154 dom.unlink()\r
155\r
156 def testReplaceChildFragment(self):\r
157 dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()\r
158 dom.documentElement.replaceChild(frag, orig)\r
159 orig.unlink()\r
160 self.confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),\r
161 "replaceChild(<fragment>)")\r
162 frag.unlink()\r
163 dom.unlink()\r
164\r
165 def testLegalChildren(self):\r
166 dom = Document()\r
167 elem = dom.createElement('element')\r
168 text = dom.createTextNode('text')\r
169 self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text)\r
170\r
171 dom.appendChild(elem)\r
172 self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text,\r
173 elem)\r
174 self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text,\r
175 elem)\r
176\r
177 nodemap = elem.attributes\r
178 self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem,\r
179 text)\r
180 self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS,\r
181 text)\r
182\r
183 elem.appendChild(text)\r
184 dom.unlink()\r
185\r
186 def testNamedNodeMapSetItem(self):\r
187 dom = Document()\r
188 elem = dom.createElement('element')\r
189 attrs = elem.attributes\r
190 attrs["foo"] = "bar"\r
191 a = attrs.item(0)\r
192 self.confirm(a.ownerDocument is dom,\r
193 "NamedNodeMap.__setitem__() sets ownerDocument")\r
194 self.confirm(a.ownerElement is elem,\r
195 "NamedNodeMap.__setitem__() sets ownerElement")\r
196 self.confirm(a.value == "bar",\r
197 "NamedNodeMap.__setitem__() sets value")\r
198 self.confirm(a.nodeValue == "bar",\r
199 "NamedNodeMap.__setitem__() sets nodeValue")\r
200 elem.unlink()\r
201 dom.unlink()\r
202\r
203 def testNonZero(self):\r
204 dom = parse(tstfile)\r
205 self.confirm(dom)# should not be zero\r
206 dom.appendChild(dom.createComment("foo"))\r
207 self.confirm(not dom.childNodes[-1].childNodes)\r
208 dom.unlink()\r
209\r
210 def testUnlink(self):\r
211 dom = parse(tstfile)\r
212 dom.unlink()\r
213\r
214 def testElement(self):\r
215 dom = Document()\r
216 dom.appendChild(dom.createElement("abc"))\r
217 self.confirm(dom.documentElement)\r
218 dom.unlink()\r
219\r
220 def testAAA(self):\r
221 dom = parseString("<abc/>")\r
222 el = dom.documentElement\r
223 el.setAttribute("spam", "jam2")\r
224 self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")\r
225 a = el.getAttributeNode("spam")\r
226 self.confirm(a.ownerDocument is dom,\r
227 "setAttribute() sets ownerDocument")\r
228 self.confirm(a.ownerElement is dom.documentElement,\r
229 "setAttribute() sets ownerElement")\r
230 dom.unlink()\r
231\r
232 def testAAB(self):\r
233 dom = parseString("<abc/>")\r
234 el = dom.documentElement\r
235 el.setAttribute("spam", "jam")\r
236 el.setAttribute("spam", "jam2")\r
237 self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")\r
238 dom.unlink()\r
239\r
240 def testAddAttr(self):\r
241 dom = Document()\r
242 child = dom.appendChild(dom.createElement("abc"))\r
243\r
244 child.setAttribute("def", "ghi")\r
245 self.confirm(child.getAttribute("def") == "ghi")\r
246 self.confirm(child.attributes["def"].value == "ghi")\r
247\r
248 child.setAttribute("jkl", "mno")\r
249 self.confirm(child.getAttribute("jkl") == "mno")\r
250 self.confirm(child.attributes["jkl"].value == "mno")\r
251\r
252 self.confirm(len(child.attributes) == 2)\r
253\r
254 child.setAttribute("def", "newval")\r
255 self.confirm(child.getAttribute("def") == "newval")\r
256 self.confirm(child.attributes["def"].value == "newval")\r
257\r
258 self.confirm(len(child.attributes) == 2)\r
259 dom.unlink()\r
260\r
261 def testDeleteAttr(self):\r
262 dom = Document()\r
263 child = dom.appendChild(dom.createElement("abc"))\r
264\r
265 self.confirm(len(child.attributes) == 0)\r
266 child.setAttribute("def", "ghi")\r
267 self.confirm(len(child.attributes) == 1)\r
268 del child.attributes["def"]\r
269 self.confirm(len(child.attributes) == 0)\r
270 dom.unlink()\r
271\r
272 def testRemoveAttr(self):\r
273 dom = Document()\r
274 child = dom.appendChild(dom.createElement("abc"))\r
275\r
276 child.setAttribute("def", "ghi")\r
277 self.confirm(len(child.attributes) == 1)\r
278 child.removeAttribute("def")\r
279 self.confirm(len(child.attributes) == 0)\r
280 dom.unlink()\r
281\r
282 def testRemoveAttrNS(self):\r
283 dom = Document()\r
284 child = dom.appendChild(\r
285 dom.createElementNS("http://www.python.org", "python:abc"))\r
286 child.setAttributeNS("http://www.w3.org", "xmlns:python",\r
287 "http://www.python.org")\r
288 child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")\r
289 self.confirm(len(child.attributes) == 2)\r
290 child.removeAttributeNS("http://www.python.org", "abcattr")\r
291 self.confirm(len(child.attributes) == 1)\r
292 dom.unlink()\r
293\r
294 def testRemoveAttributeNode(self):\r
295 dom = Document()\r
296 child = dom.appendChild(dom.createElement("foo"))\r
297 child.setAttribute("spam", "jam")\r
298 self.confirm(len(child.attributes) == 1)\r
299 node = child.getAttributeNode("spam")\r
300 child.removeAttributeNode(node)\r
301 self.confirm(len(child.attributes) == 0\r
302 and child.getAttributeNode("spam") is None)\r
303 dom.unlink()\r
304\r
305 def testChangeAttr(self):\r
306 dom = parseString("<abc/>")\r
307 el = dom.documentElement\r
308 el.setAttribute("spam", "jam")\r
309 self.confirm(len(el.attributes) == 1)\r
310 el.setAttribute("spam", "bam")\r
311 # Set this attribute to be an ID and make sure that doesn't change\r
312 # when changing the value:\r
313 el.setIdAttribute("spam")\r
314 self.confirm(len(el.attributes) == 1\r
315 and el.attributes["spam"].value == "bam"\r
316 and el.attributes["spam"].nodeValue == "bam"\r
317 and el.getAttribute("spam") == "bam"\r
318 and el.getAttributeNode("spam").isId)\r
319 el.attributes["spam"] = "ham"\r
320 self.confirm(len(el.attributes) == 1\r
321 and el.attributes["spam"].value == "ham"\r
322 and el.attributes["spam"].nodeValue == "ham"\r
323 and el.getAttribute("spam") == "ham"\r
324 and el.attributes["spam"].isId)\r
325 el.setAttribute("spam2", "bam")\r
326 self.confirm(len(el.attributes) == 2\r
327 and el.attributes["spam"].value == "ham"\r
328 and el.attributes["spam"].nodeValue == "ham"\r
329 and el.getAttribute("spam") == "ham"\r
330 and el.attributes["spam2"].value == "bam"\r
331 and el.attributes["spam2"].nodeValue == "bam"\r
332 and el.getAttribute("spam2") == "bam")\r
333 el.attributes["spam2"] = "bam2"\r
334 self.confirm(len(el.attributes) == 2\r
335 and el.attributes["spam"].value == "ham"\r
336 and el.attributes["spam"].nodeValue == "ham"\r
337 and el.getAttribute("spam") == "ham"\r
338 and el.attributes["spam2"].value == "bam2"\r
339 and el.attributes["spam2"].nodeValue == "bam2"\r
340 and el.getAttribute("spam2") == "bam2")\r
341 dom.unlink()\r
342\r
343 def testGetAttrList(self):\r
344 pass\r
345\r
346 def testGetAttrValues(self): pass\r
347\r
348 def testGetAttrLength(self): pass\r
349\r
350 def testGetAttribute(self): pass\r
351\r
352 def testGetAttributeNS(self): pass\r
353\r
354 def testGetAttributeNode(self): pass\r
355\r
356 def testGetElementsByTagNameNS(self):\r
357 d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>\r
358 <minidom:myelem/>\r
359 </foo>"""\r
360 dom = parseString(d)\r
361 elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom",\r
362 "myelem")\r
363 self.confirm(len(elems) == 1\r
364 and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"\r
365 and elems[0].localName == "myelem"\r
366 and elems[0].prefix == "minidom"\r
367 and elems[0].tagName == "minidom:myelem"\r
368 and elems[0].nodeName == "minidom:myelem")\r
369 dom.unlink()\r
370\r
371 def get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri,\r
372 lname):\r
373 nodelist = doc.getElementsByTagNameNS(nsuri, lname)\r
374 self.confirm(len(nodelist) == 0)\r
375\r
376 def testGetEmptyNodeListFromElementsByTagNameNS(self):\r
377 doc = parseString('<doc/>')\r
378 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(\r
379 doc, 'http://xml.python.org/namespaces/a', 'localname')\r
380 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(\r
381 doc, '*', 'splat')\r
382 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(\r
383 doc, 'http://xml.python.org/namespaces/a', '*')\r
384\r
385 doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')\r
386 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(\r
387 doc, "http://xml.python.org/splat", "not-there")\r
388 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(\r
389 doc, "*", "not-there")\r
390 self.get_empty_nodelist_from_elements_by_tagName_ns_helper(\r
391 doc, "http://somewhere.else.net/not-there", "e")\r
392\r
393 def testElementReprAndStr(self):\r
394 dom = Document()\r
395 el = dom.appendChild(dom.createElement("abc"))\r
396 string1 = repr(el)\r
397 string2 = str(el)\r
398 self.confirm(string1 == string2)\r
399 dom.unlink()\r
400\r
401 def testElementReprAndStrUnicode(self):\r
402 dom = Document()\r
403 el = dom.appendChild(dom.createElement(u"abc"))\r
404 string1 = repr(el)\r
405 string2 = str(el)\r
406 self.confirm(string1 == string2)\r
407 dom.unlink()\r
408\r
409 def testElementReprAndStrUnicodeNS(self):\r
410 dom = Document()\r
411 el = dom.appendChild(\r
412 dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))\r
413 string1 = repr(el)\r
414 string2 = str(el)\r
415 self.confirm(string1 == string2)\r
416 self.confirm("slash:abc" in string1)\r
417 dom.unlink()\r
418\r
419 def testAttributeRepr(self):\r
420 dom = Document()\r
421 el = dom.appendChild(dom.createElement(u"abc"))\r
422 node = el.setAttribute("abc", "def")\r
423 self.confirm(str(node) == repr(node))\r
424 dom.unlink()\r
425\r
426 def testTextNodeRepr(self): pass\r
427\r
428 def testWriteXML(self):\r
429 str = '<?xml version="1.0" ?><a b="c"/>'\r
430 dom = parseString(str)\r
431 domstr = dom.toxml()\r
432 dom.unlink()\r
433 self.confirm(str == domstr)\r
434\r
435 def testAltNewline(self):\r
436 str = '<?xml version="1.0" ?>\n<a b="c"/>\n'\r
437 dom = parseString(str)\r
438 domstr = dom.toprettyxml(newl="\r\n")\r
439 dom.unlink()\r
440 self.confirm(domstr == str.replace("\n", "\r\n"))\r
441\r
442 def testProcessingInstruction(self):\r
443 dom = parseString('<e><?mypi \t\n data \t\n ?></e>')\r
444 pi = dom.documentElement.firstChild\r
445 self.confirm(pi.target == "mypi"\r
446 and pi.data == "data \t\n "\r
447 and pi.nodeName == "mypi"\r
448 and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE\r
449 and pi.attributes is None\r
450 and not pi.hasChildNodes()\r
451 and len(pi.childNodes) == 0\r
452 and pi.firstChild is None\r
453 and pi.lastChild is None\r
454 and pi.localName is None\r
455 and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)\r
456\r
457 def testProcessingInstructionRepr(self): pass\r
458\r
459 def testTextRepr(self): pass\r
460\r
461 def testWriteText(self): pass\r
462\r
463 def testDocumentElement(self): pass\r
464\r
465 def testTooManyDocumentElements(self):\r
466 doc = parseString("<doc/>")\r
467 elem = doc.createElement("extra")\r
468 # Should raise an exception when adding an extra document element.\r
469 self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem)\r
470 elem.unlink()\r
471 doc.unlink()\r
472\r
473 def testCreateElementNS(self): pass\r
474\r
475 def testCreateAttributeNS(self): pass\r
476\r
477 def testParse(self): pass\r
478\r
479 def testParseString(self): pass\r
480\r
481 def testComment(self): pass\r
482\r
483 def testAttrListItem(self): pass\r
484\r
485 def testAttrListItems(self): pass\r
486\r
487 def testAttrListItemNS(self): pass\r
488\r
489 def testAttrListKeys(self): pass\r
490\r
491 def testAttrListKeysNS(self): pass\r
492\r
493 def testRemoveNamedItem(self):\r
494 doc = parseString("<doc a=''/>")\r
495 e = doc.documentElement\r
496 attrs = e.attributes\r
497 a1 = e.getAttributeNode("a")\r
498 a2 = attrs.removeNamedItem("a")\r
499 self.confirm(a1.isSameNode(a2))\r
500 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a")\r
501\r
502 def testRemoveNamedItemNS(self):\r
503 doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")\r
504 e = doc.documentElement\r
505 attrs = e.attributes\r
506 a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")\r
507 a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")\r
508 self.confirm(a1.isSameNode(a2))\r
509 self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS,\r
510 "http://xml.python.org/", "b")\r
511\r
512 def testAttrListValues(self): pass\r
513\r
514 def testAttrListLength(self): pass\r
515\r
516 def testAttrList__getitem__(self): pass\r
517\r
518 def testAttrList__setitem__(self): pass\r
519\r
520 def testSetAttrValueandNodeValue(self): pass\r
521\r
522 def testParseElement(self): pass\r
523\r
524 def testParseAttributes(self): pass\r
525\r
526 def testParseElementNamespaces(self): pass\r
527\r
528 def testParseAttributeNamespaces(self): pass\r
529\r
530 def testParseProcessingInstructions(self): pass\r
531\r
532 def testChildNodes(self): pass\r
533\r
534 def testFirstChild(self): pass\r
535\r
536 def testHasChildNodes(self): pass\r
537\r
538 def _testCloneElementCopiesAttributes(self, e1, e2, test):\r
539 attrs1 = e1.attributes\r
540 attrs2 = e2.attributes\r
541 keys1 = attrs1.keys()\r
542 keys2 = attrs2.keys()\r
543 keys1.sort()\r
544 keys2.sort()\r
545 self.confirm(keys1 == keys2, "clone of element has same attribute keys")\r
546 for i in range(len(keys1)):\r
547 a1 = attrs1.item(i)\r
548 a2 = attrs2.item(i)\r
549 self.confirm(a1 is not a2\r
550 and a1.value == a2.value\r
551 and a1.nodeValue == a2.nodeValue\r
552 and a1.namespaceURI == a2.namespaceURI\r
553 and a1.localName == a2.localName\r
554 , "clone of attribute node has proper attribute values")\r
555 self.confirm(a2.ownerElement is e2,\r
556 "clone of attribute node correctly owned")\r
557\r
558 def _setupCloneElement(self, deep):\r
559 dom = parseString("<doc attr='value'><foo/></doc>")\r
560 root = dom.documentElement\r
561 clone = root.cloneNode(deep)\r
562 self._testCloneElementCopiesAttributes(\r
563 root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))\r
564 # mutilate the original so shared data is detected\r
565 root.tagName = root.nodeName = "MODIFIED"\r
566 root.setAttribute("attr", "NEW VALUE")\r
567 root.setAttribute("added", "VALUE")\r
568 return dom, clone\r
569\r
570 def testCloneElementShallow(self):\r
571 dom, clone = self._setupCloneElement(0)\r
572 self.confirm(len(clone.childNodes) == 0\r
573 and clone.childNodes.length == 0\r
574 and clone.parentNode is None\r
575 and clone.toxml() == '<doc attr="value"/>'\r
576 , "testCloneElementShallow")\r
577 dom.unlink()\r
578\r
579 def testCloneElementDeep(self):\r
580 dom, clone = self._setupCloneElement(1)\r
581 self.confirm(len(clone.childNodes) == 1\r
582 and clone.childNodes.length == 1\r
583 and clone.parentNode is None\r
584 and clone.toxml() == '<doc attr="value"><foo/></doc>'\r
585 , "testCloneElementDeep")\r
586 dom.unlink()\r
587\r
588 def testCloneDocumentShallow(self):\r
589 doc = parseString("<?xml version='1.0'?>\n"\r
590 "<!-- comment -->"\r
591 "<!DOCTYPE doc [\n"\r
592 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"\r
593 "]>\n"\r
594 "<doc attr='value'/>")\r
595 doc2 = doc.cloneNode(0)\r
596 self.confirm(doc2 is None,\r
597 "testCloneDocumentShallow:"\r
598 " shallow cloning of documents makes no sense!")\r
599\r
600 def testCloneDocumentDeep(self):\r
601 doc = parseString("<?xml version='1.0'?>\n"\r
602 "<!-- comment -->"\r
603 "<!DOCTYPE doc [\n"\r
604 "<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"\r
605 "]>\n"\r
606 "<doc attr='value'/>")\r
607 doc2 = doc.cloneNode(1)\r
608 self.confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),\r
609 "testCloneDocumentDeep: document objects not distinct")\r
610 self.confirm(len(doc.childNodes) == len(doc2.childNodes),\r
611 "testCloneDocumentDeep: wrong number of Document children")\r
612 self.confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,\r
613 "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")\r
614 self.confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),\r
615 "testCloneDocumentDeep: documentElement owner is not new document")\r
616 self.confirm(not doc.documentElement.isSameNode(doc2.documentElement),\r
617 "testCloneDocumentDeep: documentElement should not be shared")\r
618 if doc.doctype is not None:\r
619 # check the doctype iff the original DOM maintained it\r
620 self.confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,\r
621 "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")\r
622 self.confirm(doc2.doctype.ownerDocument.isSameNode(doc2))\r
623 self.confirm(not doc.doctype.isSameNode(doc2.doctype))\r
624\r
625 def testCloneDocumentTypeDeepOk(self):\r
626 doctype = create_nonempty_doctype()\r
627 clone = doctype.cloneNode(1)\r
628 self.confirm(clone is not None\r
629 and clone.nodeName == doctype.nodeName\r
630 and clone.name == doctype.name\r
631 and clone.publicId == doctype.publicId\r
632 and clone.systemId == doctype.systemId\r
633 and len(clone.entities) == len(doctype.entities)\r
634 and clone.entities.item(len(clone.entities)) is None\r
635 and len(clone.notations) == len(doctype.notations)\r
636 and clone.notations.item(len(clone.notations)) is None\r
637 and len(clone.childNodes) == 0)\r
638 for i in range(len(doctype.entities)):\r
639 se = doctype.entities.item(i)\r
640 ce = clone.entities.item(i)\r
641 self.confirm((not se.isSameNode(ce))\r
642 and (not ce.isSameNode(se))\r
643 and ce.nodeName == se.nodeName\r
644 and ce.notationName == se.notationName\r
645 and ce.publicId == se.publicId\r
646 and ce.systemId == se.systemId\r
647 and ce.encoding == se.encoding\r
648 and ce.actualEncoding == se.actualEncoding\r
649 and ce.version == se.version)\r
650 for i in range(len(doctype.notations)):\r
651 sn = doctype.notations.item(i)\r
652 cn = clone.notations.item(i)\r
653 self.confirm((not sn.isSameNode(cn))\r
654 and (not cn.isSameNode(sn))\r
655 and cn.nodeName == sn.nodeName\r
656 and cn.publicId == sn.publicId\r
657 and cn.systemId == sn.systemId)\r
658\r
659 def testCloneDocumentTypeDeepNotOk(self):\r
660 doc = create_doc_with_doctype()\r
661 clone = doc.doctype.cloneNode(1)\r
662 self.confirm(clone is None, "testCloneDocumentTypeDeepNotOk")\r
663\r
664 def testCloneDocumentTypeShallowOk(self):\r
665 doctype = create_nonempty_doctype()\r
666 clone = doctype.cloneNode(0)\r
667 self.confirm(clone is not None\r
668 and clone.nodeName == doctype.nodeName\r
669 and clone.name == doctype.name\r
670 and clone.publicId == doctype.publicId\r
671 and clone.systemId == doctype.systemId\r
672 and len(clone.entities) == 0\r
673 and clone.entities.item(0) is None\r
674 and len(clone.notations) == 0\r
675 and clone.notations.item(0) is None\r
676 and len(clone.childNodes) == 0)\r
677\r
678 def testCloneDocumentTypeShallowNotOk(self):\r
679 doc = create_doc_with_doctype()\r
680 clone = doc.doctype.cloneNode(0)\r
681 self.confirm(clone is None, "testCloneDocumentTypeShallowNotOk")\r
682\r
683 def check_import_document(self, deep, testName):\r
684 doc1 = parseString("<doc/>")\r
685 doc2 = parseString("<doc/>")\r
686 self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep)\r
687\r
688 def testImportDocumentShallow(self):\r
689 self.check_import_document(0, "testImportDocumentShallow")\r
690\r
691 def testImportDocumentDeep(self):\r
692 self.check_import_document(1, "testImportDocumentDeep")\r
693\r
694 def testImportDocumentTypeShallow(self):\r
695 src = create_doc_with_doctype()\r
696 target = create_doc_without_doctype()\r
697 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,\r
698 src.doctype, 0)\r
699\r
700 def testImportDocumentTypeDeep(self):\r
701 src = create_doc_with_doctype()\r
702 target = create_doc_without_doctype()\r
703 self.assertRaises(xml.dom.NotSupportedErr, target.importNode,\r
704 src.doctype, 1)\r
705\r
706 # Testing attribute clones uses a helper, and should always be deep,\r
707 # even if the argument to cloneNode is false.\r
708 def check_clone_attribute(self, deep, testName):\r
709 doc = parseString("<doc attr='value'/>")\r
710 attr = doc.documentElement.getAttributeNode("attr")\r
711 self.assertNotEqual(attr, None)\r
712 clone = attr.cloneNode(deep)\r
713 self.confirm(not clone.isSameNode(attr))\r
714 self.confirm(not attr.isSameNode(clone))\r
715 self.confirm(clone.ownerElement is None,\r
716 testName + ": ownerElement should be None")\r
717 self.confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),\r
718 testName + ": ownerDocument does not match")\r
719 self.confirm(clone.specified,\r
720 testName + ": cloned attribute must have specified == True")\r
721\r
722 def testCloneAttributeShallow(self):\r
723 self.check_clone_attribute(0, "testCloneAttributeShallow")\r
724\r
725 def testCloneAttributeDeep(self):\r
726 self.check_clone_attribute(1, "testCloneAttributeDeep")\r
727\r
728 def check_clone_pi(self, deep, testName):\r
729 doc = parseString("<?target data?><doc/>")\r
730 pi = doc.firstChild\r
731 self.assertEqual(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE)\r
732 clone = pi.cloneNode(deep)\r
733 self.confirm(clone.target == pi.target\r
734 and clone.data == pi.data)\r
735\r
736 def testClonePIShallow(self):\r
737 self.check_clone_pi(0, "testClonePIShallow")\r
738\r
739 def testClonePIDeep(self):\r
740 self.check_clone_pi(1, "testClonePIDeep")\r
741\r
742 def testNormalize(self):\r
743 doc = parseString("<doc/>")\r
744 root = doc.documentElement\r
745 root.appendChild(doc.createTextNode("first"))\r
746 root.appendChild(doc.createTextNode("second"))\r
747 self.confirm(len(root.childNodes) == 2\r
748 and root.childNodes.length == 2,\r
749 "testNormalize -- preparation")\r
750 doc.normalize()\r
751 self.confirm(len(root.childNodes) == 1\r
752 and root.childNodes.length == 1\r
753 and root.firstChild is root.lastChild\r
754 and root.firstChild.data == "firstsecond"\r
755 , "testNormalize -- result")\r
756 doc.unlink()\r
757\r
758 doc = parseString("<doc/>")\r
759 root = doc.documentElement\r
760 root.appendChild(doc.createTextNode(""))\r
761 doc.normalize()\r
762 self.confirm(len(root.childNodes) == 0\r
763 and root.childNodes.length == 0,\r
764 "testNormalize -- single empty node removed")\r
765 doc.unlink()\r
766\r
767 def testNormalizeCombineAndNextSibling(self):\r
768 doc = parseString("<doc/>")\r
769 root = doc.documentElement\r
770 root.appendChild(doc.createTextNode("first"))\r
771 root.appendChild(doc.createTextNode("second"))\r
772 root.appendChild(doc.createElement("i"))\r
773 self.confirm(len(root.childNodes) == 3\r
774 and root.childNodes.length == 3,\r
775 "testNormalizeCombineAndNextSibling -- preparation")\r
776 doc.normalize()\r
777 self.confirm(len(root.childNodes) == 2\r
778 and root.childNodes.length == 2\r
779 and root.firstChild.data == "firstsecond"\r
780 and root.firstChild is not root.lastChild\r
781 and root.firstChild.nextSibling is root.lastChild\r
782 and root.firstChild.previousSibling is None\r
783 and root.lastChild.previousSibling is root.firstChild\r
784 and root.lastChild.nextSibling is None\r
785 , "testNormalizeCombinedAndNextSibling -- result")\r
786 doc.unlink()\r
787\r
788 def testNormalizeDeleteWithPrevSibling(self):\r
789 doc = parseString("<doc/>")\r
790 root = doc.documentElement\r
791 root.appendChild(doc.createTextNode("first"))\r
792 root.appendChild(doc.createTextNode(""))\r
793 self.confirm(len(root.childNodes) == 2\r
794 and root.childNodes.length == 2,\r
795 "testNormalizeDeleteWithPrevSibling -- preparation")\r
796 doc.normalize()\r
797 self.confirm(len(root.childNodes) == 1\r
798 and root.childNodes.length == 1\r
799 and root.firstChild.data == "first"\r
800 and root.firstChild is root.lastChild\r
801 and root.firstChild.nextSibling is None\r
802 and root.firstChild.previousSibling is None\r
803 , "testNormalizeDeleteWithPrevSibling -- result")\r
804 doc.unlink()\r
805\r
806 def testNormalizeDeleteWithNextSibling(self):\r
807 doc = parseString("<doc/>")\r
808 root = doc.documentElement\r
809 root.appendChild(doc.createTextNode(""))\r
810 root.appendChild(doc.createTextNode("second"))\r
811 self.confirm(len(root.childNodes) == 2\r
812 and root.childNodes.length == 2,\r
813 "testNormalizeDeleteWithNextSibling -- preparation")\r
814 doc.normalize()\r
815 self.confirm(len(root.childNodes) == 1\r
816 and root.childNodes.length == 1\r
817 and root.firstChild.data == "second"\r
818 and root.firstChild is root.lastChild\r
819 and root.firstChild.nextSibling is None\r
820 and root.firstChild.previousSibling is None\r
821 , "testNormalizeDeleteWithNextSibling -- result")\r
822 doc.unlink()\r
823\r
824 def testNormalizeDeleteWithTwoNonTextSiblings(self):\r
825 doc = parseString("<doc/>")\r
826 root = doc.documentElement\r
827 root.appendChild(doc.createElement("i"))\r
828 root.appendChild(doc.createTextNode(""))\r
829 root.appendChild(doc.createElement("i"))\r
830 self.confirm(len(root.childNodes) == 3\r
831 and root.childNodes.length == 3,\r
832 "testNormalizeDeleteWithTwoSiblings -- preparation")\r
833 doc.normalize()\r
834 self.confirm(len(root.childNodes) == 2\r
835 and root.childNodes.length == 2\r
836 and root.firstChild is not root.lastChild\r
837 and root.firstChild.nextSibling is root.lastChild\r
838 and root.firstChild.previousSibling is None\r
839 and root.lastChild.previousSibling is root.firstChild\r
840 and root.lastChild.nextSibling is None\r
841 , "testNormalizeDeleteWithTwoSiblings -- result")\r
842 doc.unlink()\r
843\r
844 def testNormalizeDeleteAndCombine(self):\r
845 doc = parseString("<doc/>")\r
846 root = doc.documentElement\r
847 root.appendChild(doc.createTextNode(""))\r
848 root.appendChild(doc.createTextNode("second"))\r
849 root.appendChild(doc.createTextNode(""))\r
850 root.appendChild(doc.createTextNode("fourth"))\r
851 root.appendChild(doc.createTextNode(""))\r
852 self.confirm(len(root.childNodes) == 5\r
853 and root.childNodes.length == 5,\r
854 "testNormalizeDeleteAndCombine -- preparation")\r
855 doc.normalize()\r
856 self.confirm(len(root.childNodes) == 1\r
857 and root.childNodes.length == 1\r
858 and root.firstChild is root.lastChild\r
859 and root.firstChild.data == "secondfourth"\r
860 and root.firstChild.previousSibling is None\r
861 and root.firstChild.nextSibling is None\r
862 , "testNormalizeDeleteAndCombine -- result")\r
863 doc.unlink()\r
864\r
865 def testNormalizeRecursion(self):\r
866 doc = parseString("<doc>"\r
867 "<o>"\r
868 "<i/>"\r
869 "t"\r
870 #\r
871 #x\r
872 "</o>"\r
873 "<o>"\r
874 "<o>"\r
875 "t2"\r
876 #x2\r
877 "</o>"\r
878 "t3"\r
879 #x3\r
880 "</o>"\r
881 #\r
882 "</doc>")\r
883 root = doc.documentElement\r
884 root.childNodes[0].appendChild(doc.createTextNode(""))\r
885 root.childNodes[0].appendChild(doc.createTextNode("x"))\r
886 root.childNodes[1].childNodes[0].appendChild(doc.createTextNode("x2"))\r
887 root.childNodes[1].appendChild(doc.createTextNode("x3"))\r
888 root.appendChild(doc.createTextNode(""))\r
889 self.confirm(len(root.childNodes) == 3\r
890 and root.childNodes.length == 3\r
891 and len(root.childNodes[0].childNodes) == 4\r
892 and root.childNodes[0].childNodes.length == 4\r
893 and len(root.childNodes[1].childNodes) == 3\r
894 and root.childNodes[1].childNodes.length == 3\r
895 and len(root.childNodes[1].childNodes[0].childNodes) == 2\r
896 and root.childNodes[1].childNodes[0].childNodes.length == 2\r
897 , "testNormalize2 -- preparation")\r
898 doc.normalize()\r
899 self.confirm(len(root.childNodes) == 2\r
900 and root.childNodes.length == 2\r
901 and len(root.childNodes[0].childNodes) == 2\r
902 and root.childNodes[0].childNodes.length == 2\r
903 and len(root.childNodes[1].childNodes) == 2\r
904 and root.childNodes[1].childNodes.length == 2\r
905 and len(root.childNodes[1].childNodes[0].childNodes) == 1\r
906 and root.childNodes[1].childNodes[0].childNodes.length == 1\r
907 , "testNormalize2 -- childNodes lengths")\r
908 self.confirm(root.childNodes[0].childNodes[1].data == "tx"\r
909 and root.childNodes[1].childNodes[0].childNodes[0].data == "t2x2"\r
910 and root.childNodes[1].childNodes[1].data == "t3x3"\r
911 , "testNormalize2 -- joined text fields")\r
912 self.confirm(root.childNodes[0].childNodes[1].nextSibling is None\r
913 and root.childNodes[0].childNodes[1].previousSibling\r
914 is root.childNodes[0].childNodes[0]\r
915 and root.childNodes[0].childNodes[0].previousSibling is None\r
916 and root.childNodes[0].childNodes[0].nextSibling\r
917 is root.childNodes[0].childNodes[1]\r
918 and root.childNodes[1].childNodes[1].nextSibling is None\r
919 and root.childNodes[1].childNodes[1].previousSibling\r
920 is root.childNodes[1].childNodes[0]\r
921 and root.childNodes[1].childNodes[0].previousSibling is None\r
922 and root.childNodes[1].childNodes[0].nextSibling\r
923 is root.childNodes[1].childNodes[1]\r
924 , "testNormalize2 -- sibling pointers")\r
925 doc.unlink()\r
926\r
927\r
928 def testBug0777884(self):\r
929 doc = parseString("<o>text</o>")\r
930 text = doc.documentElement.childNodes[0]\r
931 self.assertEqual(text.nodeType, Node.TEXT_NODE)\r
932 # Should run quietly, doing nothing.\r
933 text.normalize()\r
934 doc.unlink()\r
935\r
936 def testBug1433694(self):\r
937 doc = parseString("<o><i/>t</o>")\r
938 node = doc.documentElement\r
939 node.childNodes[1].nodeValue = ""\r
940 node.normalize()\r
941 self.confirm(node.childNodes[-1].nextSibling is None,\r
942 "Final child's .nextSibling should be None")\r
943\r
944 def testSiblings(self):\r
945 doc = parseString("<doc><?pi?>text?<elm/></doc>")\r
946 root = doc.documentElement\r
947 (pi, text, elm) = root.childNodes\r
948\r
949 self.confirm(pi.nextSibling is text and\r
950 pi.previousSibling is None and\r
951 text.nextSibling is elm and\r
952 text.previousSibling is pi and\r
953 elm.nextSibling is None and\r
954 elm.previousSibling is text, "testSiblings")\r
955\r
956 doc.unlink()\r
957\r
958 def testParents(self):\r
959 doc = parseString(\r
960 "<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")\r
961 root = doc.documentElement\r
962 elm1 = root.childNodes[0]\r
963 (elm2a, elm2b) = elm1.childNodes\r
964 elm3 = elm2b.childNodes[0]\r
965\r
966 self.confirm(root.parentNode is doc and\r
967 elm1.parentNode is root and\r
968 elm2a.parentNode is elm1 and\r
969 elm2b.parentNode is elm1 and\r
970 elm3.parentNode is elm2b, "testParents")\r
971 doc.unlink()\r
972\r
973 def testNodeListItem(self):\r
974 doc = parseString("<doc><e/><e/></doc>")\r
975 children = doc.childNodes\r
976 docelem = children[0]\r
977 self.confirm(children[0] is children.item(0)\r
978 and children.item(1) is None\r
979 and docelem.childNodes.item(0) is docelem.childNodes[0]\r
980 and docelem.childNodes.item(1) is docelem.childNodes[1]\r
981 and docelem.childNodes.item(0).childNodes.item(0) is None,\r
982 "test NodeList.item()")\r
983 doc.unlink()\r
984\r
985 def testSAX2DOM(self):\r
986 from xml.dom import pulldom\r
987\r
988 sax2dom = pulldom.SAX2DOM()\r
989 sax2dom.startDocument()\r
990 sax2dom.startElement("doc", {})\r
991 sax2dom.characters("text")\r
992 sax2dom.startElement("subelm", {})\r
993 sax2dom.characters("text")\r
994 sax2dom.endElement("subelm")\r
995 sax2dom.characters("text")\r
996 sax2dom.endElement("doc")\r
997 sax2dom.endDocument()\r
998\r
999 doc = sax2dom.document\r
1000 root = doc.documentElement\r
1001 (text1, elm1, text2) = root.childNodes\r
1002 text3 = elm1.childNodes[0]\r
1003\r
1004 self.confirm(text1.previousSibling is None and\r
1005 text1.nextSibling is elm1 and\r
1006 elm1.previousSibling is text1 and\r
1007 elm1.nextSibling is text2 and\r
1008 text2.previousSibling is elm1 and\r
1009 text2.nextSibling is None and\r
1010 text3.previousSibling is None and\r
1011 text3.nextSibling is None, "testSAX2DOM - siblings")\r
1012\r
1013 self.confirm(root.parentNode is doc and\r
1014 text1.parentNode is root and\r
1015 elm1.parentNode is root and\r
1016 text2.parentNode is root and\r
1017 text3.parentNode is elm1, "testSAX2DOM - parents")\r
1018 doc.unlink()\r
1019\r
1020 def testEncodings(self):\r
1021 doc = parseString('<foo>&#x20ac;</foo>')\r
1022 self.confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'\r
1023 and doc.toxml('utf-8') ==\r
1024 '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'\r
1025 and doc.toxml('iso-8859-15') ==\r
1026 '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',\r
1027 "testEncodings - encoding EURO SIGN")\r
1028\r
1029 # Verify that character decoding errors throw exceptions instead\r
1030 # of crashing\r
1031 self.assertRaises(UnicodeDecodeError, parseString,\r
1032 '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')\r
1033\r
1034 doc.unlink()\r
1035\r
1036 class UserDataHandler:\r
1037 called = 0\r
1038 def handle(self, operation, key, data, src, dst):\r
1039 dst.setUserData(key, data + 1, self)\r
1040 src.setUserData(key, None, None)\r
1041 self.called = 1\r
1042\r
1043 def testUserData(self):\r
1044 dom = Document()\r
1045 n = dom.createElement('e')\r
1046 self.confirm(n.getUserData("foo") is None)\r
1047 n.setUserData("foo", None, None)\r
1048 self.confirm(n.getUserData("foo") is None)\r
1049 n.setUserData("foo", 12, 12)\r
1050 n.setUserData("bar", 13, 13)\r
1051 self.confirm(n.getUserData("foo") == 12)\r
1052 self.confirm(n.getUserData("bar") == 13)\r
1053 n.setUserData("foo", None, None)\r
1054 self.confirm(n.getUserData("foo") is None)\r
1055 self.confirm(n.getUserData("bar") == 13)\r
1056\r
1057 handler = self.UserDataHandler()\r
1058 n.setUserData("bar", 12, handler)\r
1059 c = n.cloneNode(1)\r
1060 self.confirm(handler.called\r
1061 and n.getUserData("bar") is None\r
1062 and c.getUserData("bar") == 13)\r
1063 n.unlink()\r
1064 c.unlink()\r
1065 dom.unlink()\r
1066\r
1067 def checkRenameNodeSharedConstraints(self, doc, node):\r
1068 # Make sure illegal NS usage is detected:\r
1069 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node,\r
1070 "http://xml.python.org/ns", "xmlns:foo")\r
1071 doc2 = parseString("<doc/>")\r
1072 self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node,\r
1073 xml.dom.EMPTY_NAMESPACE, "foo")\r
1074\r
1075 def testRenameAttribute(self):\r
1076 doc = parseString("<doc a='v'/>")\r
1077 elem = doc.documentElement\r
1078 attrmap = elem.attributes\r
1079 attr = elem.attributes['a']\r
1080\r
1081 # Simple renaming\r
1082 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")\r
1083 self.confirm(attr.name == "b"\r
1084 and attr.nodeName == "b"\r
1085 and attr.localName is None\r
1086 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE\r
1087 and attr.prefix is None\r
1088 and attr.value == "v"\r
1089 and elem.getAttributeNode("a") is None\r
1090 and elem.getAttributeNode("b").isSameNode(attr)\r
1091 and attrmap["b"].isSameNode(attr)\r
1092 and attr.ownerDocument.isSameNode(doc)\r
1093 and attr.ownerElement.isSameNode(elem))\r
1094\r
1095 # Rename to have a namespace, no prefix\r
1096 attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")\r
1097 self.confirm(attr.name == "c"\r
1098 and attr.nodeName == "c"\r
1099 and attr.localName == "c"\r
1100 and attr.namespaceURI == "http://xml.python.org/ns"\r
1101 and attr.prefix is None\r
1102 and attr.value == "v"\r
1103 and elem.getAttributeNode("a") is None\r
1104 and elem.getAttributeNode("b") is None\r
1105 and elem.getAttributeNode("c").isSameNode(attr)\r
1106 and elem.getAttributeNodeNS(\r
1107 "http://xml.python.org/ns", "c").isSameNode(attr)\r
1108 and attrmap["c"].isSameNode(attr)\r
1109 and attrmap[("http://xml.python.org/ns", "c")].isSameNode(attr))\r
1110\r
1111 # Rename to have a namespace, with prefix\r
1112 attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")\r
1113 self.confirm(attr.name == "p:d"\r
1114 and attr.nodeName == "p:d"\r
1115 and attr.localName == "d"\r
1116 and attr.namespaceURI == "http://xml.python.org/ns2"\r
1117 and attr.prefix == "p"\r
1118 and attr.value == "v"\r
1119 and elem.getAttributeNode("a") is None\r
1120 and elem.getAttributeNode("b") is None\r
1121 and elem.getAttributeNode("c") is None\r
1122 and elem.getAttributeNodeNS(\r
1123 "http://xml.python.org/ns", "c") is None\r
1124 and elem.getAttributeNode("p:d").isSameNode(attr)\r
1125 and elem.getAttributeNodeNS(\r
1126 "http://xml.python.org/ns2", "d").isSameNode(attr)\r
1127 and attrmap["p:d"].isSameNode(attr)\r
1128 and attrmap[("http://xml.python.org/ns2", "d")].isSameNode(attr))\r
1129\r
1130 # Rename back to a simple non-NS node\r
1131 attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")\r
1132 self.confirm(attr.name == "e"\r
1133 and attr.nodeName == "e"\r
1134 and attr.localName is None\r
1135 and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE\r
1136 and attr.prefix is None\r
1137 and attr.value == "v"\r
1138 and elem.getAttributeNode("a") is None\r
1139 and elem.getAttributeNode("b") is None\r
1140 and elem.getAttributeNode("c") is None\r
1141 and elem.getAttributeNode("p:d") is None\r
1142 and elem.getAttributeNodeNS(\r
1143 "http://xml.python.org/ns", "c") is None\r
1144 and elem.getAttributeNode("e").isSameNode(attr)\r
1145 and attrmap["e"].isSameNode(attr))\r
1146\r
1147 self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr,\r
1148 "http://xml.python.org/ns", "xmlns")\r
1149 self.checkRenameNodeSharedConstraints(doc, attr)\r
1150 doc.unlink()\r
1151\r
1152 def testRenameElement(self):\r
1153 doc = parseString("<doc/>")\r
1154 elem = doc.documentElement\r
1155\r
1156 # Simple renaming\r
1157 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")\r
1158 self.confirm(elem.tagName == "a"\r
1159 and elem.nodeName == "a"\r
1160 and elem.localName is None\r
1161 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE\r
1162 and elem.prefix is None\r
1163 and elem.ownerDocument.isSameNode(doc))\r
1164\r
1165 # Rename to have a namespace, no prefix\r
1166 elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")\r
1167 self.confirm(elem.tagName == "b"\r
1168 and elem.nodeName == "b"\r
1169 and elem.localName == "b"\r
1170 and elem.namespaceURI == "http://xml.python.org/ns"\r
1171 and elem.prefix is None\r
1172 and elem.ownerDocument.isSameNode(doc))\r
1173\r
1174 # Rename to have a namespace, with prefix\r
1175 elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")\r
1176 self.confirm(elem.tagName == "p:c"\r
1177 and elem.nodeName == "p:c"\r
1178 and elem.localName == "c"\r
1179 and elem.namespaceURI == "http://xml.python.org/ns2"\r
1180 and elem.prefix == "p"\r
1181 and elem.ownerDocument.isSameNode(doc))\r
1182\r
1183 # Rename back to a simple non-NS node\r
1184 elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")\r
1185 self.confirm(elem.tagName == "d"\r
1186 and elem.nodeName == "d"\r
1187 and elem.localName is None\r
1188 and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE\r
1189 and elem.prefix is None\r
1190 and elem.ownerDocument.isSameNode(doc))\r
1191\r
1192 self.checkRenameNodeSharedConstraints(doc, elem)\r
1193 doc.unlink()\r
1194\r
1195 def testRenameOther(self):\r
1196 # We have to create a comment node explicitly since not all DOM\r
1197 # builders used with minidom add comments to the DOM.\r
1198 doc = xml.dom.minidom.getDOMImplementation().createDocument(\r
1199 xml.dom.EMPTY_NAMESPACE, "e", None)\r
1200 node = doc.createComment("comment")\r
1201 self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node,\r
1202 xml.dom.EMPTY_NAMESPACE, "foo")\r
1203 doc.unlink()\r
1204\r
1205 def testWholeText(self):\r
1206 doc = parseString("<doc>a</doc>")\r
1207 elem = doc.documentElement\r
1208 text = elem.childNodes[0]\r
1209 self.assertEqual(text.nodeType, Node.TEXT_NODE)\r
1210\r
1211 self.checkWholeText(text, "a")\r
1212 elem.appendChild(doc.createTextNode("b"))\r
1213 self.checkWholeText(text, "ab")\r
1214 elem.insertBefore(doc.createCDATASection("c"), text)\r
1215 self.checkWholeText(text, "cab")\r
1216\r
1217 # make sure we don't cross other nodes\r
1218 splitter = doc.createComment("comment")\r
1219 elem.appendChild(splitter)\r
1220 text2 = doc.createTextNode("d")\r
1221 elem.appendChild(text2)\r
1222 self.checkWholeText(text, "cab")\r
1223 self.checkWholeText(text2, "d")\r
1224\r
1225 x = doc.createElement("x")\r
1226 elem.replaceChild(x, splitter)\r
1227 splitter = x\r
1228 self.checkWholeText(text, "cab")\r
1229 self.checkWholeText(text2, "d")\r
1230\r
1231 x = doc.createProcessingInstruction("y", "z")\r
1232 elem.replaceChild(x, splitter)\r
1233 splitter = x\r
1234 self.checkWholeText(text, "cab")\r
1235 self.checkWholeText(text2, "d")\r
1236\r
1237 elem.removeChild(splitter)\r
1238 self.checkWholeText(text, "cabd")\r
1239 self.checkWholeText(text2, "cabd")\r
1240\r
1241 def testPatch1094164(self):\r
1242 doc = parseString("<doc><e/></doc>")\r
1243 elem = doc.documentElement\r
1244 e = elem.firstChild\r
1245 self.confirm(e.parentNode is elem, "Before replaceChild()")\r
1246 # Check that replacing a child with itself leaves the tree unchanged\r
1247 elem.replaceChild(e, e)\r
1248 self.confirm(e.parentNode is elem, "After replaceChild()")\r
1249\r
1250 def testReplaceWholeText(self):\r
1251 def setup():\r
1252 doc = parseString("<doc>a<e/>d</doc>")\r
1253 elem = doc.documentElement\r
1254 text1 = elem.firstChild\r
1255 text2 = elem.lastChild\r
1256 splitter = text1.nextSibling\r
1257 elem.insertBefore(doc.createTextNode("b"), splitter)\r
1258 elem.insertBefore(doc.createCDATASection("c"), text1)\r
1259 return doc, elem, text1, splitter, text2\r
1260\r
1261 doc, elem, text1, splitter, text2 = setup()\r
1262 text = text1.replaceWholeText("new content")\r
1263 self.checkWholeText(text, "new content")\r
1264 self.checkWholeText(text2, "d")\r
1265 self.confirm(len(elem.childNodes) == 3)\r
1266\r
1267 doc, elem, text1, splitter, text2 = setup()\r
1268 text = text2.replaceWholeText("new content")\r
1269 self.checkWholeText(text, "new content")\r
1270 self.checkWholeText(text1, "cab")\r
1271 self.confirm(len(elem.childNodes) == 5)\r
1272\r
1273 doc, elem, text1, splitter, text2 = setup()\r
1274 text = text1.replaceWholeText("")\r
1275 self.checkWholeText(text2, "d")\r
1276 self.confirm(text is None\r
1277 and len(elem.childNodes) == 2)\r
1278\r
1279 def testSchemaType(self):\r
1280 doc = parseString(\r
1281 "<!DOCTYPE doc [\n"\r
1282 " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"\r
1283 " <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"\r
1284 " <!ATTLIST doc id ID #IMPLIED \n"\r
1285 " ref IDREF #IMPLIED \n"\r
1286 " refs IDREFS #IMPLIED \n"\r
1287 " enum (a|b) #IMPLIED \n"\r
1288 " ent ENTITY #IMPLIED \n"\r
1289 " ents ENTITIES #IMPLIED \n"\r
1290 " nm NMTOKEN #IMPLIED \n"\r
1291 " nms NMTOKENS #IMPLIED \n"\r
1292 " text CDATA #IMPLIED \n"\r
1293 " >\n"\r
1294 "]><doc id='name' notid='name' text='splat!' enum='b'"\r
1295 " ref='name' refs='name name' ent='e1' ents='e1 e2'"\r
1296 " nm='123' nms='123 abc' />")\r
1297 elem = doc.documentElement\r
1298 # We don't want to rely on any specific loader at this point, so\r
1299 # just make sure we can get to all the names, and that the\r
1300 # DTD-based namespace is right. The names can vary by loader\r
1301 # since each supports a different level of DTD information.\r
1302 t = elem.schemaType\r
1303 self.confirm(t.name is None\r
1304 and t.namespace == xml.dom.EMPTY_NAMESPACE)\r
1305 names = "id notid text enum ref refs ent ents nm nms".split()\r
1306 for name in names:\r
1307 a = elem.getAttributeNode(name)\r
1308 t = a.schemaType\r
1309 self.confirm(hasattr(t, "name")\r
1310 and t.namespace == xml.dom.EMPTY_NAMESPACE)\r
1311\r
1312 def testSetIdAttribute(self):\r
1313 doc = parseString("<doc a1='v' a2='w'/>")\r
1314 e = doc.documentElement\r
1315 a1 = e.getAttributeNode("a1")\r
1316 a2 = e.getAttributeNode("a2")\r
1317 self.confirm(doc.getElementById("v") is None\r
1318 and not a1.isId\r
1319 and not a2.isId)\r
1320 e.setIdAttribute("a1")\r
1321 self.confirm(e.isSameNode(doc.getElementById("v"))\r
1322 and a1.isId\r
1323 and not a2.isId)\r
1324 e.setIdAttribute("a2")\r
1325 self.confirm(e.isSameNode(doc.getElementById("v"))\r
1326 and e.isSameNode(doc.getElementById("w"))\r
1327 and a1.isId\r
1328 and a2.isId)\r
1329 # replace the a1 node; the new node should *not* be an ID\r
1330 a3 = doc.createAttribute("a1")\r
1331 a3.value = "v"\r
1332 e.setAttributeNode(a3)\r
1333 self.confirm(doc.getElementById("v") is None\r
1334 and e.isSameNode(doc.getElementById("w"))\r
1335 and not a1.isId\r
1336 and a2.isId\r
1337 and not a3.isId)\r
1338 # renaming an attribute should not affect its ID-ness:\r
1339 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")\r
1340 self.confirm(e.isSameNode(doc.getElementById("w"))\r
1341 and a2.isId)\r
1342\r
1343 def testSetIdAttributeNS(self):\r
1344 NS1 = "http://xml.python.org/ns1"\r
1345 NS2 = "http://xml.python.org/ns2"\r
1346 doc = parseString("<doc"\r
1347 " xmlns:ns1='" + NS1 + "'"\r
1348 " xmlns:ns2='" + NS2 + "'"\r
1349 " ns1:a1='v' ns2:a2='w'/>")\r
1350 e = doc.documentElement\r
1351 a1 = e.getAttributeNodeNS(NS1, "a1")\r
1352 a2 = e.getAttributeNodeNS(NS2, "a2")\r
1353 self.confirm(doc.getElementById("v") is None\r
1354 and not a1.isId\r
1355 and not a2.isId)\r
1356 e.setIdAttributeNS(NS1, "a1")\r
1357 self.confirm(e.isSameNode(doc.getElementById("v"))\r
1358 and a1.isId\r
1359 and not a2.isId)\r
1360 e.setIdAttributeNS(NS2, "a2")\r
1361 self.confirm(e.isSameNode(doc.getElementById("v"))\r
1362 and e.isSameNode(doc.getElementById("w"))\r
1363 and a1.isId\r
1364 and a2.isId)\r
1365 # replace the a1 node; the new node should *not* be an ID\r
1366 a3 = doc.createAttributeNS(NS1, "a1")\r
1367 a3.value = "v"\r
1368 e.setAttributeNode(a3)\r
1369 self.confirm(e.isSameNode(doc.getElementById("w")))\r
1370 self.confirm(not a1.isId)\r
1371 self.confirm(a2.isId)\r
1372 self.confirm(not a3.isId)\r
1373 self.confirm(doc.getElementById("v") is None)\r
1374 # renaming an attribute should not affect its ID-ness:\r
1375 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")\r
1376 self.confirm(e.isSameNode(doc.getElementById("w"))\r
1377 and a2.isId)\r
1378\r
1379 def testSetIdAttributeNode(self):\r
1380 NS1 = "http://xml.python.org/ns1"\r
1381 NS2 = "http://xml.python.org/ns2"\r
1382 doc = parseString("<doc"\r
1383 " xmlns:ns1='" + NS1 + "'"\r
1384 " xmlns:ns2='" + NS2 + "'"\r
1385 " ns1:a1='v' ns2:a2='w'/>")\r
1386 e = doc.documentElement\r
1387 a1 = e.getAttributeNodeNS(NS1, "a1")\r
1388 a2 = e.getAttributeNodeNS(NS2, "a2")\r
1389 self.confirm(doc.getElementById("v") is None\r
1390 and not a1.isId\r
1391 and not a2.isId)\r
1392 e.setIdAttributeNode(a1)\r
1393 self.confirm(e.isSameNode(doc.getElementById("v"))\r
1394 and a1.isId\r
1395 and not a2.isId)\r
1396 e.setIdAttributeNode(a2)\r
1397 self.confirm(e.isSameNode(doc.getElementById("v"))\r
1398 and e.isSameNode(doc.getElementById("w"))\r
1399 and a1.isId\r
1400 and a2.isId)\r
1401 # replace the a1 node; the new node should *not* be an ID\r
1402 a3 = doc.createAttributeNS(NS1, "a1")\r
1403 a3.value = "v"\r
1404 e.setAttributeNode(a3)\r
1405 self.confirm(e.isSameNode(doc.getElementById("w")))\r
1406 self.confirm(not a1.isId)\r
1407 self.confirm(a2.isId)\r
1408 self.confirm(not a3.isId)\r
1409 self.confirm(doc.getElementById("v") is None)\r
1410 # renaming an attribute should not affect its ID-ness:\r
1411 doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")\r
1412 self.confirm(e.isSameNode(doc.getElementById("w"))\r
1413 and a2.isId)\r
1414\r
1415 def testPickledDocument(self):\r
1416 doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"\r
1417 "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"\r
1418 " 'http://xml.python.org/system' [\n"\r
1419 " <!ELEMENT e EMPTY>\n"\r
1420 " <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"\r
1421 "]><doc attr='value'> text\n"\r
1422 "<?pi sample?> <!-- comment --> <e/> </doc>")\r
1423 s = pickle.dumps(doc)\r
1424 doc2 = pickle.loads(s)\r
1425 stack = [(doc, doc2)]\r
1426 while stack:\r
1427 n1, n2 = stack.pop()\r
1428 self.confirm(n1.nodeType == n2.nodeType\r
1429 and len(n1.childNodes) == len(n2.childNodes)\r
1430 and n1.nodeName == n2.nodeName\r
1431 and not n1.isSameNode(n2)\r
1432 and not n2.isSameNode(n1))\r
1433 if n1.nodeType == Node.DOCUMENT_TYPE_NODE:\r
1434 len(n1.entities)\r
1435 len(n2.entities)\r
1436 len(n1.notations)\r
1437 len(n2.notations)\r
1438 self.confirm(len(n1.entities) == len(n2.entities)\r
1439 and len(n1.notations) == len(n2.notations))\r
1440 for i in range(len(n1.notations)):\r
1441 # XXX this loop body doesn't seem to be executed?\r
1442 no1 = n1.notations.item(i)\r
1443 no2 = n1.notations.item(i)\r
1444 self.confirm(no1.name == no2.name\r
1445 and no1.publicId == no2.publicId\r
1446 and no1.systemId == no2.systemId)\r
1447 stack.append((no1, no2))\r
1448 for i in range(len(n1.entities)):\r
1449 e1 = n1.entities.item(i)\r
1450 e2 = n2.entities.item(i)\r
1451 self.confirm(e1.notationName == e2.notationName\r
1452 and e1.publicId == e2.publicId\r
1453 and e1.systemId == e2.systemId)\r
1454 stack.append((e1, e2))\r
1455 if n1.nodeType != Node.DOCUMENT_NODE:\r
1456 self.confirm(n1.ownerDocument.isSameNode(doc)\r
1457 and n2.ownerDocument.isSameNode(doc2))\r
1458 for i in range(len(n1.childNodes)):\r
1459 stack.append((n1.childNodes[i], n2.childNodes[i]))\r
1460\r
1461 def testSerializeCommentNodeWithDoubleHyphen(self):\r
1462 doc = create_doc_without_doctype()\r
1463 doc.appendChild(doc.createComment("foo--bar"))\r
1464 self.assertRaises(ValueError, doc.toxml)\r
1465\r
1466 def testEmptyXMLNSValue(self):\r
1467 doc = parseString("<element xmlns=''>\n"\r
1468 "<foo/>\n</element>")\r
1469 doc2 = parseString(doc.toxml())\r
1470 self.confirm(doc2.namespaceURI == xml.dom.EMPTY_NAMESPACE)\r
1471\r
1472\r
1473def test_main():\r
1474 run_unittest(MinidomTest)\r
1475\r
1476if __name__ == "__main__":\r
1477 test_main()\r