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