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