Commit d28fcbc7 authored by Collin Winter's avatar Collin Winter

Consolidate patches #1690164, 1683397, and 1690169, all of which refactor...

Consolidate patches #1690164, 1683397, and 1690169, all of which refactor XML-related test suites. The patches are applied together because they use a common output/xmltests file.
Thanks to Jerry Seutter for all three patches.
parent 366d6262
test_pyexpat
OK.
OK.
OK.
OK.
OK.
OK.
OK.
OK.
OK.
OK.
OK.
OK.
PI:
'xml-stylesheet' 'href="stylesheet.css"'
Comment:
' comment data '
Notation declared: ('notation', None, 'notation.jpeg', None)
Unparsed entity decl:
('unparsed_entity', None, 'entity.file', None, 'notation')
Start element:
'root' {'attr1': 'value1', 'attr2': 'value2\xe1\xbd\x80'}
NS decl:
'myns' 'http://www.python.org/namespace'
Start element:
'http://www.python.org/namespace!subelement' {}
Character data:
'Contents of subelements'
End element:
'http://www.python.org/namespace!subelement'
End of NS decl:
'myns'
Start element:
'sub2' {}
Start of CDATA section
Character data:
'contents of CDATA section'
End of CDATA section
End element:
'sub2'
External entity ref: (None, 'entity.file', None)
End element:
'root'
PI:
u'xml-stylesheet' u'href="stylesheet.css"'
Comment:
u' comment data '
Notation declared: (u'notation', None, u'notation.jpeg', None)
Unparsed entity decl:
(u'unparsed_entity', None, u'entity.file', None, u'notation')
Start element:
u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
NS decl:
u'myns' u'http://www.python.org/namespace'
Start element:
u'http://www.python.org/namespace!subelement' {}
Character data:
u'Contents of subelements'
End element:
u'http://www.python.org/namespace!subelement'
End of NS decl:
u'myns'
Start element:
u'sub2' {}
Start of CDATA section
Character data:
u'contents of CDATA section'
End of CDATA section
End element:
u'sub2'
External entity ref: (None, u'entity.file', None)
End element:
u'root'
PI:
u'xml-stylesheet' u'href="stylesheet.css"'
Comment:
u' comment data '
Notation declared: (u'notation', None, u'notation.jpeg', None)
Unparsed entity decl:
(u'unparsed_entity', None, u'entity.file', None, u'notation')
Start element:
u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
NS decl:
u'myns' u'http://www.python.org/namespace'
Start element:
u'http://www.python.org/namespace!subelement' {}
Character data:
u'Contents of subelements'
End element:
u'http://www.python.org/namespace!subelement'
End of NS decl:
u'myns'
Start element:
u'sub2' {}
Start of CDATA section
Character data:
u'contents of CDATA section'
End of CDATA section
End element:
u'sub2'
External entity ref: (None, u'entity.file', None)
End element:
u'root'
Testing constructor for proper handling of namespace_separator values:
Legal values tested o.k.
Caught expected TypeError:
ParserCreate() argument 2 must be string or None, not int
Caught expected ValueError:
namespace_separator must be at most one character, omitted, or None
xmltests
Passed testAAA
Passed setAttribute() sets ownerDocument
Passed setAttribute() sets ownerElement
Test Succeeded testAAA
Passed assertion: len(Node.allnodes) == 0
Passed testAAB
Test Succeeded testAAB
Passed assertion: len(Node.allnodes) == 0
Passed Test
Passed Test
Passed Test
Passed Test
Passed Test
Passed Test
Passed Test
Passed Test
Test Succeeded testAddAttr
Passed assertion: len(Node.allnodes) == 0
Passed Test
Passed Test
Test Succeeded testAppendChild
Passed assertion: len(Node.allnodes) == 0
Passed appendChild(<fragment>)
Test Succeeded testAppendChildFragment
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testAttrListItem
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testAttrListItemNS
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testAttrListItems
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testAttrListKeys
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testAttrListKeysNS
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testAttrListLength
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testAttrListValues
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testAttrList__getitem__
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testAttrList__setitem__
Passed assertion: len(Node.allnodes) == 0
Passed Test
Passed Test
Test Succeeded testAttributeRepr
Passed assertion: len(Node.allnodes) == 0
Passed Test
Passed Test
Passed Test
Passed Test
Passed Test
Test Succeeded testChangeAttr
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testChildNodes
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testCloneAttributeDeep
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testCloneAttributeShallow
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testCloneDocumentDeep
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testCloneDocumentShallow
Passed assertion: len(Node.allnodes) == 0
Passed clone of element has same attribute keys
Passed clone of attribute node has proper attribute values
Passed clone of attribute node correctly owned
Passed testCloneElementDeep
Test Succeeded testCloneElementDeep
Passed assertion: len(Node.allnodes) == 0
Passed clone of element has same attribute keys
Passed clone of attribute node has proper attribute values
Passed clone of attribute node correctly owned
Passed testCloneElementShallow
Test Succeeded testCloneElementShallow
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testClonePIDeep
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testClonePIShallow
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testComment
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testCreateAttributeNS
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testCreateElementNS
Passed assertion: len(Node.allnodes) == 0
Passed Test
Passed Test
Passed Test
Test Succeeded testDeleteAttr
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testDocumentElement
Passed assertion: len(Node.allnodes) == 0
Passed Test
Test Succeeded testElement
Passed assertion: len(Node.allnodes) == 0
Passed Test
Test Succeeded testElementReprAndStr
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testFirstChild
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testGetAttrLength
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testGetAttrList
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testGetAttrValues
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testGetAttribute
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testGetAttributeNS
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testGetAttributeNode
Passed assertion: len(Node.allnodes) == 0
Passed Test
Test Succeeded testGetElementsByTagName
Passed assertion: len(Node.allnodes) == 0
Passed Test
Test Succeeded testGetElementsByTagNameNS
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testGetEmptyNodeListFromElementsByTagNameNS
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testHasChildNodes
Passed assertion: len(Node.allnodes) == 0
Passed testInsertBefore -- node properly placed in tree
Passed testInsertBefore -- node properly placed in tree
Passed testInsertBefore -- node properly placed in tree
Test Succeeded testInsertBefore
Passed assertion: len(Node.allnodes) == 0
Passed insertBefore(<fragment>, None)
Passed insertBefore(<fragment>, orig)
Test Succeeded testInsertBeforeFragment
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testLegalChildren
Passed assertion: len(Node.allnodes) == 0
Passed NamedNodeMap.__setitem__() sets ownerDocument
Passed NamedNodeMap.__setitem__() sets ownerElement
Passed NamedNodeMap.__setitem__() sets value
Passed NamedNodeMap.__setitem__() sets nodeValue
Test Succeeded testNamedNodeMapSetItem
Passed assertion: len(Node.allnodes) == 0
Passed test NodeList.item()
Test Succeeded testNodeListItem
Passed assertion: len(Node.allnodes) == 0
Passed Test
Passed Test
Test Succeeded testNonZero
Passed assertion: len(Node.allnodes) == 0
Passed testNormalize -- preparation
Passed testNormalize -- result
Passed testNormalize -- single empty node removed
Test Succeeded testNormalize
Passed assertion: len(Node.allnodes) == 0
Passed testParents
Test Succeeded testParents
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testParse
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testParseAttributeNamespaces
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testParseAttributes
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testParseElement
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testParseElementNamespaces
Passed assertion: len(Node.allnodes) == 0
Passed Test
Test Succeeded testParseFromFile
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testParseProcessingInstructions
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testParseString
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testProcessingInstruction
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testProcessingInstructionRepr
Passed assertion: len(Node.allnodes) == 0
Passed Test
Passed Test
Test Succeeded testRemoveAttr
Passed assertion: len(Node.allnodes) == 0
Passed Test
Passed Test
Test Succeeded testRemoveAttrNS
Passed assertion: len(Node.allnodes) == 0
Passed Test
Passed Test
Test Succeeded testRemoveAttributeNode
Passed assertion: len(Node.allnodes) == 0
Passed replaceChild(<fragment>)
Test Succeeded testReplaceChildFragment
Passed assertion: len(Node.allnodes) == 0
Passed testSAX2DOM - siblings
Passed testSAX2DOM - parents
Test Succeeded testSAX2DOM
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testSetAttrValueandNodeValue
Passed assertion: len(Node.allnodes) == 0
Passed testSiblings
Test Succeeded testSiblings
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testTextNodeRepr
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testTextRepr
Passed assertion: len(Node.allnodes) == 0
Caught expected exception when adding extra document element.
Test Succeeded testTooManyDocumentElements
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testUnlink
Passed assertion: len(Node.allnodes) == 0
Test Succeeded testWriteText
Passed assertion: len(Node.allnodes) == 0
Passed Test
Passed Test
Test Succeeded testWriteXML
Passed assertion: len(Node.allnodes) == 0
All tests succeeded
OK.
OK.
OK.
OK.
OK.
OK.
OK.
OK.
OK.
OK.
OK.
OK.
PI:
'xml-stylesheet' 'href="stylesheet.css"'
Comment:
' comment data '
Notation declared: ('notation', None, 'notation.jpeg', None)
Unparsed entity decl:
('unparsed_entity', None, 'entity.file', None, 'notation')
Start element:
'root' {'attr1': 'value1', 'attr2': 'value2\xe1\xbd\x80'}
NS decl:
'myns' 'http://www.python.org/namespace'
Start element:
'http://www.python.org/namespace!subelement' {}
Character data:
'Contents of subelements'
End element:
'http://www.python.org/namespace!subelement'
End of NS decl:
'myns'
Start element:
'sub2' {}
Start of CDATA section
Character data:
'contents of CDATA section'
End of CDATA section
End element:
'sub2'
External entity ref: (None, 'entity.file', None)
End element:
'root'
PI:
u'xml-stylesheet' u'href="stylesheet.css"'
Comment:
u' comment data '
Notation declared: (u'notation', None, u'notation.jpeg', None)
Unparsed entity decl:
(u'unparsed_entity', None, u'entity.file', None, u'notation')
Start element:
u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
NS decl:
u'myns' u'http://www.python.org/namespace'
Start element:
u'http://www.python.org/namespace!subelement' {}
Character data:
u'Contents of subelements'
End element:
u'http://www.python.org/namespace!subelement'
End of NS decl:
u'myns'
Start element:
u'sub2' {}
Start of CDATA section
Character data:
u'contents of CDATA section'
End of CDATA section
End element:
u'sub2'
External entity ref: (None, u'entity.file', None)
End element:
u'root'
PI:
u'xml-stylesheet' u'href="stylesheet.css"'
Comment:
u' comment data '
Notation declared: (u'notation', None, u'notation.jpeg', None)
Unparsed entity decl:
(u'unparsed_entity', None, u'entity.file', None, u'notation')
Start element:
u'root' {u'attr1': u'value1', u'attr2': u'value2\u1f40'}
NS decl:
u'myns' u'http://www.python.org/namespace'
Start element:
u'http://www.python.org/namespace!subelement' {}
Character data:
u'Contents of subelements'
End element:
u'http://www.python.org/namespace!subelement'
End of NS decl:
u'myns'
Start element:
u'sub2' {}
Start of CDATA section
Character data:
u'contents of CDATA section'
End of CDATA section
End element:
u'sub2'
External entity ref: (None, u'entity.file', None)
End element:
u'root'
Testing constructor for proper handling of namespace_separator values:
Legal values tested o.k.
Caught expected TypeError:
ParserCreate() argument 2 must be string or None, not int
Caught expected ValueError:
namespace_separator must be at most one character, omitted, or None
Passed test_attrs_empty
Passed test_attrs_wattr
Passed test_double_quoteattr
Passed test_escape_all
Passed test_escape_basic
Passed test_escape_extra
Passed test_expat_attrs_empty
Passed test_expat_attrs_wattr
Passed test_expat_dtdhandler
Passed test_expat_entityresolver
Passed test_expat_file
Passed test_expat_incomplete
Passed test_expat_incremental
Passed test_expat_incremental_reset
Passed test_expat_inpsource_filename
Passed test_expat_inpsource_location
Passed test_expat_inpsource_stream
Passed test_expat_inpsource_sysid
Passed test_expat_locator_noinfo
Passed test_expat_locator_withinfo
Passed test_expat_nsattrs_empty
Passed test_expat_nsattrs_wattr
Passed test_filter_basic
Passed test_make_parser
Passed test_make_parser2
Passed test_nsattrs_empty
Passed test_nsattrs_wattr
Passed test_quoteattr_basic
Passed test_single_double_quoteattr
Passed test_single_quoteattr
Passed test_xmlgen_attr_escape
Passed test_xmlgen_basic
Passed test_xmlgen_content
Passed test_xmlgen_content_escape
Passed test_xmlgen_ignorable
Passed test_xmlgen_ns
Passed test_xmlgen_pi
37 tests, 0 failures
...@@ -5,7 +5,8 @@ import sys ...@@ -5,7 +5,8 @@ import sys
import pickle import pickle
import traceback import traceback
from StringIO import StringIO from StringIO import StringIO
from test.test_support import verbose from test.test_support import verbose, run_unittest, TestSkipped
import unittest
import xml.dom import xml.dom
import xml.dom.minidom import xml.dom.minidom
...@@ -22,29 +23,81 @@ else: ...@@ -22,29 +23,81 @@ else:
tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml") tstfile = os.path.join(os.path.dirname(base), "test"+os.extsep+"xml")
del base del base
def confirm(test, testname = "Test"): # The tests of DocumentType importing use these helpers to construct
if not test: # the documents to work with, since not all DOM builders actually
print "Failed " + testname # create the DocumentType nodes.
raise Exception def create_doc_without_doctype(doctype=None):
return getDOMImplementation().createDocument(None, "doc", doctype)
def create_nonempty_doctype():
doctype = getDOMImplementation().createDocumentType("doc", None, None)
doctype.entities._seq = []
doctype.notations._seq = []
notation = xml.dom.minidom.Notation("my-notation", None,
"http://xml.python.org/notations/my")
doctype.notations._seq.append(notation)
entity = xml.dom.minidom.Entity("my-entity", None,
"http://xml.python.org/entities/my",
"my-notation")
entity.version = "1.0"
entity.encoding = "utf-8"
entity.actualEncoding = "us-ascii"
doctype.entities._seq.append(entity)
return doctype
def testParseFromFile(): def create_doc_with_doctype():
doctype = create_nonempty_doctype()
doc = create_doc_without_doctype(doctype)
doctype.entities.item(0).ownerDocument = doc
doctype.notations.item(0).ownerDocument = doc
return doc
class MinidomTest(unittest.TestCase):
def tearDown(self):
try:
Node.allnodes
except AttributeError:
# We don't actually have the minidom from the standard library,
# but are picking up the PyXML version from site-packages.
pass
else:
self.confirm(len(Node.allnodes) == 0,
"assertion: len(Node.allnodes) == 0")
if len(Node.allnodes):
print "Garbage left over:"
if verbose:
print Node.allnodes.items()[0:10]
else:
# Don't print specific nodes if repeatable results
# are needed
print len(Node.allnodes)
Node.allnodes = {}
def confirm(self, test, testname = "Test"):
self.assertTrue(test, testname)
def checkWholeText(self, node, s):
t = node.wholeText
self.confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
def testParseFromFile(self):
dom = parse(StringIO(open(tstfile).read())) dom = parse(StringIO(open(tstfile).read()))
dom.unlink() dom.unlink()
confirm(isinstance(dom,Document)) self.confirm(isinstance(dom,Document))
def testGetElementsByTagName(): def testGetElementsByTagName(self):
dom = parse(tstfile) dom = parse(tstfile)
confirm(dom.getElementsByTagName("LI") == \ self.confirm(dom.getElementsByTagName("LI") == \
dom.documentElement.getElementsByTagName("LI")) dom.documentElement.getElementsByTagName("LI"))
dom.unlink() dom.unlink()
def testInsertBefore(): def testInsertBefore(self):
dom = parseString("<doc><foo/></doc>") dom = parseString("<doc><foo/></doc>")
root = dom.documentElement root = dom.documentElement
elem = root.childNodes[0] elem = root.childNodes[0]
nelem = dom.createElement("element") nelem = dom.createElement("element")
root.insertBefore(nelem, elem) root.insertBefore(nelem, elem)
confirm(len(root.childNodes) == 2 self.confirm(len(root.childNodes) == 2
and root.childNodes.length == 2 and root.childNodes.length == 2
and root.childNodes[0] is nelem and root.childNodes[0] is nelem
and root.childNodes.item(0) is nelem and root.childNodes.item(0) is nelem
...@@ -56,7 +109,7 @@ def testInsertBefore(): ...@@ -56,7 +109,7 @@ def testInsertBefore():
, "testInsertBefore -- node properly placed in tree") , "testInsertBefore -- node properly placed in tree")
nelem = dom.createElement("element") nelem = dom.createElement("element")
root.insertBefore(nelem, None) root.insertBefore(nelem, None)
confirm(len(root.childNodes) == 3 self.confirm(len(root.childNodes) == 3
and root.childNodes.length == 3 and root.childNodes.length == 3
and root.childNodes[1] is elem and root.childNodes[1] is elem
and root.childNodes.item(1) is elem and root.childNodes.item(1) is elem
...@@ -68,7 +121,7 @@ def testInsertBefore(): ...@@ -68,7 +121,7 @@ def testInsertBefore():
, "testInsertBefore -- node properly placed in tree") , "testInsertBefore -- node properly placed in tree")
nelem2 = dom.createElement("bar") nelem2 = dom.createElement("bar")
root.insertBefore(nelem2, nelem) root.insertBefore(nelem2, nelem)
confirm(len(root.childNodes) == 4 self.confirm(len(root.childNodes) == 4
and root.childNodes.length == 4 and root.childNodes.length == 4
and root.childNodes[2] is nelem2 and root.childNodes[2] is nelem2
and root.childNodes.item(2) is nelem2 and root.childNodes.item(2) is nelem2
...@@ -76,11 +129,12 @@ def testInsertBefore(): ...@@ -76,11 +129,12 @@ def testInsertBefore():
and root.childNodes.item(3) is nelem and root.childNodes.item(3) is nelem
and nelem2.nextSibling is nelem and nelem2.nextSibling is nelem
and nelem.previousSibling is nelem2 and nelem.previousSibling is nelem2
and root.toxml() == "<doc><element/><foo/><bar/><element/></doc>" and root.toxml() ==
"<doc><element/><foo/><bar/><element/></doc>"
, "testInsertBefore -- node properly placed in tree") , "testInsertBefore -- node properly placed in tree")
dom.unlink() dom.unlink()
def _create_fragment_test_nodes(): def _create_fragment_test_nodes(self):
dom = parseString("<doc/>") dom = parseString("<doc/>")
orig = dom.createTextNode("original") orig = dom.createTextNode("original")
c1 = dom.createTextNode("foo") c1 = dom.createTextNode("foo")
...@@ -93,224 +147,210 @@ def _create_fragment_test_nodes(): ...@@ -93,224 +147,210 @@ def _create_fragment_test_nodes():
frag.appendChild(c3) frag.appendChild(c3)
return dom, orig, c1, c2, c3, frag return dom, orig, c1, c2, c3, frag
def testInsertBeforeFragment(): def testInsertBeforeFragment(self):
dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
dom.documentElement.insertBefore(frag, None) dom.documentElement.insertBefore(frag, None)
confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3), self.confirm(tuple(dom.documentElement.childNodes) ==
(orig, c1, c2, c3),
"insertBefore(<fragment>, None)") "insertBefore(<fragment>, None)")
frag.unlink() frag.unlink()
dom.unlink() dom.unlink()
#
dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
dom.documentElement.insertBefore(frag, orig) dom.documentElement.insertBefore(frag, orig)
confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3, orig), self.confirm(tuple(dom.documentElement.childNodes) ==
(c1, c2, c3, orig),
"insertBefore(<fragment>, orig)") "insertBefore(<fragment>, orig)")
frag.unlink() frag.unlink()
dom.unlink() dom.unlink()
def testAppendChild(): def testAppendChild(self):
dom = parse(tstfile) dom = parse(tstfile)
dom.documentElement.appendChild(dom.createComment(u"Hello")) dom.documentElement.appendChild(dom.createComment(u"Hello"))
confirm(dom.documentElement.childNodes[-1].nodeName == "#comment") self.confirm(dom.documentElement.childNodes[-1].nodeName == "#comment")
confirm(dom.documentElement.childNodes[-1].data == "Hello") self.confirm(dom.documentElement.childNodes[-1].data == "Hello")
dom.unlink() dom.unlink()
def testAppendChildFragment(): def testAppendChildFragment(self):
dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
dom.documentElement.appendChild(frag) dom.documentElement.appendChild(frag)
confirm(tuple(dom.documentElement.childNodes) == (orig, c1, c2, c3), self.confirm(tuple(dom.documentElement.childNodes) ==
(orig, c1, c2, c3),
"appendChild(<fragment>)") "appendChild(<fragment>)")
frag.unlink() frag.unlink()
dom.unlink() dom.unlink()
def testReplaceChildFragment(): def testReplaceChildFragment(self):
dom, orig, c1, c2, c3, frag = _create_fragment_test_nodes() dom, orig, c1, c2, c3, frag = self._create_fragment_test_nodes()
dom.documentElement.replaceChild(frag, orig) dom.documentElement.replaceChild(frag, orig)
orig.unlink() orig.unlink()
confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3), self.confirm(tuple(dom.documentElement.childNodes) == (c1, c2, c3),
"replaceChild(<fragment>)") "replaceChild(<fragment>)")
frag.unlink() frag.unlink()
dom.unlink() dom.unlink()
def testLegalChildren(): def testLegalChildren(self):
dom = Document() dom = Document()
elem = dom.createElement('element') elem = dom.createElement('element')
text = dom.createTextNode('text') text = dom.createTextNode('text')
self.assertRaises(xml.dom.HierarchyRequestErr, dom.appendChild, text)
try: dom.appendChild(text)
except xml.dom.HierarchyRequestErr: pass
else:
print "dom.appendChild didn't raise HierarchyRequestErr"
dom.appendChild(elem) dom.appendChild(elem)
try: dom.insertBefore(text, elem) self.assertRaises(xml.dom.HierarchyRequestErr, dom.insertBefore, text,
except xml.dom.HierarchyRequestErr: pass elem)
else: self.assertRaises(xml.dom.HierarchyRequestErr, dom.replaceChild, text,
print "dom.appendChild didn't raise HierarchyRequestErr" elem)
try: dom.replaceChild(text, elem)
except xml.dom.HierarchyRequestErr: pass
else:
print "dom.appendChild didn't raise HierarchyRequestErr"
nodemap = elem.attributes nodemap = elem.attributes
try: nodemap.setNamedItem(text) self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItem,
except xml.dom.HierarchyRequestErr: pass text)
else: self.assertRaises(xml.dom.HierarchyRequestErr, nodemap.setNamedItemNS,
print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr" text)
try: nodemap.setNamedItemNS(text)
except xml.dom.HierarchyRequestErr: pass
else:
print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr"
elem.appendChild(text) elem.appendChild(text)
dom.unlink() dom.unlink()
def testNamedNodeMapSetItem(): def testNamedNodeMapSetItem(self):
dom = Document() dom = Document()
elem = dom.createElement('element') elem = dom.createElement('element')
attrs = elem.attributes attrs = elem.attributes
attrs["foo"] = "bar" attrs["foo"] = "bar"
a = attrs.item(0) a = attrs.item(0)
confirm(a.ownerDocument is dom, self.confirm(a.ownerDocument is dom,
"NamedNodeMap.__setitem__() sets ownerDocument") "NamedNodeMap.__setitem__() sets ownerDocument")
confirm(a.ownerElement is elem, self.confirm(a.ownerElement is elem,
"NamedNodeMap.__setitem__() sets ownerElement") "NamedNodeMap.__setitem__() sets ownerElement")
confirm(a.value == "bar", self.confirm(a.value == "bar",
"NamedNodeMap.__setitem__() sets value") "NamedNodeMap.__setitem__() sets value")
confirm(a.nodeValue == "bar", self.confirm(a.nodeValue == "bar",
"NamedNodeMap.__setitem__() sets nodeValue") "NamedNodeMap.__setitem__() sets nodeValue")
elem.unlink() elem.unlink()
dom.unlink() dom.unlink()
def testNonZero(): def testNonZero(self):
dom = parse(tstfile) dom = parse(tstfile)
confirm(dom)# should not be zero self.confirm(dom)# should not be zero
dom.appendChild(dom.createComment("foo")) dom.appendChild(dom.createComment("foo"))
confirm(not dom.childNodes[-1].childNodes) self.confirm(not dom.childNodes[-1].childNodes)
dom.unlink() dom.unlink()
def testUnlink(): def testUnlink(self):
dom = parse(tstfile) dom = parse(tstfile)
dom.unlink() dom.unlink()
def testElement(): def testElement(self):
dom = Document() dom = Document()
dom.appendChild(dom.createElement("abc")) dom.appendChild(dom.createElement("abc"))
confirm(dom.documentElement) self.confirm(dom.documentElement)
dom.unlink() dom.unlink()
def testAAA(): def testAAA(self):
dom = parseString("<abc/>") dom = parseString("<abc/>")
el = dom.documentElement el = dom.documentElement
el.setAttribute("spam", "jam2") el.setAttribute("spam", "jam2")
confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA") self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAA")
a = el.getAttributeNode("spam") a = el.getAttributeNode("spam")
confirm(a.ownerDocument is dom, self.confirm(a.ownerDocument is dom,
"setAttribute() sets ownerDocument") "setAttribute() sets ownerDocument")
confirm(a.ownerElement is dom.documentElement, self.confirm(a.ownerElement is dom.documentElement,
"setAttribute() sets ownerElement") "setAttribute() sets ownerElement")
dom.unlink() dom.unlink()
def testAAB(): def testAAB(self):
dom = parseString("<abc/>") dom = parseString("<abc/>")
el = dom.documentElement el = dom.documentElement
el.setAttribute("spam", "jam") el.setAttribute("spam", "jam")
el.setAttribute("spam", "jam2") el.setAttribute("spam", "jam2")
confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB") self.confirm(el.toxml() == '<abc spam="jam2"/>', "testAAB")
dom.unlink() dom.unlink()
def testAddAttr(): def testAddAttr(self):
dom = Document() dom = Document()
child = dom.appendChild(dom.createElement("abc")) child = dom.appendChild(dom.createElement("abc"))
child.setAttribute("def", "ghi") child.setAttribute("def", "ghi")
confirm(child.getAttribute("def") == "ghi") self.confirm(child.getAttribute("def") == "ghi")
confirm(child.attributes["def"].value == "ghi") self.confirm(child.attributes["def"].value == "ghi")
child.setAttribute("jkl", "mno") child.setAttribute("jkl", "mno")
confirm(child.getAttribute("jkl") == "mno") self.confirm(child.getAttribute("jkl") == "mno")
confirm(child.attributes["jkl"].value == "mno") self.confirm(child.attributes["jkl"].value == "mno")
confirm(len(child.attributes) == 2) self.confirm(len(child.attributes) == 2)
child.setAttribute("def", "newval") child.setAttribute("def", "newval")
confirm(child.getAttribute("def") == "newval") self.confirm(child.getAttribute("def") == "newval")
confirm(child.attributes["def"].value == "newval") self.confirm(child.attributes["def"].value == "newval")
confirm(len(child.attributes) == 2) self.confirm(len(child.attributes) == 2)
dom.unlink() dom.unlink()
def testDeleteAttr(): def testDeleteAttr(self):
dom = Document() dom = Document()
child = dom.appendChild(dom.createElement("abc")) child = dom.appendChild(dom.createElement("abc"))
confirm(len(child.attributes) == 0) self.confirm(len(child.attributes) == 0)
child.setAttribute("def", "ghi") child.setAttribute("def", "ghi")
confirm(len(child.attributes) == 1) self.confirm(len(child.attributes) == 1)
del child.attributes["def"] del child.attributes["def"]
confirm(len(child.attributes) == 0) self.confirm(len(child.attributes) == 0)
dom.unlink() dom.unlink()
def testRemoveAttr(): def testRemoveAttr(self):
dom = Document() dom = Document()
child = dom.appendChild(dom.createElement("abc")) child = dom.appendChild(dom.createElement("abc"))
child.setAttribute("def", "ghi") child.setAttribute("def", "ghi")
confirm(len(child.attributes) == 1) self.confirm(len(child.attributes) == 1)
child.removeAttribute("def") child.removeAttribute("def")
confirm(len(child.attributes) == 0) self.confirm(len(child.attributes) == 0)
dom.unlink() dom.unlink()
def testRemoveAttrNS(): def testRemoveAttrNS(self):
dom = Document() dom = Document()
child = dom.appendChild( child = dom.appendChild(
dom.createElementNS("http://www.python.org", "python:abc")) dom.createElementNS("http://www.python.org", "python:abc"))
child.setAttributeNS("http://www.w3.org", "xmlns:python", child.setAttributeNS("http://www.w3.org", "xmlns:python",
"http://www.python.org") "http://www.python.org")
child.setAttributeNS("http://www.python.org", "python:abcattr", "foo") child.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
confirm(len(child.attributes) == 2) self.confirm(len(child.attributes) == 2)
child.removeAttributeNS("http://www.python.org", "abcattr") child.removeAttributeNS("http://www.python.org", "abcattr")
confirm(len(child.attributes) == 1) self.confirm(len(child.attributes) == 1)
dom.unlink() dom.unlink()
def testRemoveAttributeNode(): def testRemoveAttributeNode(self):
dom = Document() dom = Document()
child = dom.appendChild(dom.createElement("foo")) child = dom.appendChild(dom.createElement("foo"))
child.setAttribute("spam", "jam") child.setAttribute("spam", "jam")
confirm(len(child.attributes) == 1) self.confirm(len(child.attributes) == 1)
node = child.getAttributeNode("spam") node = child.getAttributeNode("spam")
child.removeAttributeNode(node) child.removeAttributeNode(node)
confirm(len(child.attributes) == 0 self.confirm(len(child.attributes) == 0
and child.getAttributeNode("spam") is None) and child.getAttributeNode("spam") is None)
dom.unlink() dom.unlink()
def testChangeAttr(): def testChangeAttr(self):
dom = parseString("<abc/>") dom = parseString("<abc/>")
el = dom.documentElement el = dom.documentElement
el.setAttribute("spam", "jam") el.setAttribute("spam", "jam")
confirm(len(el.attributes) == 1) self.confirm(len(el.attributes) == 1)
el.setAttribute("spam", "bam") el.setAttribute("spam", "bam")
# Set this attribute to be an ID and make sure that doesn't change # Set this attribute to be an ID and make sure that doesn't change
# when changing the value: # when changing the value:
el.setIdAttribute("spam") el.setIdAttribute("spam")
confirm(len(el.attributes) == 1 self.confirm(len(el.attributes) == 1
and el.attributes["spam"].value == "bam" and el.attributes["spam"].value == "bam"
and el.attributes["spam"].nodeValue == "bam" and el.attributes["spam"].nodeValue == "bam"
and el.getAttribute("spam") == "bam" and el.getAttribute("spam") == "bam"
and el.getAttributeNode("spam").isId) and el.getAttributeNode("spam").isId)
el.attributes["spam"] = "ham" el.attributes["spam"] = "ham"
confirm(len(el.attributes) == 1 self.confirm(len(el.attributes) == 1
and el.attributes["spam"].value == "ham" and el.attributes["spam"].value == "ham"
and el.attributes["spam"].nodeValue == "ham" and el.attributes["spam"].nodeValue == "ham"
and el.getAttribute("spam") == "ham" and el.getAttribute("spam") == "ham"
and el.attributes["spam"].isId) and el.attributes["spam"].isId)
el.setAttribute("spam2", "bam") el.setAttribute("spam2", "bam")
confirm(len(el.attributes) == 2 self.confirm(len(el.attributes) == 2
and el.attributes["spam"].value == "ham" and el.attributes["spam"].value == "ham"
and el.attributes["spam"].nodeValue == "ham" and el.attributes["spam"].nodeValue == "ham"
and el.getAttribute("spam") == "ham" and el.getAttribute("spam") == "ham"
...@@ -318,7 +358,7 @@ def testChangeAttr(): ...@@ -318,7 +358,7 @@ def testChangeAttr():
and el.attributes["spam2"].nodeValue == "bam" and el.attributes["spam2"].nodeValue == "bam"
and el.getAttribute("spam2") == "bam") and el.getAttribute("spam2") == "bam")
el.attributes["spam2"] = "bam2" el.attributes["spam2"] = "bam2"
confirm(len(el.attributes) == 2 self.confirm(len(el.attributes) == 2
and el.attributes["spam"].value == "ham" and el.attributes["spam"].value == "ham"
and el.attributes["spam"].nodeValue == "ham" and el.attributes["spam"].nodeValue == "ham"
and el.getAttribute("spam") == "ham" and el.getAttribute("spam") == "ham"
...@@ -327,26 +367,27 @@ def testChangeAttr(): ...@@ -327,26 +367,27 @@ def testChangeAttr():
and el.getAttribute("spam2") == "bam2") and el.getAttribute("spam2") == "bam2")
dom.unlink() dom.unlink()
def testGetAttrList(): def testGetAttrList(self):
pass pass
def testGetAttrValues(): pass def testGetAttrValues(self): pass
def testGetAttrLength(): pass def testGetAttrLength(self): pass
def testGetAttribute(): pass def testGetAttribute(self): pass
def testGetAttributeNS(): pass def testGetAttributeNS(self): pass
def testGetAttributeNode(): pass def testGetAttributeNode(self): pass
def testGetElementsByTagNameNS(): def testGetElementsByTagNameNS(self):
d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'> d="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
<minidom:myelem/> <minidom:myelem/>
</foo>""" </foo>"""
dom = parseString(d) dom = parseString(d)
elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom", "myelem") elems = dom.getElementsByTagNameNS("http://pyxml.sf.net/minidom",
confirm(len(elems) == 1 "myelem")
self.confirm(len(elems) == 1
and elems[0].namespaceURI == "http://pyxml.sf.net/minidom" and elems[0].namespaceURI == "http://pyxml.sf.net/minidom"
and elems[0].localName == "myelem" and elems[0].localName == "myelem"
and elems[0].prefix == "minidom" and elems[0].prefix == "minidom"
...@@ -354,82 +395,81 @@ def testGetElementsByTagNameNS(): ...@@ -354,82 +395,81 @@ def testGetElementsByTagNameNS():
and elems[0].nodeName == "minidom:myelem") and elems[0].nodeName == "minidom:myelem")
dom.unlink() dom.unlink()
def get_empty_nodelist_from_elements_by_tagName_ns_helper(doc, nsuri, lname): def get_empty_nodelist_from_elements_by_tagName_ns_helper(self, doc, nsuri,
lname):
nodelist = doc.getElementsByTagNameNS(nsuri, lname) nodelist = doc.getElementsByTagNameNS(nsuri, lname)
confirm(len(nodelist) == 0) self.confirm(len(nodelist) == 0)
def testGetEmptyNodeListFromElementsByTagNameNS(): def testGetEmptyNodeListFromElementsByTagNameNS(self):
doc = parseString('<doc/>') doc = parseString('<doc/>')
get_empty_nodelist_from_elements_by_tagName_ns_helper( self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
doc, 'http://xml.python.org/namespaces/a', 'localname') doc, 'http://xml.python.org/namespaces/a', 'localname')
get_empty_nodelist_from_elements_by_tagName_ns_helper( self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
doc, '*', 'splat') doc, '*', 'splat')
get_empty_nodelist_from_elements_by_tagName_ns_helper( self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
doc, 'http://xml.python.org/namespaces/a', '*') doc, 'http://xml.python.org/namespaces/a', '*')
doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>') doc = parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
get_empty_nodelist_from_elements_by_tagName_ns_helper( self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
doc, "http://xml.python.org/splat", "not-there") doc, "http://xml.python.org/splat", "not-there")
get_empty_nodelist_from_elements_by_tagName_ns_helper( self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
doc, "*", "not-there") doc, "*", "not-there")
get_empty_nodelist_from_elements_by_tagName_ns_helper( self.get_empty_nodelist_from_elements_by_tagName_ns_helper(
doc, "http://somewhere.else.net/not-there", "e") doc, "http://somewhere.else.net/not-there", "e")
def testElementReprAndStr(): def testElementReprAndStr(self):
dom = Document() dom = Document()
el = dom.appendChild(dom.createElement("abc")) el = dom.appendChild(dom.createElement("abc"))
string1 = repr(el) string1 = repr(el)
string2 = str(el) string2 = str(el)
confirm(string1 == string2) self.confirm(string1 == string2)
dom.unlink() dom.unlink()
# commented out until Fredrick's fix is checked in def testElementReprAndStrUnicode(self):
def _testElementReprAndStrUnicode():
dom = Document() dom = Document()
el = dom.appendChild(dom.createElement(u"abc")) el = dom.appendChild(dom.createElement(u"abc"))
string1 = repr(el) string1 = repr(el)
string2 = str(el) string2 = str(el)
confirm(string1 == string2) self.confirm(string1 == string2)
dom.unlink() dom.unlink()
# commented out until Fredrick's fix is checked in def testElementReprAndStrUnicodeNS(self):
def _testElementReprAndStrUnicodeNS():
dom = Document() dom = Document()
el = dom.appendChild( el = dom.appendChild(
dom.createElementNS(u"http://www.slashdot.org", u"slash:abc")) dom.createElementNS(u"http://www.slashdot.org", u"slash:abc"))
string1 = repr(el) string1 = repr(el)
string2 = str(el) string2 = str(el)
confirm(string1 == string2) self.confirm(string1 == string2)
confirm(string1.find("slash:abc") != -1) self.confirm(string1.find("slash:abc") != -1)
dom.unlink() dom.unlink()
def testAttributeRepr(): def testAttributeRepr(self):
dom = Document() dom = Document()
el = dom.appendChild(dom.createElement(u"abc")) el = dom.appendChild(dom.createElement(u"abc"))
node = el.setAttribute("abc", "def") node = el.setAttribute("abc", "def")
confirm(str(node) == repr(node)) self.confirm(str(node) == repr(node))
dom.unlink() dom.unlink()
def testTextNodeRepr(): pass def testTextNodeRepr(self): pass
def testWriteXML(): def testWriteXML(self):
str = '<?xml version="1.0" ?><a b="c"/>' str = '<?xml version="1.0" ?><a b="c"/>'
dom = parseString(str) dom = parseString(str)
domstr = dom.toxml() domstr = dom.toxml()
dom.unlink() dom.unlink()
confirm(str == domstr) self.confirm(str == domstr)
def testAltNewline(): def testAltNewline(self):
str = '<?xml version="1.0" ?>\n<a b="c"/>\n' str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
dom = parseString(str) dom = parseString(str)
domstr = dom.toprettyxml(newl="\r\n") domstr = dom.toprettyxml(newl="\r\n")
dom.unlink() dom.unlink()
confirm(domstr == str.replace("\n", "\r\n")) self.confirm(domstr == str.replace("\n", "\r\n"))
def testProcessingInstruction(): def testProcessingInstruction(self):
dom = parseString('<e><?mypi \t\n data \t\n ?></e>') dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
pi = dom.documentElement.firstChild pi = dom.documentElement.firstChild
confirm(pi.target == "mypi" self.confirm(pi.target == "mypi"
and pi.data == "data \t\n " and pi.data == "data \t\n "
and pi.nodeName == "mypi" and pi.nodeName == "mypi"
and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE and pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE
...@@ -441,148 +481,138 @@ def testProcessingInstruction(): ...@@ -441,148 +481,138 @@ def testProcessingInstruction():
and pi.localName is None and pi.localName is None
and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE) and pi.namespaceURI == xml.dom.EMPTY_NAMESPACE)
def testProcessingInstructionRepr(): pass def testProcessingInstructionRepr(self): pass
def testTextRepr(): pass def testTextRepr(self): pass
def testWriteText(): pass def testWriteText(self): pass
def testDocumentElement(): pass def testDocumentElement(self): pass
def testTooManyDocumentElements(): def testTooManyDocumentElements(self):
doc = parseString("<doc/>") doc = parseString("<doc/>")
elem = doc.createElement("extra") elem = doc.createElement("extra")
try: # Should raise an exception when adding an extra document element.
doc.appendChild(elem) self.assertRaises(xml.dom.HierarchyRequestErr, doc.appendChild, elem)
except xml.dom.HierarchyRequestErr:
pass
else:
print "Failed to catch expected exception when" \
" adding extra document element."
elem.unlink() elem.unlink()
doc.unlink() doc.unlink()
def testCreateElementNS(): pass def testCreateElementNS(self): pass
def testCreateAttributeNS(): pass def testCreateAttributeNS(self): pass
def testParse(): pass def testParse(self): pass
def testParseString(): pass def testParseString(self): pass
def testComment(): pass def testComment(self): pass
def testAttrListItem(): pass def testAttrListItem(self): pass
def testAttrListItems(): pass def testAttrListItems(self): pass
def testAttrListItemNS(): pass def testAttrListItemNS(self): pass
def testAttrListKeys(): pass def testAttrListKeys(self): pass
def testAttrListKeysNS(): pass def testAttrListKeysNS(self): pass
def testRemoveNamedItem(): def testRemoveNamedItem(self):
doc = parseString("<doc a=''/>") doc = parseString("<doc a=''/>")
e = doc.documentElement e = doc.documentElement
attrs = e.attributes attrs = e.attributes
a1 = e.getAttributeNode("a") a1 = e.getAttributeNode("a")
a2 = attrs.removeNamedItem("a") a2 = attrs.removeNamedItem("a")
confirm(a1.isSameNode(a2)) self.confirm(a1.isSameNode(a2))
try: self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItem, "a")
attrs.removeNamedItem("a")
except xml.dom.NotFoundErr:
pass
def testRemoveNamedItemNS(): def testRemoveNamedItemNS(self):
doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>") doc = parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
e = doc.documentElement e = doc.documentElement
attrs = e.attributes attrs = e.attributes
a1 = e.getAttributeNodeNS("http://xml.python.org/", "b") a1 = e.getAttributeNodeNS("http://xml.python.org/", "b")
a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b") a2 = attrs.removeNamedItemNS("http://xml.python.org/", "b")
confirm(a1.isSameNode(a2)) self.confirm(a1.isSameNode(a2))
try: self.assertRaises(xml.dom.NotFoundErr, attrs.removeNamedItemNS,
attrs.removeNamedItemNS("http://xml.python.org/", "b") "http://xml.python.org/", "b")
except xml.dom.NotFoundErr:
pass
def testAttrListValues(): pass def testAttrListValues(self): pass
def testAttrListLength(): pass def testAttrListLength(self): pass
def testAttrList__getitem__(): pass def testAttrList__getitem__(self): pass
def testAttrList__setitem__(): pass def testAttrList__setitem__(self): pass
def testSetAttrValueandNodeValue(): pass def testSetAttrValueandNodeValue(self): pass
def testParseElement(): pass def testParseElement(self): pass
def testParseAttributes(): pass def testParseAttributes(self): pass
def testParseElementNamespaces(): pass def testParseElementNamespaces(self): pass
def testParseAttributeNamespaces(): pass def testParseAttributeNamespaces(self): pass
def testParseProcessingInstructions(): pass def testParseProcessingInstructions(self): pass
def testChildNodes(): pass def testChildNodes(self): pass
def testFirstChild(): pass def testFirstChild(self): pass
def testHasChildNodes(): pass def testHasChildNodes(self): pass
def testCloneElementShallow(): def _testCloneElementCopiesAttributes(self, e1, e2, test):
dom, clone = _setupCloneElement(0)
confirm(len(clone.childNodes) == 0
and clone.childNodes.length == 0
and clone.parentNode is None
and clone.toxml() == '<doc attr="value"/>'
, "testCloneElementShallow")
dom.unlink()
def testCloneElementDeep():
dom, clone = _setupCloneElement(1)
confirm(len(clone.childNodes) == 1
and clone.childNodes.length == 1
and clone.parentNode is None
and clone.toxml() == '<doc attr="value"><foo/></doc>'
, "testCloneElementDeep")
dom.unlink()
def _setupCloneElement(deep):
dom = parseString("<doc attr='value'><foo/></doc>")
root = dom.documentElement
clone = root.cloneNode(deep)
_testCloneElementCopiesAttributes(
root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
# mutilate the original so shared data is detected
root.tagName = root.nodeName = "MODIFIED"
root.setAttribute("attr", "NEW VALUE")
root.setAttribute("added", "VALUE")
return dom, clone
def _testCloneElementCopiesAttributes(e1, e2, test):
attrs1 = e1.attributes attrs1 = e1.attributes
attrs2 = e2.attributes attrs2 = e2.attributes
keys1 = attrs1.keys() keys1 = attrs1.keys()
keys2 = attrs2.keys() keys2 = attrs2.keys()
keys1.sort() keys1.sort()
keys2.sort() keys2.sort()
confirm(keys1 == keys2, "clone of element has same attribute keys") self.confirm(keys1 == keys2, "clone of element has same attribute keys")
for i in range(len(keys1)): for i in range(len(keys1)):
a1 = attrs1.item(i) a1 = attrs1.item(i)
a2 = attrs2.item(i) a2 = attrs2.item(i)
confirm(a1 is not a2 self.confirm(a1 is not a2
and a1.value == a2.value and a1.value == a2.value
and a1.nodeValue == a2.nodeValue and a1.nodeValue == a2.nodeValue
and a1.namespaceURI == a2.namespaceURI and a1.namespaceURI == a2.namespaceURI
and a1.localName == a2.localName and a1.localName == a2.localName
, "clone of attribute node has proper attribute values") , "clone of attribute node has proper attribute values")
confirm(a2.ownerElement is e2, self.confirm(a2.ownerElement is e2,
"clone of attribute node correctly owned") "clone of attribute node correctly owned")
def testCloneDocumentShallow(): def _setupCloneElement(self, deep):
dom = parseString("<doc attr='value'><foo/></doc>")
root = dom.documentElement
clone = root.cloneNode(deep)
self._testCloneElementCopiesAttributes(
root, clone, "testCloneElement" + (deep and "Deep" or "Shallow"))
# mutilate the original so shared data is detected
root.tagName = root.nodeName = "MODIFIED"
root.setAttribute("attr", "NEW VALUE")
root.setAttribute("added", "VALUE")
return dom, clone
def testCloneElementShallow(self):
dom, clone = self._setupCloneElement(0)
self.confirm(len(clone.childNodes) == 0
and clone.childNodes.length == 0
and clone.parentNode is None
and clone.toxml() == '<doc attr="value"/>'
, "testCloneElementShallow")
dom.unlink()
def testCloneElementDeep(self):
dom, clone = self._setupCloneElement(1)
self.confirm(len(clone.childNodes) == 1
and clone.childNodes.length == 1
and clone.parentNode is None
and clone.toxml() == '<doc attr="value"><foo/></doc>'
, "testCloneElementDeep")
dom.unlink()
def testCloneDocumentShallow(self):
doc = parseString("<?xml version='1.0'?>\n" doc = parseString("<?xml version='1.0'?>\n"
"<!-- comment -->" "<!-- comment -->"
"<!DOCTYPE doc [\n" "<!DOCTYPE doc [\n"
...@@ -590,11 +620,11 @@ def testCloneDocumentShallow(): ...@@ -590,11 +620,11 @@ def testCloneDocumentShallow():
"]>\n" "]>\n"
"<doc attr='value'/>") "<doc attr='value'/>")
doc2 = doc.cloneNode(0) doc2 = doc.cloneNode(0)
confirm(doc2 is None, self.confirm(doc2 is None,
"testCloneDocumentShallow:" "testCloneDocumentShallow:"
" shallow cloning of documents makes no sense!") " shallow cloning of documents makes no sense!")
def testCloneDocumentDeep(): def testCloneDocumentDeep(self):
doc = parseString("<?xml version='1.0'?>\n" doc = parseString("<?xml version='1.0'?>\n"
"<!-- comment -->" "<!-- comment -->"
"<!DOCTYPE doc [\n" "<!DOCTYPE doc [\n"
...@@ -602,27 +632,27 @@ def testCloneDocumentDeep(): ...@@ -602,27 +632,27 @@ def testCloneDocumentDeep():
"]>\n" "]>\n"
"<doc attr='value'/>") "<doc attr='value'/>")
doc2 = doc.cloneNode(1) doc2 = doc.cloneNode(1)
confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)), self.confirm(not (doc.isSameNode(doc2) or doc2.isSameNode(doc)),
"testCloneDocumentDeep: document objects not distinct") "testCloneDocumentDeep: document objects not distinct")
confirm(len(doc.childNodes) == len(doc2.childNodes), self.confirm(len(doc.childNodes) == len(doc2.childNodes),
"testCloneDocumentDeep: wrong number of Document children") "testCloneDocumentDeep: wrong number of Document children")
confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE, self.confirm(doc2.documentElement.nodeType == Node.ELEMENT_NODE,
"testCloneDocumentDeep: documentElement not an ELEMENT_NODE") "testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
confirm(doc2.documentElement.ownerDocument.isSameNode(doc2), self.confirm(doc2.documentElement.ownerDocument.isSameNode(doc2),
"testCloneDocumentDeep: documentElement owner is not new document") "testCloneDocumentDeep: documentElement owner is not new document")
confirm(not doc.documentElement.isSameNode(doc2.documentElement), self.confirm(not doc.documentElement.isSameNode(doc2.documentElement),
"testCloneDocumentDeep: documentElement should not be shared") "testCloneDocumentDeep: documentElement should not be shared")
if doc.doctype is not None: if doc.doctype is not None:
# check the doctype iff the original DOM maintained it # check the doctype iff the original DOM maintained it
confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE, self.confirm(doc2.doctype.nodeType == Node.DOCUMENT_TYPE_NODE,
"testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE") "testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
confirm(doc2.doctype.ownerDocument.isSameNode(doc2)) self.confirm(doc2.doctype.ownerDocument.isSameNode(doc2))
confirm(not doc.doctype.isSameNode(doc2.doctype)) self.confirm(not doc.doctype.isSameNode(doc2.doctype))
def testCloneDocumentTypeDeepOk(): def testCloneDocumentTypeDeepOk(self):
doctype = create_nonempty_doctype() doctype = create_nonempty_doctype()
clone = doctype.cloneNode(1) clone = doctype.cloneNode(1)
confirm(clone is not None self.confirm(clone is not None
and clone.nodeName == doctype.nodeName and clone.nodeName == doctype.nodeName
and clone.name == doctype.name and clone.name == doctype.name
and clone.publicId == doctype.publicId and clone.publicId == doctype.publicId
...@@ -635,7 +665,7 @@ def testCloneDocumentTypeDeepOk(): ...@@ -635,7 +665,7 @@ def testCloneDocumentTypeDeepOk():
for i in range(len(doctype.entities)): for i in range(len(doctype.entities)):
se = doctype.entities.item(i) se = doctype.entities.item(i)
ce = clone.entities.item(i) ce = clone.entities.item(i)
confirm((not se.isSameNode(ce)) self.confirm((not se.isSameNode(ce))
and (not ce.isSameNode(se)) and (not ce.isSameNode(se))
and ce.nodeName == se.nodeName and ce.nodeName == se.nodeName
and ce.notationName == se.notationName and ce.notationName == se.notationName
...@@ -647,21 +677,21 @@ def testCloneDocumentTypeDeepOk(): ...@@ -647,21 +677,21 @@ def testCloneDocumentTypeDeepOk():
for i in range(len(doctype.notations)): for i in range(len(doctype.notations)):
sn = doctype.notations.item(i) sn = doctype.notations.item(i)
cn = clone.notations.item(i) cn = clone.notations.item(i)
confirm((not sn.isSameNode(cn)) self.confirm((not sn.isSameNode(cn))
and (not cn.isSameNode(sn)) and (not cn.isSameNode(sn))
and cn.nodeName == sn.nodeName and cn.nodeName == sn.nodeName
and cn.publicId == sn.publicId and cn.publicId == sn.publicId
and cn.systemId == sn.systemId) and cn.systemId == sn.systemId)
def testCloneDocumentTypeDeepNotOk(): def testCloneDocumentTypeDeepNotOk(self):
doc = create_doc_with_doctype() doc = create_doc_with_doctype()
clone = doc.doctype.cloneNode(1) clone = doc.doctype.cloneNode(1)
confirm(clone is None, "testCloneDocumentTypeDeepNotOk") self.confirm(clone is None, "testCloneDocumentTypeDeepNotOk")
def testCloneDocumentTypeShallowOk(): def testCloneDocumentTypeShallowOk(self):
doctype = create_nonempty_doctype() doctype = create_nonempty_doctype()
clone = doctype.cloneNode(0) clone = doctype.cloneNode(0)
confirm(clone is not None self.confirm(clone is not None
and clone.nodeName == doctype.nodeName and clone.nodeName == doctype.nodeName
and clone.name == doctype.name and clone.name == doctype.name
and clone.publicId == doctype.publicId and clone.publicId == doctype.publicId
...@@ -672,125 +702,80 @@ def testCloneDocumentTypeShallowOk(): ...@@ -672,125 +702,80 @@ def testCloneDocumentTypeShallowOk():
and clone.notations.item(0) is None and clone.notations.item(0) is None
and len(clone.childNodes) == 0) and len(clone.childNodes) == 0)
def testCloneDocumentTypeShallowNotOk(): def testCloneDocumentTypeShallowNotOk(self):
doc = create_doc_with_doctype() doc = create_doc_with_doctype()
clone = doc.doctype.cloneNode(0) clone = doc.doctype.cloneNode(0)
confirm(clone is None, "testCloneDocumentTypeShallowNotOk") self.confirm(clone is None, "testCloneDocumentTypeShallowNotOk")
def check_import_document(deep, testName): def check_import_document(self, deep, testName):
doc1 = parseString("<doc/>") doc1 = parseString("<doc/>")
doc2 = parseString("<doc/>") doc2 = parseString("<doc/>")
try: self.assertRaises(xml.dom.NotSupportedErr, doc1.importNode, doc2, deep)
doc1.importNode(doc2, deep)
except xml.dom.NotSupportedErr:
pass
else:
raise Exception(testName +
": expected NotSupportedErr when importing a document")
def testImportDocumentShallow():
check_import_document(0, "testImportDocumentShallow")
def testImportDocumentDeep(): def testImportDocumentShallow(self):
check_import_document(1, "testImportDocumentDeep") self.check_import_document(0, "testImportDocumentShallow")
# The tests of DocumentType importing use these helpers to construct def testImportDocumentDeep(self):
# the documents to work with, since not all DOM builders actually self.check_import_document(1, "testImportDocumentDeep")
# create the DocumentType nodes.
def create_doc_without_doctype(doctype=None): def testImportDocumentTypeShallow(self):
return getDOMImplementation().createDocument(None, "doc", doctype)
def create_nonempty_doctype():
doctype = getDOMImplementation().createDocumentType("doc", None, None)
doctype.entities._seq = []
doctype.notations._seq = []
notation = xml.dom.minidom.Notation("my-notation", None,
"http://xml.python.org/notations/my")
doctype.notations._seq.append(notation)
entity = xml.dom.minidom.Entity("my-entity", None,
"http://xml.python.org/entities/my",
"my-notation")
entity.version = "1.0"
entity.encoding = "utf-8"
entity.actualEncoding = "us-ascii"
doctype.entities._seq.append(entity)
return doctype
def create_doc_with_doctype():
doctype = create_nonempty_doctype()
doc = create_doc_without_doctype(doctype)
doctype.entities.item(0).ownerDocument = doc
doctype.notations.item(0).ownerDocument = doc
return doc
def testImportDocumentTypeShallow():
src = create_doc_with_doctype() src = create_doc_with_doctype()
target = create_doc_without_doctype() target = create_doc_without_doctype()
try: self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
imported = target.importNode(src.doctype, 0) src.doctype, 0)
except xml.dom.NotSupportedErr:
pass
else:
raise Exception(
"testImportDocumentTypeShallow: expected NotSupportedErr")
def testImportDocumentTypeDeep(): def testImportDocumentTypeDeep(self):
src = create_doc_with_doctype() src = create_doc_with_doctype()
target = create_doc_without_doctype() target = create_doc_without_doctype()
try: self.assertRaises(xml.dom.NotSupportedErr, target.importNode,
imported = target.importNode(src.doctype, 1) src.doctype, 1)
except xml.dom.NotSupportedErr:
pass
else:
raise Exception(
"testImportDocumentTypeDeep: expected NotSupportedErr")
# Testing attribute clones uses a helper, and should always be deep, # Testing attribute clones uses a helper, and should always be deep,
# even if the argument to cloneNode is false. # even if the argument to cloneNode is false.
def check_clone_attribute(deep, testName): def check_clone_attribute(self, deep, testName):
doc = parseString("<doc attr='value'/>") doc = parseString("<doc attr='value'/>")
attr = doc.documentElement.getAttributeNode("attr") attr = doc.documentElement.getAttributeNode("attr")
assert attr is not None self.failIfEqual(attr, None)
clone = attr.cloneNode(deep) clone = attr.cloneNode(deep)
confirm(not clone.isSameNode(attr)) self.confirm(not clone.isSameNode(attr))
confirm(not attr.isSameNode(clone)) self.confirm(not attr.isSameNode(clone))
confirm(clone.ownerElement is None, self.confirm(clone.ownerElement is None,
testName + ": ownerElement should be None") testName + ": ownerElement should be None")
confirm(clone.ownerDocument.isSameNode(attr.ownerDocument), self.confirm(clone.ownerDocument.isSameNode(attr.ownerDocument),
testName + ": ownerDocument does not match") testName + ": ownerDocument does not match")
confirm(clone.specified, self.confirm(clone.specified,
testName + ": cloned attribute must have specified == True") testName + ": cloned attribute must have specified == True")
def testCloneAttributeShallow(): def testCloneAttributeShallow(self):
check_clone_attribute(0, "testCloneAttributeShallow") self.check_clone_attribute(0, "testCloneAttributeShallow")
def testCloneAttributeDeep(): def testCloneAttributeDeep(self):
check_clone_attribute(1, "testCloneAttributeDeep") self.check_clone_attribute(1, "testCloneAttributeDeep")
def check_clone_pi(deep, testName): def check_clone_pi(self, deep, testName):
doc = parseString("<?target data?><doc/>") doc = parseString("<?target data?><doc/>")
pi = doc.firstChild pi = doc.firstChild
assert pi.nodeType == Node.PROCESSING_INSTRUCTION_NODE self.assertEquals(pi.nodeType, Node.PROCESSING_INSTRUCTION_NODE)
clone = pi.cloneNode(deep) clone = pi.cloneNode(deep)
confirm(clone.target == pi.target self.confirm(clone.target == pi.target
and clone.data == pi.data) and clone.data == pi.data)
def testClonePIShallow(): def testClonePIShallow(self):
check_clone_pi(0, "testClonePIShallow") self.check_clone_pi(0, "testClonePIShallow")
def testClonePIDeep(): def testClonePIDeep(self):
check_clone_pi(1, "testClonePIDeep") self.check_clone_pi(1, "testClonePIDeep")
def testNormalize(): def testNormalize(self):
doc = parseString("<doc/>") doc = parseString("<doc/>")
root = doc.documentElement root = doc.documentElement
root.appendChild(doc.createTextNode("first")) root.appendChild(doc.createTextNode("first"))
root.appendChild(doc.createTextNode("second")) root.appendChild(doc.createTextNode("second"))
confirm(len(root.childNodes) == 2 self.confirm(len(root.childNodes) == 2
and root.childNodes.length == 2, "testNormalize -- preparation") and root.childNodes.length == 2,
"testNormalize -- preparation")
doc.normalize() doc.normalize()
confirm(len(root.childNodes) == 1 self.confirm(len(root.childNodes) == 1
and root.childNodes.length == 1 and root.childNodes.length == 1
and root.firstChild is root.lastChild and root.firstChild is root.lastChild
and root.firstChild.data == "firstsecond" and root.firstChild.data == "firstsecond"
...@@ -801,17 +786,17 @@ def testNormalize(): ...@@ -801,17 +786,17 @@ def testNormalize():
root = doc.documentElement root = doc.documentElement
root.appendChild(doc.createTextNode("")) root.appendChild(doc.createTextNode(""))
doc.normalize() doc.normalize()
confirm(len(root.childNodes) == 0 self.confirm(len(root.childNodes) == 0
and root.childNodes.length == 0, and root.childNodes.length == 0,
"testNormalize -- single empty node removed") "testNormalize -- single empty node removed")
doc.unlink() doc.unlink()
def testSiblings(): def testSiblings(self):
doc = parseString("<doc><?pi?>text?<elm/></doc>") doc = parseString("<doc><?pi?>text?<elm/></doc>")
root = doc.documentElement root = doc.documentElement
(pi, text, elm) = root.childNodes (pi, text, elm) = root.childNodes
confirm(pi.nextSibling is text and self.confirm(pi.nextSibling is text and
pi.previousSibling is None and pi.previousSibling is None and
text.nextSibling is elm and text.nextSibling is elm and
text.previousSibling is pi and text.previousSibling is pi and
...@@ -820,26 +805,26 @@ def testSiblings(): ...@@ -820,26 +805,26 @@ def testSiblings():
doc.unlink() doc.unlink()
def testParents(): def testParents(self):
doc = parseString("<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>") doc = parseString(
"<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
root = doc.documentElement root = doc.documentElement
elm1 = root.childNodes[0] elm1 = root.childNodes[0]
(elm2a, elm2b) = elm1.childNodes (elm2a, elm2b) = elm1.childNodes
elm3 = elm2b.childNodes[0] elm3 = elm2b.childNodes[0]
confirm(root.parentNode is doc and self.confirm(root.parentNode is doc and
elm1.parentNode is root and elm1.parentNode is root and
elm2a.parentNode is elm1 and elm2a.parentNode is elm1 and
elm2b.parentNode is elm1 and elm2b.parentNode is elm1 and
elm3.parentNode is elm2b, "testParents") elm3.parentNode is elm2b, "testParents")
doc.unlink() doc.unlink()
def testNodeListItem(): def testNodeListItem(self):
doc = parseString("<doc><e/><e/></doc>") doc = parseString("<doc><e/><e/></doc>")
children = doc.childNodes children = doc.childNodes
docelem = children[0] docelem = children[0]
confirm(children[0] is children.item(0) self.confirm(children[0] is children.item(0)
and children.item(1) is None and children.item(1) is None
and docelem.childNodes.item(0) is docelem.childNodes[0] and docelem.childNodes.item(0) is docelem.childNodes[0]
and docelem.childNodes.item(1) is docelem.childNodes[1] and docelem.childNodes.item(1) is docelem.childNodes[1]
...@@ -847,7 +832,7 @@ def testNodeListItem(): ...@@ -847,7 +832,7 @@ def testNodeListItem():
"test NodeList.item()") "test NodeList.item()")
doc.unlink() doc.unlink()
def testSAX2DOM(): def testSAX2DOM(self):
from xml.dom import pulldom from xml.dom import pulldom
sax2dom = pulldom.SAX2DOM() sax2dom = pulldom.SAX2DOM()
...@@ -866,7 +851,7 @@ def testSAX2DOM(): ...@@ -866,7 +851,7 @@ def testSAX2DOM():
(text1, elm1, text2) = root.childNodes (text1, elm1, text2) = root.childNodes
text3 = elm1.childNodes[0] text3 = elm1.childNodes[0]
confirm(text1.previousSibling is None and self.confirm(text1.previousSibling is None and
text1.nextSibling is elm1 and text1.nextSibling is elm1 and
elm1.previousSibling is text1 and elm1.previousSibling is text1 and
elm1.nextSibling is text2 and elm1.nextSibling is text2 and
...@@ -875,63 +860,69 @@ def testSAX2DOM(): ...@@ -875,63 +860,69 @@ def testSAX2DOM():
text3.previousSibling is None and text3.previousSibling is None and
text3.nextSibling is None, "testSAX2DOM - siblings") text3.nextSibling is None, "testSAX2DOM - siblings")
confirm(root.parentNode is doc and self.confirm(root.parentNode is doc and
text1.parentNode is root and text1.parentNode is root and
elm1.parentNode is root and elm1.parentNode is root and
text2.parentNode is root and text2.parentNode is root and
text3.parentNode is elm1, "testSAX2DOM - parents") text3.parentNode is elm1, "testSAX2DOM - parents")
doc.unlink() doc.unlink()
def testEncodings(): def testEncodings(self):
doc = parseString('<foo>&#x20ac;</foo>') doc = parseString('<foo>&#x20ac;</foo>')
confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>' self.confirm(doc.toxml() == u'<?xml version="1.0" ?><foo>\u20ac</foo>'
and doc.toxml('utf-8') == '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>' and doc.toxml('utf-8') ==
and doc.toxml('iso-8859-15') == '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>', '<?xml version="1.0" encoding="utf-8"?><foo>\xe2\x82\xac</foo>'
and doc.toxml('iso-8859-15') ==
'<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
"testEncodings - encoding EURO SIGN") "testEncodings - encoding EURO SIGN")
# Verify that character decoding errors throw exceptions instead of crashing # Verify that character decoding errors throw exceptions instead
try: # of crashing
doc = parseString('<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>') self.assertRaises(UnicodeDecodeError, parseString,
except UnicodeDecodeError: '<fran\xe7ais>Comment \xe7a va ? Tr\xe8s bien ?</fran\xe7ais>')
pass
else:
print 'parsing with bad encoding should raise a UnicodeDecodeError'
doc.unlink() doc.unlink()
class UserDataHandler: class UserDataHandler:
called = 0 called = 0
def handle(self, operation, key, data, src, dst): def handle(self, operation, key, data, src, dst):
dst.setUserData(key, data + 1, self) dst.setUserData(key, data + 1, self)
src.setUserData(key, None, None) src.setUserData(key, None, None)
self.called = 1 self.called = 1
def testUserData(): def testUserData(self):
dom = Document() dom = Document()
n = dom.createElement('e') n = dom.createElement('e')
confirm(n.getUserData("foo") is None) self.confirm(n.getUserData("foo") is None)
n.setUserData("foo", None, None) n.setUserData("foo", None, None)
confirm(n.getUserData("foo") is None) self.confirm(n.getUserData("foo") is None)
n.setUserData("foo", 12, 12) n.setUserData("foo", 12, 12)
n.setUserData("bar", 13, 13) n.setUserData("bar", 13, 13)
confirm(n.getUserData("foo") == 12) self.confirm(n.getUserData("foo") == 12)
confirm(n.getUserData("bar") == 13) self.confirm(n.getUserData("bar") == 13)
n.setUserData("foo", None, None) n.setUserData("foo", None, None)
confirm(n.getUserData("foo") is None) self.confirm(n.getUserData("foo") is None)
confirm(n.getUserData("bar") == 13) self.confirm(n.getUserData("bar") == 13)
handler = UserDataHandler() handler = self.UserDataHandler()
n.setUserData("bar", 12, handler) n.setUserData("bar", 12, handler)
c = n.cloneNode(1) c = n.cloneNode(1)
confirm(handler.called self.confirm(handler.called
and n.getUserData("bar") is None and n.getUserData("bar") is None
and c.getUserData("bar") == 13) and c.getUserData("bar") == 13)
n.unlink() n.unlink()
c.unlink() c.unlink()
dom.unlink() dom.unlink()
def testRenameAttribute(): def checkRenameNodeSharedConstraints(self, doc, node):
# Make sure illegal NS usage is detected:
self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, node,
"http://xml.python.org/ns", "xmlns:foo")
doc2 = parseString("<doc/>")
self.assertRaises(xml.dom.WrongDocumentErr, doc2.renameNode, node,
xml.dom.EMPTY_NAMESPACE, "foo")
def testRenameAttribute(self):
doc = parseString("<doc a='v'/>") doc = parseString("<doc a='v'/>")
elem = doc.documentElement elem = doc.documentElement
attrmap = elem.attributes attrmap = elem.attributes
...@@ -939,7 +930,7 @@ def testRenameAttribute(): ...@@ -939,7 +930,7 @@ def testRenameAttribute():
# Simple renaming # Simple renaming
attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b") attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "b")
confirm(attr.name == "b" self.confirm(attr.name == "b"
and attr.nodeName == "b" and attr.nodeName == "b"
and attr.localName is None and attr.localName is None
and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
...@@ -953,7 +944,7 @@ def testRenameAttribute(): ...@@ -953,7 +944,7 @@ def testRenameAttribute():
# Rename to have a namespace, no prefix # Rename to have a namespace, no prefix
attr = doc.renameNode(attr, "http://xml.python.org/ns", "c") attr = doc.renameNode(attr, "http://xml.python.org/ns", "c")
confirm(attr.name == "c" self.confirm(attr.name == "c"
and attr.nodeName == "c" and attr.nodeName == "c"
and attr.localName == "c" and attr.localName == "c"
and attr.namespaceURI == "http://xml.python.org/ns" and attr.namespaceURI == "http://xml.python.org/ns"
...@@ -969,7 +960,7 @@ def testRenameAttribute(): ...@@ -969,7 +960,7 @@ def testRenameAttribute():
# Rename to have a namespace, with prefix # Rename to have a namespace, with prefix
attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d") attr = doc.renameNode(attr, "http://xml.python.org/ns2", "p:d")
confirm(attr.name == "p:d" self.confirm(attr.name == "p:d"
and attr.nodeName == "p:d" and attr.nodeName == "p:d"
and attr.localName == "d" and attr.localName == "d"
and attr.namespaceURI == "http://xml.python.org/ns2" and attr.namespaceURI == "http://xml.python.org/ns2"
...@@ -988,7 +979,7 @@ def testRenameAttribute(): ...@@ -988,7 +979,7 @@ def testRenameAttribute():
# Rename back to a simple non-NS node # Rename back to a simple non-NS node
attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e") attr = doc.renameNode(attr, xml.dom.EMPTY_NAMESPACE, "e")
confirm(attr.name == "e" self.confirm(attr.name == "e"
and attr.nodeName == "e" and attr.nodeName == "e"
and attr.localName is None and attr.localName is None
and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE and attr.namespaceURI == xml.dom.EMPTY_NAMESPACE
...@@ -1003,23 +994,18 @@ def testRenameAttribute(): ...@@ -1003,23 +994,18 @@ def testRenameAttribute():
and elem.getAttributeNode("e").isSameNode(attr) and elem.getAttributeNode("e").isSameNode(attr)
and attrmap["e"].isSameNode(attr)) and attrmap["e"].isSameNode(attr))
try: self.assertRaises(xml.dom.NamespaceErr, doc.renameNode, attr,
doc.renameNode(attr, "http://xml.python.org/ns", "xmlns") "http://xml.python.org/ns", "xmlns")
except xml.dom.NamespaceErr: self.checkRenameNodeSharedConstraints(doc, attr)
pass
else:
print "expected NamespaceErr"
checkRenameNodeSharedConstraints(doc, attr)
doc.unlink() doc.unlink()
def testRenameElement(): def testRenameElement(self):
doc = parseString("<doc/>") doc = parseString("<doc/>")
elem = doc.documentElement elem = doc.documentElement
# Simple renaming # Simple renaming
elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a") elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "a")
confirm(elem.tagName == "a" self.confirm(elem.tagName == "a"
and elem.nodeName == "a" and elem.nodeName == "a"
and elem.localName is None and elem.localName is None
and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
...@@ -1028,7 +1014,7 @@ def testRenameElement(): ...@@ -1028,7 +1014,7 @@ def testRenameElement():
# Rename to have a namespace, no prefix # Rename to have a namespace, no prefix
elem = doc.renameNode(elem, "http://xml.python.org/ns", "b") elem = doc.renameNode(elem, "http://xml.python.org/ns", "b")
confirm(elem.tagName == "b" self.confirm(elem.tagName == "b"
and elem.nodeName == "b" and elem.nodeName == "b"
and elem.localName == "b" and elem.localName == "b"
and elem.namespaceURI == "http://xml.python.org/ns" and elem.namespaceURI == "http://xml.python.org/ns"
...@@ -1037,7 +1023,7 @@ def testRenameElement(): ...@@ -1037,7 +1023,7 @@ def testRenameElement():
# Rename to have a namespace, with prefix # Rename to have a namespace, with prefix
elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c") elem = doc.renameNode(elem, "http://xml.python.org/ns2", "p:c")
confirm(elem.tagName == "p:c" self.confirm(elem.tagName == "p:c"
and elem.nodeName == "p:c" and elem.nodeName == "p:c"
and elem.localName == "c" and elem.localName == "c"
and elem.namespaceURI == "http://xml.python.org/ns2" and elem.namespaceURI == "http://xml.python.org/ns2"
...@@ -1046,99 +1032,72 @@ def testRenameElement(): ...@@ -1046,99 +1032,72 @@ def testRenameElement():
# Rename back to a simple non-NS node # Rename back to a simple non-NS node
elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d") elem = doc.renameNode(elem, xml.dom.EMPTY_NAMESPACE, "d")
confirm(elem.tagName == "d" self.confirm(elem.tagName == "d"
and elem.nodeName == "d" and elem.nodeName == "d"
and elem.localName is None and elem.localName is None
and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE and elem.namespaceURI == xml.dom.EMPTY_NAMESPACE
and elem.prefix is None and elem.prefix is None
and elem.ownerDocument.isSameNode(doc)) and elem.ownerDocument.isSameNode(doc))
checkRenameNodeSharedConstraints(doc, elem) self.checkRenameNodeSharedConstraints(doc, elem)
doc.unlink() doc.unlink()
def checkRenameNodeSharedConstraints(doc, node): def testRenameOther(self):
# Make sure illegal NS usage is detected:
try:
doc.renameNode(node, "http://xml.python.org/ns", "xmlns:foo")
except xml.dom.NamespaceErr:
pass
else:
print "expected NamespaceErr"
doc2 = parseString("<doc/>")
try:
doc2.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo")
except xml.dom.WrongDocumentErr:
pass
else:
print "expected WrongDocumentErr"
def testRenameOther():
# We have to create a comment node explicitly since not all DOM # We have to create a comment node explicitly since not all DOM
# builders used with minidom add comments to the DOM. # builders used with minidom add comments to the DOM.
doc = xml.dom.minidom.getDOMImplementation().createDocument( doc = xml.dom.minidom.getDOMImplementation().createDocument(
xml.dom.EMPTY_NAMESPACE, "e", None) xml.dom.EMPTY_NAMESPACE, "e", None)
node = doc.createComment("comment") node = doc.createComment("comment")
try: self.assertRaises(xml.dom.NotSupportedErr, doc.renameNode, node,
doc.renameNode(node, xml.dom.EMPTY_NAMESPACE, "foo") xml.dom.EMPTY_NAMESPACE, "foo")
except xml.dom.NotSupportedErr:
pass
else:
print "expected NotSupportedErr when renaming comment node"
doc.unlink() doc.unlink()
def checkWholeText(node, s): def testWholeText(self):
t = node.wholeText
confirm(t == s, "looking for %s, found %s" % (repr(s), repr(t)))
def testWholeText():
doc = parseString("<doc>a</doc>") doc = parseString("<doc>a</doc>")
elem = doc.documentElement elem = doc.documentElement
text = elem.childNodes[0] text = elem.childNodes[0]
assert text.nodeType == Node.TEXT_NODE self.assertEquals(text.nodeType, Node.TEXT_NODE)
checkWholeText(text, "a") self.checkWholeText(text, "a")
elem.appendChild(doc.createTextNode("b")) elem.appendChild(doc.createTextNode("b"))
checkWholeText(text, "ab") self.checkWholeText(text, "ab")
elem.insertBefore(doc.createCDATASection("c"), text) elem.insertBefore(doc.createCDATASection("c"), text)
checkWholeText(text, "cab") self.checkWholeText(text, "cab")
# make sure we don't cross other nodes # make sure we don't cross other nodes
splitter = doc.createComment("comment") splitter = doc.createComment("comment")
elem.appendChild(splitter) elem.appendChild(splitter)
text2 = doc.createTextNode("d") text2 = doc.createTextNode("d")
elem.appendChild(text2) elem.appendChild(text2)
checkWholeText(text, "cab") self.checkWholeText(text, "cab")
checkWholeText(text2, "d") self.checkWholeText(text2, "d")
x = doc.createElement("x") x = doc.createElement("x")
elem.replaceChild(x, splitter) elem.replaceChild(x, splitter)
splitter = x splitter = x
checkWholeText(text, "cab") self.checkWholeText(text, "cab")
checkWholeText(text2, "d") self.checkWholeText(text2, "d")
x = doc.createProcessingInstruction("y", "z") x = doc.createProcessingInstruction("y", "z")
elem.replaceChild(x, splitter) elem.replaceChild(x, splitter)
splitter = x splitter = x
checkWholeText(text, "cab") self.checkWholeText(text, "cab")
checkWholeText(text2, "d") self.checkWholeText(text2, "d")
elem.removeChild(splitter) elem.removeChild(splitter)
checkWholeText(text, "cabd") self.checkWholeText(text, "cabd")
checkWholeText(text2, "cabd") self.checkWholeText(text2, "cabd")
def testPatch1094164 (): def testPatch1094164(self):
doc = parseString("<doc><e/></doc>") doc = parseString("<doc><e/></doc>")
elem = doc.documentElement elem = doc.documentElement
e = elem.firstChild e = elem.firstChild
confirm(e.parentNode is elem, "Before replaceChild()") self.confirm(e.parentNode is elem, "Before replaceChild()")
# Check that replacing a child with itself leaves the tree unchanged # Check that replacing a child with itself leaves the tree unchanged
elem.replaceChild(e, e) elem.replaceChild(e, e)
confirm(e.parentNode is elem, "After replaceChild()") self.confirm(e.parentNode is elem, "After replaceChild()")
def testReplaceWholeText(self):
def testReplaceWholeText():
def setup(): def setup():
doc = parseString("<doc>a<e/>d</doc>") doc = parseString("<doc>a<e/>d</doc>")
elem = doc.documentElement elem = doc.documentElement
...@@ -1151,23 +1110,23 @@ def testReplaceWholeText(): ...@@ -1151,23 +1110,23 @@ def testReplaceWholeText():
doc, elem, text1, splitter, text2 = setup() doc, elem, text1, splitter, text2 = setup()
text = text1.replaceWholeText("new content") text = text1.replaceWholeText("new content")
checkWholeText(text, "new content") self.checkWholeText(text, "new content")
checkWholeText(text2, "d") self.checkWholeText(text2, "d")
confirm(len(elem.childNodes) == 3) self.confirm(len(elem.childNodes) == 3)
doc, elem, text1, splitter, text2 = setup() doc, elem, text1, splitter, text2 = setup()
text = text2.replaceWholeText("new content") text = text2.replaceWholeText("new content")
checkWholeText(text, "new content") self.checkWholeText(text, "new content")
checkWholeText(text1, "cab") self.checkWholeText(text1, "cab")
confirm(len(elem.childNodes) == 5) self.confirm(len(elem.childNodes) == 5)
doc, elem, text1, splitter, text2 = setup() doc, elem, text1, splitter, text2 = setup()
text = text1.replaceWholeText("") text = text1.replaceWholeText("")
checkWholeText(text2, "d") self.checkWholeText(text2, "d")
confirm(text is None self.confirm(text is None
and len(elem.childNodes) == 2) and len(elem.childNodes) == 2)
def testSchemaType(): def testSchemaType(self):
doc = parseString( doc = parseString(
"<!DOCTYPE doc [\n" "<!DOCTYPE doc [\n"
" <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n" " <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
...@@ -1191,29 +1150,29 @@ def testSchemaType(): ...@@ -1191,29 +1150,29 @@ def testSchemaType():
# DTD-based namespace is right. The names can vary by loader # DTD-based namespace is right. The names can vary by loader
# since each supports a different level of DTD information. # since each supports a different level of DTD information.
t = elem.schemaType t = elem.schemaType
confirm(t.name is None self.confirm(t.name is None
and t.namespace == xml.dom.EMPTY_NAMESPACE) and t.namespace == xml.dom.EMPTY_NAMESPACE)
names = "id notid text enum ref refs ent ents nm nms".split() names = "id notid text enum ref refs ent ents nm nms".split()
for name in names: for name in names:
a = elem.getAttributeNode(name) a = elem.getAttributeNode(name)
t = a.schemaType t = a.schemaType
confirm(hasattr(t, "name") self.confirm(hasattr(t, "name")
and t.namespace == xml.dom.EMPTY_NAMESPACE) and t.namespace == xml.dom.EMPTY_NAMESPACE)
def testSetIdAttribute(): def testSetIdAttribute(self):
doc = parseString("<doc a1='v' a2='w'/>") doc = parseString("<doc a1='v' a2='w'/>")
e = doc.documentElement e = doc.documentElement
a1 = e.getAttributeNode("a1") a1 = e.getAttributeNode("a1")
a2 = e.getAttributeNode("a2") a2 = e.getAttributeNode("a2")
confirm(doc.getElementById("v") is None self.confirm(doc.getElementById("v") is None
and not a1.isId and not a1.isId
and not a2.isId) and not a2.isId)
e.setIdAttribute("a1") e.setIdAttribute("a1")
confirm(e.isSameNode(doc.getElementById("v")) self.confirm(e.isSameNode(doc.getElementById("v"))
and a1.isId and a1.isId
and not a2.isId) and not a2.isId)
e.setIdAttribute("a2") e.setIdAttribute("a2")
confirm(e.isSameNode(doc.getElementById("v")) self.confirm(e.isSameNode(doc.getElementById("v"))
and e.isSameNode(doc.getElementById("w")) and e.isSameNode(doc.getElementById("w"))
and a1.isId and a1.isId
and a2.isId) and a2.isId)
...@@ -1221,17 +1180,17 @@ def testSetIdAttribute(): ...@@ -1221,17 +1180,17 @@ def testSetIdAttribute():
a3 = doc.createAttribute("a1") a3 = doc.createAttribute("a1")
a3.value = "v" a3.value = "v"
e.setAttributeNode(a3) e.setAttributeNode(a3)
confirm(doc.getElementById("v") is None self.confirm(doc.getElementById("v") is None
and e.isSameNode(doc.getElementById("w")) and e.isSameNode(doc.getElementById("w"))
and not a1.isId and not a1.isId
and a2.isId and a2.isId
and not a3.isId) and not a3.isId)
# renaming an attribute should not affect its ID-ness: # renaming an attribute should not affect its ID-ness:
doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
confirm(e.isSameNode(doc.getElementById("w")) self.confirm(e.isSameNode(doc.getElementById("w"))
and a2.isId) and a2.isId)
def testSetIdAttributeNS(): def testSetIdAttributeNS(self):
NS1 = "http://xml.python.org/ns1" NS1 = "http://xml.python.org/ns1"
NS2 = "http://xml.python.org/ns2" NS2 = "http://xml.python.org/ns2"
doc = parseString("<doc" doc = parseString("<doc"
...@@ -1241,15 +1200,15 @@ def testSetIdAttributeNS(): ...@@ -1241,15 +1200,15 @@ def testSetIdAttributeNS():
e = doc.documentElement e = doc.documentElement
a1 = e.getAttributeNodeNS(NS1, "a1") a1 = e.getAttributeNodeNS(NS1, "a1")
a2 = e.getAttributeNodeNS(NS2, "a2") a2 = e.getAttributeNodeNS(NS2, "a2")
confirm(doc.getElementById("v") is None self.confirm(doc.getElementById("v") is None
and not a1.isId and not a1.isId
and not a2.isId) and not a2.isId)
e.setIdAttributeNS(NS1, "a1") e.setIdAttributeNS(NS1, "a1")
confirm(e.isSameNode(doc.getElementById("v")) self.confirm(e.isSameNode(doc.getElementById("v"))
and a1.isId and a1.isId
and not a2.isId) and not a2.isId)
e.setIdAttributeNS(NS2, "a2") e.setIdAttributeNS(NS2, "a2")
confirm(e.isSameNode(doc.getElementById("v")) self.confirm(e.isSameNode(doc.getElementById("v"))
and e.isSameNode(doc.getElementById("w")) and e.isSameNode(doc.getElementById("w"))
and a1.isId and a1.isId
and a2.isId) and a2.isId)
...@@ -1257,17 +1216,17 @@ def testSetIdAttributeNS(): ...@@ -1257,17 +1216,17 @@ def testSetIdAttributeNS():
a3 = doc.createAttributeNS(NS1, "a1") a3 = doc.createAttributeNS(NS1, "a1")
a3.value = "v" a3.value = "v"
e.setAttributeNode(a3) e.setAttributeNode(a3)
confirm(e.isSameNode(doc.getElementById("w"))) self.confirm(e.isSameNode(doc.getElementById("w")))
confirm(not a1.isId) self.confirm(not a1.isId)
confirm(a2.isId) self.confirm(a2.isId)
confirm(not a3.isId) self.confirm(not a3.isId)
confirm(doc.getElementById("v") is None) self.confirm(doc.getElementById("v") is None)
# renaming an attribute should not affect its ID-ness: # renaming an attribute should not affect its ID-ness:
doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
confirm(e.isSameNode(doc.getElementById("w")) self.confirm(e.isSameNode(doc.getElementById("w"))
and a2.isId) and a2.isId)
def testSetIdAttributeNode(): def testSetIdAttributeNode(self):
NS1 = "http://xml.python.org/ns1" NS1 = "http://xml.python.org/ns1"
NS2 = "http://xml.python.org/ns2" NS2 = "http://xml.python.org/ns2"
doc = parseString("<doc" doc = parseString("<doc"
...@@ -1277,15 +1236,15 @@ def testSetIdAttributeNode(): ...@@ -1277,15 +1236,15 @@ def testSetIdAttributeNode():
e = doc.documentElement e = doc.documentElement
a1 = e.getAttributeNodeNS(NS1, "a1") a1 = e.getAttributeNodeNS(NS1, "a1")
a2 = e.getAttributeNodeNS(NS2, "a2") a2 = e.getAttributeNodeNS(NS2, "a2")
confirm(doc.getElementById("v") is None self.confirm(doc.getElementById("v") is None
and not a1.isId and not a1.isId
and not a2.isId) and not a2.isId)
e.setIdAttributeNode(a1) e.setIdAttributeNode(a1)
confirm(e.isSameNode(doc.getElementById("v")) self.confirm(e.isSameNode(doc.getElementById("v"))
and a1.isId and a1.isId
and not a2.isId) and not a2.isId)
e.setIdAttributeNode(a2) e.setIdAttributeNode(a2)
confirm(e.isSameNode(doc.getElementById("v")) self.confirm(e.isSameNode(doc.getElementById("v"))
and e.isSameNode(doc.getElementById("w")) and e.isSameNode(doc.getElementById("w"))
and a1.isId and a1.isId
and a2.isId) and a2.isId)
...@@ -1293,17 +1252,17 @@ def testSetIdAttributeNode(): ...@@ -1293,17 +1252,17 @@ def testSetIdAttributeNode():
a3 = doc.createAttributeNS(NS1, "a1") a3 = doc.createAttributeNS(NS1, "a1")
a3.value = "v" a3.value = "v"
e.setAttributeNode(a3) e.setAttributeNode(a3)
confirm(e.isSameNode(doc.getElementById("w"))) self.confirm(e.isSameNode(doc.getElementById("w")))
confirm(not a1.isId) self.confirm(not a1.isId)
confirm(a2.isId) self.confirm(a2.isId)
confirm(not a3.isId) self.confirm(not a3.isId)
confirm(doc.getElementById("v") is None) self.confirm(doc.getElementById("v") is None)
# renaming an attribute should not affect its ID-ness: # renaming an attribute should not affect its ID-ness:
doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an") doc.renameNode(a2, xml.dom.EMPTY_NAMESPACE, "an")
confirm(e.isSameNode(doc.getElementById("w")) self.confirm(e.isSameNode(doc.getElementById("w"))
and a2.isId) and a2.isId)
def testPickledDocument(): def testPickledDocument(self):
doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n" doc = parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
"<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'" "<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
" 'http://xml.python.org/system' [\n" " 'http://xml.python.org/system' [\n"
...@@ -1316,7 +1275,7 @@ def testPickledDocument(): ...@@ -1316,7 +1275,7 @@ def testPickledDocument():
stack = [(doc, doc2)] stack = [(doc, doc2)]
while stack: while stack:
n1, n2 = stack.pop() n1, n2 = stack.pop()
confirm(n1.nodeType == n2.nodeType self.confirm(n1.nodeType == n2.nodeType
and len(n1.childNodes) == len(n2.childNodes) and len(n1.childNodes) == len(n2.childNodes)
and n1.nodeName == n2.nodeName and n1.nodeName == n2.nodeName
and not n1.isSameNode(n2) and not n1.isSameNode(n2)
...@@ -1326,72 +1285,30 @@ def testPickledDocument(): ...@@ -1326,72 +1285,30 @@ def testPickledDocument():
len(n2.entities) len(n2.entities)
len(n1.notations) len(n1.notations)
len(n2.notations) len(n2.notations)
confirm(len(n1.entities) == len(n2.entities) self.confirm(len(n1.entities) == len(n2.entities)
and len(n1.notations) == len(n2.notations)) and len(n1.notations) == len(n2.notations))
for i in range(len(n1.notations)): for i in range(len(n1.notations)):
no1 = n1.notations.item(i) no1 = n1.notations.item(i)
no2 = n1.notations.item(i) no2 = n1.notations.item(i)
confirm(no1.name == no2.name self.confirm(no1.name == no2.name
and no1.publicId == no2.publicId and no1.publicId == no2.publicId
and no1.systemId == no2.systemId) and no1.systemId == no2.systemId)
statck.append((no1, no2)) statck.append((no1, no2))
for i in range(len(n1.entities)): for i in range(len(n1.entities)):
e1 = n1.entities.item(i) e1 = n1.entities.item(i)
e2 = n2.entities.item(i) e2 = n2.entities.item(i)
confirm(e1.notationName == e2.notationName self.confirm(e1.notationName == e2.notationName
and e1.publicId == e2.publicId and e1.publicId == e2.publicId
and e1.systemId == e2.systemId) and e1.systemId == e2.systemId)
stack.append((e1, e2)) stack.append((e1, e2))
if n1.nodeType != Node.DOCUMENT_NODE: if n1.nodeType != Node.DOCUMENT_NODE:
confirm(n1.ownerDocument.isSameNode(doc) self.confirm(n1.ownerDocument.isSameNode(doc)
and n2.ownerDocument.isSameNode(doc2)) and n2.ownerDocument.isSameNode(doc2))
for i in range(len(n1.childNodes)): for i in range(len(n1.childNodes)):
stack.append((n1.childNodes[i], n2.childNodes[i])) stack.append((n1.childNodes[i], n2.childNodes[i]))
def test_main():
run_unittest(MinidomTest)
# --- MAIN PROGRAM if __name__ == "__main__":
test_main()
names = globals().keys()
names.sort()
failed = []
try:
Node.allnodes
except AttributeError:
# We don't actually have the minidom from the standard library,
# but are picking up the PyXML version from site-packages.
def check_allnodes():
pass
else:
def check_allnodes():
confirm(len(Node.allnodes) == 0,
"assertion: len(Node.allnodes) == 0")
if len(Node.allnodes):
print "Garbage left over:"
if verbose:
print Node.allnodes.items()[0:10]
else:
# Don't print specific nodes if repeatable results
# are needed
print len(Node.allnodes)
Node.allnodes = {}
for name in names:
if name.startswith("test"):
func = globals()[name]
try:
func()
check_allnodes()
except:
failed.append(name)
print "Test Failed: ", name
sys.stdout.flush()
traceback.print_exception(*sys.exc_info())
print repr(sys.exc_info()[1])
Node.allnodes = {}
if failed:
print "\n\n\n**** Check for failures in these tests:"
for name in failed:
print " " + name
# Very simple test - Parse a file and print what happens
# XXX TypeErrors on calling handlers, or on bad return values from a # XXX TypeErrors on calling handlers, or on bad return values from a
# handler, are obscure and unhelpful. # handler, are obscure and unhelpful.
import StringIO
import unittest
import pyexpat import pyexpat
from xml.parsers import expat from xml.parsers import expat
from test.test_support import sortdict, TestFailed from test.test_support import sortdict, run_unittest
class SetAttributeTest(unittest.TestCase):
def setUp(self):
self.parser = expat.ParserCreate(namespace_separator='!')
self.set_get_pairs = [
[0, 0],
[1, 1],
[2, 1],
[0, 0],
]
def test_returns_unicode(self):
for x, y in self.set_get_pairs:
self.parser.returns_unicode = x
self.assertEquals(self.parser.returns_unicode, y)
def test_ordered_attributes(self):
for x, y in self.set_get_pairs:
self.parser.ordered_attributes = x
self.assertEquals(self.parser.ordered_attributes, y)
def test_specified_attributes(self):
for x, y in self.set_get_pairs:
self.parser.specified_attributes = x
self.assertEquals(self.parser.specified_attributes, y)
data = '''\
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<?xml-stylesheet href="stylesheet.css"?>
<!-- comment data -->
<!DOCTYPE quotations SYSTEM "quotations.dtd" [
<!ELEMENT root ANY>
<!NOTATION notation SYSTEM "notation.jpeg">
<!ENTITY acirc "&#226;">
<!ENTITY external_entity SYSTEM "entity.file">
<!ENTITY unparsed_entity SYSTEM "entity.file" NDATA notation>
%unparsed_entity;
]>
<root attr1="value1" attr2="value2&#8000;">
<myns:subelement xmlns:myns="http://www.python.org/namespace">
Contents of subelements
</myns:subelement>
<sub2><![CDATA[contents of CDATA section]]></sub2>
&external_entity;
</root>
'''
# Produce UTF-8 output
class ParseTest(unittest.TestCase):
class Outputter:
def __init__(self):
self.out = []
class Outputter:
def StartElementHandler(self, name, attrs): def StartElementHandler(self, name, attrs):
print 'Start element:\n\t', repr(name), sortdict(attrs) self.out.append('Start element: ' + repr(name) + ' ' +
sortdict(attrs))
def EndElementHandler(self, name): def EndElementHandler(self, name):
print 'End element:\n\t', repr(name) self.out.append('End element: ' + repr(name))
def CharacterDataHandler(self, data): def CharacterDataHandler(self, data):
data = data.strip() data = data.strip()
if data: if data:
print 'Character data:' self.out.append('Character data: ' + repr(data))
print '\t', repr(data)
def ProcessingInstructionHandler(self, target, data): def ProcessingInstructionHandler(self, target, data):
print 'PI:\n\t', repr(target), repr(data) self.out.append('PI: ' + repr(target) + ' ' + repr(data))
def StartNamespaceDeclHandler(self, prefix, uri): def StartNamespaceDeclHandler(self, prefix, uri):
print 'NS decl:\n\t', repr(prefix), repr(uri) self.out.append('NS decl: ' + repr(prefix) + ' ' + repr(uri))
def EndNamespaceDeclHandler(self, prefix): def EndNamespaceDeclHandler(self, prefix):
print 'End of NS decl:\n\t', repr(prefix) self.out.append('End of NS decl: ' + repr(prefix))
def StartCdataSectionHandler(self): def StartCdataSectionHandler(self):
print 'Start of CDATA section' self.out.append('Start of CDATA section')
def EndCdataSectionHandler(self): def EndCdataSectionHandler(self):
print 'End of CDATA section' self.out.append('End of CDATA section')
def CommentHandler(self, text): def CommentHandler(self, text):
print 'Comment:\n\t', repr(text) self.out.append('Comment: ' + repr(text))
def NotationDeclHandler(self, *args): def NotationDeclHandler(self, *args):
name, base, sysid, pubid = args name, base, sysid, pubid = args
print 'Notation declared:', args self.out.append('Notation declared: %s' %(args,))
def UnparsedEntityDeclHandler(self, *args): def UnparsedEntityDeclHandler(self, *args):
entityName, base, systemId, publicId, notationName = args entityName, base, systemId, publicId, notationName = args
print 'Unparsed entity decl:\n\t', args self.out.append('Unparsed entity decl: %s' %(args,))
def NotStandaloneHandler(self, userData): def NotStandaloneHandler(self, userData):
print 'Not standalone' self.out.append('Not standalone')
return 1 return 1
def ExternalEntityRefHandler(self, *args): def ExternalEntityRefHandler(self, *args):
context, base, sysId, pubId = args context, base, sysId, pubId = args
print 'External entity ref:', args[1:] self.out.append('External entity ref: %s' %(args[1:],))
return 1 return 1
def DefaultHandler(self, userData): def DefaultHandler(self, userData):
...@@ -62,35 +118,7 @@ class Outputter: ...@@ -62,35 +118,7 @@ class Outputter:
def DefaultHandlerExpand(self, userData): def DefaultHandlerExpand(self, userData):
pass pass
handler_names = [
def confirm(ok):
if ok:
print "OK."
else:
print "Not OK."
out = Outputter()
parser = expat.ParserCreate(namespace_separator='!')
# Test getting/setting returns_unicode
parser.returns_unicode = 0; confirm(parser.returns_unicode == 0)
parser.returns_unicode = 1; confirm(parser.returns_unicode == 1)
parser.returns_unicode = 2; confirm(parser.returns_unicode == 1)
parser.returns_unicode = 0; confirm(parser.returns_unicode == 0)
# Test getting/setting ordered_attributes
parser.ordered_attributes = 0; confirm(parser.ordered_attributes == 0)
parser.ordered_attributes = 1; confirm(parser.ordered_attributes == 1)
parser.ordered_attributes = 2; confirm(parser.ordered_attributes == 1)
parser.ordered_attributes = 0; confirm(parser.ordered_attributes == 0)
# Test getting/setting specified_attributes
parser.specified_attributes = 0; confirm(parser.specified_attributes == 0)
parser.specified_attributes = 1; confirm(parser.specified_attributes == 1)
parser.specified_attributes = 2; confirm(parser.specified_attributes == 1)
parser.specified_attributes = 0; confirm(parser.specified_attributes == 0)
HANDLER_NAMES = [
'StartElementHandler', 'EndElementHandler', 'StartElementHandler', 'EndElementHandler',
'CharacterDataHandler', 'ProcessingInstructionHandler', 'CharacterDataHandler', 'ProcessingInstructionHandler',
'UnparsedEntityDeclHandler', 'NotationDeclHandler', 'UnparsedEntityDeclHandler', 'NotationDeclHandler',
...@@ -101,133 +129,157 @@ HANDLER_NAMES = [ ...@@ -101,133 +129,157 @@ HANDLER_NAMES = [
#'NotStandaloneHandler', #'NotStandaloneHandler',
'ExternalEntityRefHandler' 'ExternalEntityRefHandler'
] ]
for name in HANDLER_NAMES:
setattr(parser, name, getattr(out, name))
data = '''\
<?xml version="1.0" encoding="iso-8859-1" standalone="no"?>
<?xml-stylesheet href="stylesheet.css"?>
<!-- comment data -->
<!DOCTYPE quotations SYSTEM "quotations.dtd" [
<!ELEMENT root ANY>
<!NOTATION notation SYSTEM "notation.jpeg">
<!ENTITY acirc "&#226;">
<!ENTITY external_entity SYSTEM "entity.file">
<!ENTITY unparsed_entity SYSTEM "entity.file" NDATA notation>
%unparsed_entity;
]>
<root attr1="value1" attr2="value2&#8000;"> def test_utf8(self):
<myns:subelement xmlns:myns="http://www.python.org/namespace">
Contents of subelements
</myns:subelement>
<sub2><![CDATA[contents of CDATA section]]></sub2>
&external_entity;
</root>
'''
# Produce UTF-8 output out = self.Outputter()
parser.returns_unicode = 0 parser = expat.ParserCreate(namespace_separator='!')
try: for name in self.handler_names:
setattr(parser, name, getattr(out, name))
parser.returns_unicode = 0
parser.Parse(data, 1) parser.Parse(data, 1)
except expat.error:
print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)
print '** Line', parser.ErrorLineNumber
print '** Column', parser.ErrorColumnNumber
print '** Byte', parser.ErrorByteIndex
# Try the parse again, this time producing Unicode output
parser = expat.ParserCreate(namespace_separator='!')
parser.returns_unicode = 1
for name in HANDLER_NAMES: # Verify output
op = out.out
self.assertEquals(op[0], 'PI: \'xml-stylesheet\' \'href="stylesheet.css"\'')
self.assertEquals(op[1], "Comment: ' comment data '")
self.assertEquals(op[2], "Notation declared: ('notation', None, 'notation.jpeg', None)")
self.assertEquals(op[3], "Unparsed entity decl: ('unparsed_entity', None, 'entity.file', None, 'notation')")
self.assertEquals(op[4], "Start element: 'root' {'attr1': 'value1', 'attr2': 'value2\\xe1\\xbd\\x80'}")
self.assertEquals(op[5], "NS decl: 'myns' 'http://www.python.org/namespace'")
self.assertEquals(op[6], "Start element: 'http://www.python.org/namespace!subelement' {}")
self.assertEquals(op[7], "Character data: 'Contents of subelements'")
self.assertEquals(op[8], "End element: 'http://www.python.org/namespace!subelement'")
self.assertEquals(op[9], "End of NS decl: 'myns'")
self.assertEquals(op[10], "Start element: 'sub2' {}")
self.assertEquals(op[11], 'Start of CDATA section')
self.assertEquals(op[12], "Character data: 'contents of CDATA section'")
self.assertEquals(op[13], 'End of CDATA section')
self.assertEquals(op[14], "End element: 'sub2'")
self.assertEquals(op[15], "External entity ref: (None, 'entity.file', None)")
self.assertEquals(op[16], "End element: 'root'")
def test_unicode(self):
# Try the parse again, this time producing Unicode output
out = self.Outputter()
parser = expat.ParserCreate(namespace_separator='!')
parser.returns_unicode = 1
for name in self.handler_names:
setattr(parser, name, getattr(out, name)) setattr(parser, name, getattr(out, name))
try:
parser.Parse(data, 1)
except expat.error:
print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode)
print '** Line', parser.ErrorLineNumber
print '** Column', parser.ErrorColumnNumber
print '** Byte', parser.ErrorByteIndex
# Try parsing a file parser.Parse(data, 1)
parser = expat.ParserCreate(namespace_separator='!')
parser.returns_unicode = 1
for name in HANDLER_NAMES: op = out.out
self.assertEquals(op[0], 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'')
self.assertEquals(op[1], "Comment: u' comment data '")
self.assertEquals(op[2], "Notation declared: (u'notation', None, u'notation.jpeg', None)")
self.assertEquals(op[3], "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')")
self.assertEquals(op[4], "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}")
self.assertEquals(op[5], "NS decl: u'myns' u'http://www.python.org/namespace'")
self.assertEquals(op[6], "Start element: u'http://www.python.org/namespace!subelement' {}")
self.assertEquals(op[7], "Character data: u'Contents of subelements'")
self.assertEquals(op[8], "End element: u'http://www.python.org/namespace!subelement'")
self.assertEquals(op[9], "End of NS decl: u'myns'")
self.assertEquals(op[10], "Start element: u'sub2' {}")
self.assertEquals(op[11], 'Start of CDATA section')
self.assertEquals(op[12], "Character data: u'contents of CDATA section'")
self.assertEquals(op[13], 'End of CDATA section')
self.assertEquals(op[14], "End element: u'sub2'")
self.assertEquals(op[15], "External entity ref: (None, u'entity.file', None)")
self.assertEquals(op[16], "End element: u'root'")
def test_parse_file(self):
# Try parsing a file
out = self.Outputter()
parser = expat.ParserCreate(namespace_separator='!')
parser.returns_unicode = 1
for name in self.handler_names:
setattr(parser, name, getattr(out, name)) setattr(parser, name, getattr(out, name))
import StringIO file = StringIO.StringIO(data)
file = StringIO.StringIO(data)
try:
parser.ParseFile(file) parser.ParseFile(file)
except expat.error:
print '** Error', parser.ErrorCode, expat.ErrorString(parser.ErrorCode) op = out.out
print '** Line', parser.ErrorLineNumber self.assertEquals(op[0], 'PI: u\'xml-stylesheet\' u\'href="stylesheet.css"\'')
print '** Column', parser.ErrorColumnNumber self.assertEquals(op[1], "Comment: u' comment data '")
print '** Byte', parser.ErrorByteIndex self.assertEquals(op[2], "Notation declared: (u'notation', None, u'notation.jpeg', None)")
self.assertEquals(op[3], "Unparsed entity decl: (u'unparsed_entity', None, u'entity.file', None, u'notation')")
self.assertEquals(op[4], "Start element: u'root' {u'attr1': u'value1', u'attr2': u'value2\\u1f40'}")
# Tests that make sure we get errors when the namespace_separator value self.assertEquals(op[5], "NS decl: u'myns' u'http://www.python.org/namespace'")
# is illegal, and that we don't for good values: self.assertEquals(op[6], "Start element: u'http://www.python.org/namespace!subelement' {}")
print self.assertEquals(op[7], "Character data: u'Contents of subelements'")
print "Testing constructor for proper handling of namespace_separator values:" self.assertEquals(op[8], "End element: u'http://www.python.org/namespace!subelement'")
expat.ParserCreate() self.assertEquals(op[9], "End of NS decl: u'myns'")
expat.ParserCreate(namespace_separator=None) self.assertEquals(op[10], "Start element: u'sub2' {}")
expat.ParserCreate(namespace_separator=' ') self.assertEquals(op[11], 'Start of CDATA section')
print "Legal values tested o.k." self.assertEquals(op[12], "Character data: u'contents of CDATA section'")
try: self.assertEquals(op[13], 'End of CDATA section')
self.assertEquals(op[14], "End element: u'sub2'")
self.assertEquals(op[15], "External entity ref: (None, u'entity.file', None)")
self.assertEquals(op[16], "End element: u'root'")
class NamespaceSeparatorTest(unittest.TestCase):
def test_legal(self):
# Tests that make sure we get errors when the namespace_separator value
# is illegal, and that we don't for good values:
expat.ParserCreate()
expat.ParserCreate(namespace_separator=None)
expat.ParserCreate(namespace_separator=' ')
def test_illegal(self):
try:
expat.ParserCreate(namespace_separator=42) expat.ParserCreate(namespace_separator=42)
except TypeError, e: self.fail()
print "Caught expected TypeError:" except TypeError, e:
print e self.assertEquals(str(e),
else: 'ParserCreate() argument 2 must be string or None, not int')
print "Failed to catch expected TypeError."
try: try:
expat.ParserCreate(namespace_separator='too long') expat.ParserCreate(namespace_separator='too long')
except ValueError, e: self.fail()
print "Caught expected ValueError:" except ValueError, e:
print e self.assertEquals(str(e),
else: 'namespace_separator must be at most one character, omitted, or None')
print "Failed to catch expected ValueError."
def test_zero_length(self):
# ParserCreate() needs to accept a namespace_separator of zero length # ParserCreate() needs to accept a namespace_separator of zero length
# to satisfy the requirements of RDF applications that are required # to satisfy the requirements of RDF applications that are required
# to simply glue together the namespace URI and the localname. Though # to simply glue together the namespace URI and the localname. Though
# considered a wart of the RDF specifications, it needs to be supported. # considered a wart of the RDF specifications, it needs to be supported.
# #
# See XML-SIG mailing list thread starting with # See XML-SIG mailing list thread starting with
# http://mail.python.org/pipermail/xml-sig/2001-April/005202.html # http://mail.python.org/pipermail/xml-sig/2001-April/005202.html
# #
expat.ParserCreate(namespace_separator='') # too short expat.ParserCreate(namespace_separator='') # too short
# Test the interning machinery.
p = expat.ParserCreate() class InterningTest(unittest.TestCase):
L = [] def test(self):
def collector(name, *args): # Test the interning machinery.
p = expat.ParserCreate()
L = []
def collector(name, *args):
L.append(name) L.append(name)
p.StartElementHandler = collector p.StartElementHandler = collector
p.EndElementHandler = collector p.EndElementHandler = collector
p.Parse("<e> <e/> <e></e> </e>", 1) p.Parse("<e> <e/> <e></e> </e>", 1)
tag = L[0] tag = L[0]
if len(L) != 6: self.assertEquals(len(L), 6)
print "L should only contain 6 entries; found", len(L) for entry in L:
for entry in L: # L should have the same string repeated over and over.
if tag is not entry: self.assertTrue(tag is entry)
print "expected L to contain many references to the same string",
print "(it didn't)"
print "L =", repr(L) class BufferTextTest(unittest.TestCase):
break def setUp(self):
# Tests of the buffer_text attribute.
import sys
class TextCollector:
def __init__(self, parser):
self.stuff = [] self.stuff = []
self.parser = expat.ParserCreate()
self.parser.buffer_text = 1
self.parser.CharacterDataHandler = self.CharacterDataHandler
def check(self, expected, label): def check(self, expected, label):
require(self.stuff == expected, self.assertEquals(self.stuff, expected,
"%s\nstuff = %r\nexpected = %r" "%s\nstuff = %r\nexpected = %r"
% (label, self.stuff, map(unicode, expected))) % (label, self.stuff, map(unicode, expected)))
...@@ -238,9 +290,9 @@ class TextCollector: ...@@ -238,9 +290,9 @@ class TextCollector:
self.stuff.append("<%s>" % name) self.stuff.append("<%s>" % name)
bt = attrs.get("buffer-text") bt = attrs.get("buffer-text")
if bt == "yes": if bt == "yes":
parser.buffer_text = 1 self.parser.buffer_text = 1
elif bt == "no": elif bt == "no":
parser.buffer_text = 0 self.parser.buffer_text = 0
def EndElementHandler(self, name): def EndElementHandler(self, name):
self.stuff.append("</%s>" % name) self.stuff.append("</%s>" % name)
...@@ -248,95 +300,91 @@ class TextCollector: ...@@ -248,95 +300,91 @@ class TextCollector:
def CommentHandler(self, data): def CommentHandler(self, data):
self.stuff.append("<!--%s-->" % data) self.stuff.append("<!--%s-->" % data)
def require(cond, label): def setHandlers(self, handlers=[]):
# similar to confirm(), but no extraneous output for name in handlers:
if not cond: setattr(self.parser, name, getattr(self, name))
raise TestFailed(label)
def setup(handlers=[]): def test_default_to_disabled(self):
parser = expat.ParserCreate() parser = expat.ParserCreate()
require(not parser.buffer_text, self.assertFalse(parser.buffer_text)
"buffer_text not disabled by default")
parser.buffer_text = 1 def test_buffering_enabled(self):
handler = TextCollector(parser) # Make sure buffering is turned on
parser.CharacterDataHandler = handler.CharacterDataHandler self.assertTrue(self.parser.buffer_text)
for name in handlers: self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
setattr(parser, name, getattr(handler, name)) self.assertEquals(self.stuff, ['123'],
return parser, handler
parser, handler = setup()
require(parser.buffer_text,
"text buffering either not acknowledged or not enabled")
parser.Parse("<a>1<b/>2<c/>3</a>", 1)
handler.check(["123"],
"buffered text not properly collapsed") "buffered text not properly collapsed")
# XXX This test exposes more detail of Expat's text chunking than we def test1(self):
# XXX like, but it tests what we need to concisely. # XXX This test exposes more detail of Expat's text chunking than we
parser, handler = setup(["StartElementHandler"]) # XXX like, but it tests what we need to concisely.
parser.Parse("<a>1<b buffer-text='no'/>2\n3<c buffer-text='yes'/>4\n5</a>", 1) self.setHandlers(["StartElementHandler"])
handler.check(["<a>", "1", "<b>", "2", "\n", "3", "<c>", "4\n5"], self.parser.Parse("<a>1<b buffer-text='no'/>2\n3<c buffer-text='yes'/>4\n5</a>", 1)
self.assertEquals(self.stuff,
["<a>", "1", "<b>", "2", "\n", "3", "<c>", "4\n5"],
"buffering control not reacting as expected") "buffering control not reacting as expected")
parser, handler = setup() def test2(self):
parser.Parse("<a>1<b/>&lt;2&gt;<c/>&#32;\n&#x20;3</a>", 1) self.parser.Parse("<a>1<b/>&lt;2&gt;<c/>&#32;\n&#x20;3</a>", 1)
handler.check(["1<2> \n 3"], self.assertEquals(self.stuff, ["1<2> \n 3"],
"buffered text not properly collapsed") "buffered text not properly collapsed")
parser, handler = setup(["StartElementHandler"]) def test3(self):
parser.Parse("<a>1<b/>2<c/>3</a>", 1) self.setHandlers(["StartElementHandler"])
handler.check(["<a>", "1", "<b>", "2", "<c>", "3"], self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
self.assertEquals(self.stuff, ["<a>", "1", "<b>", "2", "<c>", "3"],
"buffered text not properly split") "buffered text not properly split")
parser, handler = setup(["StartElementHandler", "EndElementHandler"]) def test4(self):
parser.CharacterDataHandler = None self.setHandlers(["StartElementHandler", "EndElementHandler"])
parser.Parse("<a>1<b/>2<c/>3</a>", 1) self.parser.CharacterDataHandler = None
handler.check(["<a>", "<b>", "</b>", "<c>", "</c>", "</a>"], self.parser.Parse("<a>1<b/>2<c/>3</a>", 1)
"huh?") self.assertEquals(self.stuff,
["<a>", "<b>", "</b>", "<c>", "</c>", "</a>"])
parser, handler = setup(["StartElementHandler", "EndElementHandler"])
parser.Parse("<a>1<b></b>2<c/>3</a>", 1) def test5(self):
handler.check(["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3", "</a>"], self.setHandlers(["StartElementHandler", "EndElementHandler"])
"huh?") self.parser.Parse("<a>1<b></b>2<c/>3</a>", 1)
self.assertEquals(self.stuff,
parser, handler = setup(["CommentHandler", "EndElementHandler", ["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3", "</a>"])
def test6(self):
self.setHandlers(["CommentHandler", "EndElementHandler",
"StartElementHandler"]) "StartElementHandler"])
parser.Parse("<a>1<b/>2<c></c>345</a> ", 1) self.parser.Parse("<a>1<b/>2<c></c>345</a> ", 1)
handler.check(["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "345", "</a>"], self.assertEquals(self.stuff,
["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "345", "</a>"],
"buffered text not properly split") "buffered text not properly split")
parser, handler = setup(["CommentHandler", "EndElementHandler", def test7(self):
self.setHandlers(["CommentHandler", "EndElementHandler",
"StartElementHandler"]) "StartElementHandler"])
parser.Parse("<a>1<b/>2<c></c>3<!--abc-->4<!--def-->5</a> ", 1) self.parser.Parse("<a>1<b/>2<c></c>3<!--abc-->4<!--def-->5</a> ", 1)
handler.check(["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3", self.assertEquals(self.stuff,
["<a>", "1", "<b>", "</b>", "2", "<c>", "</c>", "3",
"<!--abc-->", "4", "<!--def-->", "5", "</a>"], "<!--abc-->", "4", "<!--def-->", "5", "</a>"],
"buffered text not properly split") "buffered text not properly split")
# Test handling of exception from callback: # Test handling of exception from callback:
def StartElementHandler(name, attrs): class HandlerExceptionTest(unittest.TestCase):
def StartElementHandler(self, name, attrs):
raise RuntimeError(name) raise RuntimeError(name)
parser = expat.ParserCreate() def test(self):
parser.StartElementHandler = StartElementHandler parser = expat.ParserCreate()
parser.StartElementHandler = self.StartElementHandler
try: try:
parser.Parse("<a><b><c/></b></a>", 1) parser.Parse("<a><b><c/></b></a>", 1)
except RuntimeError, e: self.fail()
if e.args[0] != "a": except RuntimeError, e:
print "Expected RuntimeError for element 'a'; found %r" % e.args[0] self.assertEquals(e.args[0], 'a',
else: "Expected RuntimeError for element 'a', but" + \
print "Expected RuntimeError for 'a'" " found %r" % e.args[0])
# Test Current* members:
class PositionTest:
def __init__(self, expected_list, parser):
self.parser = parser
self.parser.StartElementHandler = self.StartElementHandler
self.parser.EndElementHandler = self.EndElementHandler
self.expected_list = expected_list
self.upto = 0
# Test Current* members:
class PositionTest(unittest.TestCase):
def StartElementHandler(self, name, attrs): def StartElementHandler(self, name, attrs):
self.check_pos('s') self.check_pos('s')
...@@ -348,41 +396,54 @@ class PositionTest: ...@@ -348,41 +396,54 @@ class PositionTest:
self.parser.CurrentByteIndex, self.parser.CurrentByteIndex,
self.parser.CurrentLineNumber, self.parser.CurrentLineNumber,
self.parser.CurrentColumnNumber) self.parser.CurrentColumnNumber)
require(self.upto < len(self.expected_list), self.assertTrue(self.upto < len(self.expected_list),
'too many parser events') 'too many parser events')
expected = self.expected_list[self.upto] expected = self.expected_list[self.upto]
require(pos == expected, self.assertEquals(pos, expected,
'expected position %s, got %s' % (expected, pos)) 'Expected position %s, got position %s' %(pos, expected))
self.upto += 1 self.upto += 1
def test(self):
self.parser = expat.ParserCreate()
self.parser.StartElementHandler = self.StartElementHandler
self.parser.EndElementHandler = self.EndElementHandler
self.upto = 0
self.expected_list = [('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2),
('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)]
parser = expat.ParserCreate() xml = '<a>\n <b>\n <c/>\n </b>\n</a>'
handler = PositionTest([('s', 0, 1, 0), ('s', 5, 2, 1), ('s', 11, 3, 2), self.parser.Parse(xml, 1)
('e', 15, 3, 6), ('e', 17, 4, 1), ('e', 22, 5, 0)],
parser)
parser.Parse('''<a>
<b>
<c/>
</b>
</a>''', 1)
def test_parse_only_xml_data(): class sf1296433Test(unittest.TestCase):
def test_parse_only_xml_data(self):
# http://python.org/sf/1296433 # http://python.org/sf/1296433
# #
xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * 1025) xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * 1025)
# this one doesn't crash # this one doesn't crash
#xml = "<?xml version='1.0'?><s>%s</s>" % ('a' * 10000) #xml = "<?xml version='1.0'?><s>%s</s>" % ('a' * 10000)
class SpecificException(Exception):
pass
def handler(text): def handler(text):
raise Exception raise SpecificException
parser = expat.ParserCreate() parser = expat.ParserCreate()
parser.CharacterDataHandler = handler parser.CharacterDataHandler = handler
try: self.assertRaises(Exception, parser.Parse, xml)
parser.Parse(xml)
except:
pass def test_main():
run_unittest(SetAttributeTest,
ParseTest,
NamespaceSeparatorTest,
InterningTest,
BufferTextTest,
HandlerExceptionTest,
PositionTest,
sf1296433Test)
test_parse_only_xml_data() if __name__ == "__main__":
test_main()
...@@ -13,26 +13,66 @@ from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \ ...@@ -13,26 +13,66 @@ from xml.sax.saxutils import XMLGenerator, escape, unescape, quoteattr, \
from xml.sax.expatreader import create_parser from xml.sax.expatreader import create_parser
from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl from xml.sax.xmlreader import InputSource, AttributesImpl, AttributesNSImpl
from cStringIO import StringIO from cStringIO import StringIO
from test.test_support import verify, verbose, TestFailed, findfile from test.test_support import findfile, run_unittest
import unittest
import os import os
# ===== Utilities ns_uri = "http://www.python.org/xml-ns/saxtest/"
tests = 0
failures = []
def confirm(outcome, name):
global tests
tests = tests + 1
if outcome:
if verbose:
print "Passed", name
else:
failures.append(name)
def test_make_parser2(): class XmlTestBase(unittest.TestCase):
try: def verify_empty_attrs(self, attrs):
self.assertRaises(KeyError, attrs.getValue, "attr")
self.assertRaises(KeyError, attrs.getValueByQName, "attr")
self.assertRaises(KeyError, attrs.getNameByQName, "attr")
self.assertRaises(KeyError, attrs.getQNameByName, "attr")
self.assertRaises(KeyError, attrs.__getitem__, "attr")
self.assertEquals(attrs.getLength(), 0)
self.assertEquals(attrs.getNames(), [])
self.assertEquals(attrs.getQNames(), [])
self.assertEquals(len(attrs), 0)
self.assertFalse(attrs.has_key("attr"))
self.assertEquals(attrs.keys(), [])
self.assertEquals(attrs.get("attrs"), None)
self.assertEquals(attrs.get("attrs", 25), 25)
self.assertEquals(attrs.items(), [])
self.assertEquals(attrs.values(), [])
def verify_empty_nsattrs(self, attrs):
self.assertRaises(KeyError, attrs.getValue, (ns_uri, "attr"))
self.assertRaises(KeyError, attrs.getValueByQName, "ns:attr")
self.assertRaises(KeyError, attrs.getNameByQName, "ns:attr")
self.assertRaises(KeyError, attrs.getQNameByName, (ns_uri, "attr"))
self.assertRaises(KeyError, attrs.__getitem__, (ns_uri, "attr"))
self.assertEquals(attrs.getLength(), 0)
self.assertEquals(attrs.getNames(), [])
self.assertEquals(attrs.getQNames(), [])
self.assertEquals(len(attrs), 0)
self.assertFalse(attrs.has_key((ns_uri, "attr")))
self.assertEquals(attrs.keys(), [])
self.assertEquals(attrs.get((ns_uri, "attr")), None)
self.assertEquals(attrs.get((ns_uri, "attr"), 25), 25)
self.assertEquals(attrs.items(), [])
self.assertEquals(attrs.values(), [])
def verify_attrs_wattr(self, attrs):
self.assertEquals(attrs.getLength(), 1)
self.assertEquals(attrs.getNames(), ["attr"])
self.assertEquals(attrs.getQNames(), ["attr"])
self.assertEquals(len(attrs), 1)
self.assertTrue(attrs.has_key("attr"))
self.assertEquals(attrs.keys(), ["attr"])
self.assertEquals(attrs.get("attr"), "val")
self.assertEquals(attrs.get("attr", 25), "val")
self.assertEquals(attrs.items(), [("attr", "val")])
self.assertEquals(attrs.values(), ["val"])
self.assertEquals(attrs.getValue("attr"), "val")
self.assertEquals(attrs.getValueByQName("attr"), "val")
self.assertEquals(attrs.getNameByQName("attr"), "attr")
self.assertEquals(attrs["attr"], "val")
self.assertEquals(attrs.getQNameByName("attr"), "attr")
class MakeParserTest(unittest.TestCase):
def test_make_parser2(self):
# Creating parsers several times in a row should succeed. # Creating parsers several times in a row should succeed.
# Testing this because there have been failures of this kind # Testing this because there have been failures of this kind
# before. # before.
...@@ -48,10 +88,6 @@ def test_make_parser2(): ...@@ -48,10 +88,6 @@ def test_make_parser2():
p = make_parser() p = make_parser()
from xml.sax import make_parser from xml.sax import make_parser
p = make_parser() p = make_parser()
except:
return 0
else:
return p
# =========================================================================== # ===========================================================================
...@@ -60,66 +96,64 @@ def test_make_parser2(): ...@@ -60,66 +96,64 @@ def test_make_parser2():
# #
# =========================================================================== # ===========================================================================
# ===== escape class SaxutilsTest(unittest.TestCase):
# ===== escape
def test_escape_basic(): def test_escape_basic(self):
return escape("Donald Duck & Co") == "Donald Duck &amp; Co" self.assertEquals(escape("Donald Duck & Co"), "Donald Duck &amp; Co")
def test_escape_all(): def test_escape_all(self):
return escape("<Donald Duck & Co>") == "&lt;Donald Duck &amp; Co&gt;" self.assertEquals(escape("<Donald Duck & Co>"),
"&lt;Donald Duck &amp; Co&gt;")
def test_escape_extra(): def test_escape_extra(self):
return escape("Hei p deg", {"" : "&aring;"}) == "Hei p&aring; deg" self.assertEquals(escape("Hei p deg", {"" : "&aring;"}),
"Hei p&aring; deg")
# ===== unescape # ===== unescape
def test_unescape_basic(self):
self.assertEquals(unescape("Donald Duck &amp; Co"), "Donald Duck & Co")
def test_unescape_basic(): def test_unescape_all(self):
return unescape("Donald Duck &amp; Co") == "Donald Duck & Co" self.assertEquals(unescape("&lt;Donald Duck &amp; Co&gt;"),
"<Donald Duck & Co>")
def test_unescape_all(): def test_unescape_extra(self):
return unescape("&lt;Donald Duck &amp; Co&gt;") == "<Donald Duck & Co>" self.assertEquals(unescape("Hei p deg", {"" : "&aring;"}),
"Hei p&aring; deg")
def test_unescape_extra(): def test_unescape_amp_extra(self):
return unescape("Hei p deg", {"" : "&aring;"}) == "Hei p&aring; deg" self.assertEquals(unescape("&amp;foo;", {"&foo;": "splat"}), "&foo;")
def test_unescape_amp_extra(): # ===== quoteattr
return unescape("&amp;foo;", {"&foo;": "splat"}) == "&foo;" def test_quoteattr_basic(self):
self.assertEquals(quoteattr("Donald Duck & Co"),
'"Donald Duck &amp; Co"')
# ===== quoteattr def test_single_quoteattr(self):
self.assertEquals(quoteattr('Includes "double" quotes'),
'\'Includes "double" quotes\'')
def test_quoteattr_basic(): def test_double_quoteattr(self):
return quoteattr("Donald Duck & Co") == '"Donald Duck &amp; Co"' self.assertEquals(quoteattr("Includes 'single' quotes"),
"\"Includes 'single' quotes\"")
def test_single_quoteattr(): def test_single_double_quoteattr(self):
return (quoteattr('Includes "double" quotes') self.assertEquals(quoteattr("Includes 'single' and \"double\" quotes"),
== '\'Includes "double" quotes\'') "\"Includes 'single' and &quot;double&quot; quotes\"")
def test_double_quoteattr(): # ===== make_parser
return (quoteattr("Includes 'single' quotes") def test_make_parser(self):
== "\"Includes 'single' quotes\"")
def test_single_double_quoteattr():
return (quoteattr("Includes 'single' and \"double\" quotes")
== "\"Includes 'single' and &quot;double&quot; quotes\"")
# ===== make_parser
def test_make_parser():
try:
# Creating a parser should succeed - it should fall back # Creating a parser should succeed - it should fall back
# to the expatreader # to the expatreader
p = make_parser(['xml.parsers.no_such_parser']) p = make_parser(['xml.parsers.no_such_parser'])
except:
return 0
else:
return p
# ===== XMLGenerator # ===== XMLGenerator
start = '<?xml version="1.0" encoding="iso-8859-1"?>\n' start = '<?xml version="1.0" encoding="iso-8859-1"?>\n'
def test_xmlgen_basic(): class XmlgenTest(unittest.TestCase):
def test_xmlgen_basic(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
gen.startDocument() gen.startDocument()
...@@ -127,9 +161,9 @@ def test_xmlgen_basic(): ...@@ -127,9 +161,9 @@ def test_xmlgen_basic():
gen.endElement("doc") gen.endElement("doc")
gen.endDocument() gen.endDocument()
return result.getvalue() == start + "<doc></doc>" self.assertEquals(result.getvalue(), start + "<doc></doc>")
def test_xmlgen_content(): def test_xmlgen_content(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
...@@ -139,9 +173,9 @@ def test_xmlgen_content(): ...@@ -139,9 +173,9 @@ def test_xmlgen_content():
gen.endElement("doc") gen.endElement("doc")
gen.endDocument() gen.endDocument()
return result.getvalue() == start + "<doc>huhei</doc>" self.assertEquals(result.getvalue(), start + "<doc>huhei</doc>")
def test_xmlgen_pi(): def test_xmlgen_pi(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
...@@ -151,9 +185,9 @@ def test_xmlgen_pi(): ...@@ -151,9 +185,9 @@ def test_xmlgen_pi():
gen.endElement("doc") gen.endElement("doc")
gen.endDocument() gen.endDocument()
return result.getvalue() == start + "<?test data?><doc></doc>" self.assertEquals(result.getvalue(), start + "<?test data?><doc></doc>")
def test_xmlgen_content_escape(): def test_xmlgen_content_escape(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
...@@ -163,9 +197,10 @@ def test_xmlgen_content_escape(): ...@@ -163,9 +197,10 @@ def test_xmlgen_content_escape():
gen.endElement("doc") gen.endElement("doc")
gen.endDocument() gen.endDocument()
return result.getvalue() == start + "<doc>&lt;huhei&amp;</doc>" self.assertEquals(result.getvalue(),
start + "<doc>&lt;huhei&amp;</doc>")
def test_xmlgen_attr_escape(): def test_xmlgen_attr_escape(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
...@@ -180,11 +215,12 @@ def test_xmlgen_attr_escape(): ...@@ -180,11 +215,12 @@ def test_xmlgen_attr_escape():
gen.endElement("doc") gen.endElement("doc")
gen.endDocument() gen.endDocument()
return result.getvalue() == start + ("<doc a='\"'><e a=\"'\"></e>" self.assertEquals(result.getvalue(), start +
("<doc a='\"'><e a=\"'\"></e>"
"<e a=\"'&quot;\"></e>" "<e a=\"'&quot;\"></e>"
"<e a=\"&#10;&#13;&#9;\"></e></doc>") "<e a=\"&#10;&#13;&#9;\"></e></doc>"))
def test_xmlgen_ignorable(): def test_xmlgen_ignorable(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
...@@ -194,11 +230,9 @@ def test_xmlgen_ignorable(): ...@@ -194,11 +230,9 @@ def test_xmlgen_ignorable():
gen.endElement("doc") gen.endElement("doc")
gen.endDocument() gen.endDocument()
return result.getvalue() == start + "<doc> </doc>" self.assertEquals(result.getvalue(), start + "<doc> </doc>")
ns_uri = "http://www.python.org/xml-ns/saxtest/"
def test_xmlgen_ns(): def test_xmlgen_ns(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
...@@ -212,11 +246,11 @@ def test_xmlgen_ns(): ...@@ -212,11 +246,11 @@ def test_xmlgen_ns():
gen.endPrefixMapping("ns1") gen.endPrefixMapping("ns1")
gen.endDocument() gen.endDocument()
return result.getvalue() == start + \ self.assertEquals(result.getvalue(), start + \
('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' % ('<ns1:doc xmlns:ns1="%s"><udoc></udoc></ns1:doc>' %
ns_uri) ns_uri))
def test_1463026_1(): def test_1463026_1(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
...@@ -225,9 +259,9 @@ def test_1463026_1(): ...@@ -225,9 +259,9 @@ def test_1463026_1():
gen.endElementNS((None, 'a'), 'a') gen.endElementNS((None, 'a'), 'a')
gen.endDocument() gen.endDocument()
return result.getvalue() == start+'<a b="c"></a>' self.assertEquals(result.getvalue(), start+'<a b="c"></a>')
def test_1463026_2(): def test_1463026_2(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
...@@ -238,9 +272,9 @@ def test_1463026_2(): ...@@ -238,9 +272,9 @@ def test_1463026_2():
gen.endPrefixMapping(None) gen.endPrefixMapping(None)
gen.endDocument() gen.endDocument()
return result.getvalue() == start+'<a xmlns="qux"></a>' self.assertEquals(result.getvalue(), start+'<a xmlns="qux"></a>')
def test_1463026_3(): def test_1463026_3(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
...@@ -251,11 +285,12 @@ def test_1463026_3(): ...@@ -251,11 +285,12 @@ def test_1463026_3():
gen.endPrefixMapping('my') gen.endPrefixMapping('my')
gen.endDocument() gen.endDocument()
return result.getvalue() == start+'<my:a xmlns:my="qux" b="c"></my:a>' self.assertEquals(result.getvalue(),
start+'<my:a xmlns:my="qux" b="c"></my:a>')
# ===== Xmlfilterbase
def test_filter_basic(): class XMLFilterBaseTest(unittest.TestCase):
def test_filter_basic(self):
result = StringIO() result = StringIO()
gen = XMLGenerator(result) gen = XMLGenerator(result)
filter = XMLFilterBase() filter = XMLFilterBase()
...@@ -268,7 +303,7 @@ def test_filter_basic(): ...@@ -268,7 +303,7 @@ def test_filter_basic():
filter.endElement("doc") filter.endElement("doc")
filter.endDocument() filter.endDocument()
return result.getvalue() == start + "<doc>content </doc>" self.assertEquals(result.getvalue(), start + "<doc>content </doc>")
# =========================================================================== # ===========================================================================
# #
...@@ -276,9 +311,13 @@ def test_filter_basic(): ...@@ -276,9 +311,13 @@ def test_filter_basic():
# #
# =========================================================================== # ===========================================================================
# ===== XMLReader support xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read()
class ExpatReaderTest(XmlTestBase):
# ===== XMLReader support
def test_expat_file(): def test_expat_file(self):
parser = create_parser() parser = create_parser()
result = StringIO() result = StringIO()
xmlgen = XMLGenerator(result) xmlgen = XMLGenerator(result)
...@@ -286,11 +325,11 @@ def test_expat_file(): ...@@ -286,11 +325,11 @@ def test_expat_file():
parser.setContentHandler(xmlgen) parser.setContentHandler(xmlgen)
parser.parse(open(findfile("test"+os.extsep+"xml"))) parser.parse(open(findfile("test"+os.extsep+"xml")))
return result.getvalue() == xml_test_out self.assertEquals(result.getvalue(), xml_test_out)
# ===== DTDHandler support # ===== DTDHandler support
class TestDTDHandler: class TestDTDHandler:
def __init__(self): def __init__(self):
self._notations = [] self._notations = []
...@@ -302,9 +341,9 @@ class TestDTDHandler: ...@@ -302,9 +341,9 @@ class TestDTDHandler:
def unparsedEntityDecl(self, name, publicId, systemId, ndata): def unparsedEntityDecl(self, name, publicId, systemId, ndata):
self._entities.append((name, publicId, systemId, ndata)) self._entities.append((name, publicId, systemId, ndata))
def test_expat_dtdhandler(): def test_expat_dtdhandler(self):
parser = create_parser() parser = create_parser()
handler = TestDTDHandler() handler = self.TestDTDHandler()
parser.setDTDHandler(handler) parser.setDTDHandler(handler)
parser.feed('<!DOCTYPE doc [\n') parser.feed('<!DOCTYPE doc [\n')
...@@ -314,21 +353,22 @@ def test_expat_dtdhandler(): ...@@ -314,21 +353,22 @@ def test_expat_dtdhandler():
parser.feed('<doc></doc>') parser.feed('<doc></doc>')
parser.close() parser.close()
return handler._notations == [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)] and \ self.assertEquals(handler._notations,
handler._entities == [("img", None, "expat.gif", "GIF")] [("GIF", "-//CompuServe//NOTATION Graphics Interchange Format 89a//EN", None)])
self.assertEquals(handler._entities, [("img", None, "expat.gif", "GIF")])
# ===== EntityResolver support # ===== EntityResolver support
class TestEntityResolver: class TestEntityResolver:
def resolveEntity(self, publicId, systemId): def resolveEntity(self, publicId, systemId):
inpsrc = InputSource() inpsrc = InputSource()
inpsrc.setByteStream(StringIO("<entity/>")) inpsrc.setByteStream(StringIO("<entity/>"))
return inpsrc return inpsrc
def test_expat_entityresolver(): def test_expat_entityresolver(self):
parser = create_parser() parser = create_parser()
parser.setEntityResolver(TestEntityResolver()) parser.setEntityResolver(self.TestEntityResolver())
result = StringIO() result = StringIO()
parser.setContentHandler(XMLGenerator(result)) parser.setContentHandler(XMLGenerator(result))
...@@ -338,11 +378,12 @@ def test_expat_entityresolver(): ...@@ -338,11 +378,12 @@ def test_expat_entityresolver():
parser.feed('<doc>&test;</doc>') parser.feed('<doc>&test;</doc>')
parser.close() parser.close()
return result.getvalue() == start + "<doc><entity></entity></doc>" self.assertEquals(result.getvalue(), start +
"<doc><entity></entity></doc>")
# ===== Attributes support # ===== Attributes support
class AttrGatherer(ContentHandler): class AttrGatherer(ContentHandler):
def startElement(self, name, attrs): def startElement(self, name, attrs):
self._attrs = attrs self._attrs = attrs
...@@ -350,39 +391,39 @@ class AttrGatherer(ContentHandler): ...@@ -350,39 +391,39 @@ class AttrGatherer(ContentHandler):
def startElementNS(self, name, qname, attrs): def startElementNS(self, name, qname, attrs):
self._attrs = attrs self._attrs = attrs
def test_expat_attrs_empty(): def test_expat_attrs_empty(self):
parser = create_parser() parser = create_parser()
gather = AttrGatherer() gather = self.AttrGatherer()
parser.setContentHandler(gather) parser.setContentHandler(gather)
parser.feed("<doc/>") parser.feed("<doc/>")
parser.close() parser.close()
return verify_empty_attrs(gather._attrs) self.verify_empty_attrs(gather._attrs)
def test_expat_attrs_wattr(): def test_expat_attrs_wattr(self):
parser = create_parser() parser = create_parser()
gather = AttrGatherer() gather = self.AttrGatherer()
parser.setContentHandler(gather) parser.setContentHandler(gather)
parser.feed("<doc attr='val'/>") parser.feed("<doc attr='val'/>")
parser.close() parser.close()
return verify_attrs_wattr(gather._attrs) self.verify_attrs_wattr(gather._attrs)
def test_expat_nsattrs_empty(): def test_expat_nsattrs_empty(self):
parser = create_parser(1) parser = create_parser(1)
gather = AttrGatherer() gather = self.AttrGatherer()
parser.setContentHandler(gather) parser.setContentHandler(gather)
parser.feed("<doc/>") parser.feed("<doc/>")
parser.close() parser.close()
return verify_empty_nsattrs(gather._attrs) self.verify_empty_nsattrs(gather._attrs)
def test_expat_nsattrs_wattr(): def test_expat_nsattrs_wattr(self):
parser = create_parser(1) parser = create_parser(1)
gather = AttrGatherer() gather = self.AttrGatherer()
parser.setContentHandler(gather) parser.setContentHandler(gather)
parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri) parser.feed("<doc xmlns:ns='%s' ns:attr='val'/>" % ns_uri)
...@@ -390,24 +431,22 @@ def test_expat_nsattrs_wattr(): ...@@ -390,24 +431,22 @@ def test_expat_nsattrs_wattr():
attrs = gather._attrs attrs = gather._attrs
return attrs.getLength() == 1 and \ self.assertEquals(attrs.getLength(), 1)
attrs.getNames() == [(ns_uri, "attr")] and \ self.assertEquals(attrs.getNames(), [(ns_uri, "attr")])
(attrs.getQNames() == [] or attrs.getQNames() == ["ns:attr"]) and \ self.assertTrue((attrs.getQNames() == [] or
len(attrs) == 1 and \ attrs.getQNames() == ["ns:attr"]))
attrs.has_key((ns_uri, "attr")) and \ self.assertEquals(len(attrs), 1)
attrs.keys() == [(ns_uri, "attr")] and \ self.assertTrue(attrs.has_key((ns_uri, "attr")))
attrs.get((ns_uri, "attr")) == "val" and \ self.assertEquals(attrs.get((ns_uri, "attr")), "val")
attrs.get((ns_uri, "attr"), 25) == "val" and \ self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val")
attrs.items() == [((ns_uri, "attr"), "val")] and \ self.assertEquals(attrs.items(), [((ns_uri, "attr"), "val")])
attrs.values() == ["val"] and \ self.assertEquals(attrs.values(), ["val"])
attrs.getValue((ns_uri, "attr")) == "val" and \ self.assertEquals(attrs.getValue((ns_uri, "attr")), "val")
attrs[(ns_uri, "attr")] == "val" self.assertEquals(attrs[(ns_uri, "attr")], "val")
# ===== InputSource support # ===== InputSource support
xml_test_out = open(findfile("test"+os.extsep+"xml"+os.extsep+"out")).read() def test_expat_inpsource_filename(self):
def test_expat_inpsource_filename():
parser = create_parser() parser = create_parser()
result = StringIO() result = StringIO()
xmlgen = XMLGenerator(result) xmlgen = XMLGenerator(result)
...@@ -415,9 +454,9 @@ def test_expat_inpsource_filename(): ...@@ -415,9 +454,9 @@ def test_expat_inpsource_filename():
parser.setContentHandler(xmlgen) parser.setContentHandler(xmlgen)
parser.parse(findfile("test"+os.extsep+"xml")) parser.parse(findfile("test"+os.extsep+"xml"))
return result.getvalue() == xml_test_out self.assertEquals(result.getvalue(), xml_test_out)
def test_expat_inpsource_sysid(): def test_expat_inpsource_sysid(self):
parser = create_parser() parser = create_parser()
result = StringIO() result = StringIO()
xmlgen = XMLGenerator(result) xmlgen = XMLGenerator(result)
...@@ -425,9 +464,9 @@ def test_expat_inpsource_sysid(): ...@@ -425,9 +464,9 @@ def test_expat_inpsource_sysid():
parser.setContentHandler(xmlgen) parser.setContentHandler(xmlgen)
parser.parse(InputSource(findfile("test"+os.extsep+"xml"))) parser.parse(InputSource(findfile("test"+os.extsep+"xml")))
return result.getvalue() == xml_test_out self.assertEquals(result.getvalue(), xml_test_out)
def test_expat_inpsource_stream(): def test_expat_inpsource_stream(self):
parser = create_parser() parser = create_parser()
result = StringIO() result = StringIO()
xmlgen = XMLGenerator(result) xmlgen = XMLGenerator(result)
...@@ -437,11 +476,11 @@ def test_expat_inpsource_stream(): ...@@ -437,11 +476,11 @@ def test_expat_inpsource_stream():
inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml"))) inpsrc.setByteStream(open(findfile("test"+os.extsep+"xml")))
parser.parse(inpsrc) parser.parse(inpsrc)
return result.getvalue() == xml_test_out self.assertEquals(result.getvalue(), xml_test_out)
# ===== IncrementalParser support # ===== IncrementalParser support
def test_expat_incremental(): def test_expat_incremental(self):
result = StringIO() result = StringIO()
xmlgen = XMLGenerator(result) xmlgen = XMLGenerator(result)
parser = create_parser() parser = create_parser()
...@@ -451,9 +490,9 @@ def test_expat_incremental(): ...@@ -451,9 +490,9 @@ def test_expat_incremental():
parser.feed("</doc>") parser.feed("</doc>")
parser.close() parser.close()
return result.getvalue() == start + "<doc></doc>" self.assertEquals(result.getvalue(), start + "<doc></doc>")
def test_expat_incremental_reset(): def test_expat_incremental_reset(self):
result = StringIO() result = StringIO()
xmlgen = XMLGenerator(result) xmlgen = XMLGenerator(result)
parser = create_parser() parser = create_parser()
...@@ -472,11 +511,11 @@ def test_expat_incremental_reset(): ...@@ -472,11 +511,11 @@ def test_expat_incremental_reset():
parser.feed("</doc>") parser.feed("</doc>")
parser.close() parser.close()
return result.getvalue() == start + "<doc>text</doc>" self.assertEquals(result.getvalue(), start + "<doc>text</doc>")
# ===== Locator support # ===== Locator support
def test_expat_locator_noinfo(): def test_expat_locator_noinfo(self):
result = StringIO() result = StringIO()
xmlgen = XMLGenerator(result) xmlgen = XMLGenerator(result)
parser = create_parser() parser = create_parser()
...@@ -486,19 +525,19 @@ def test_expat_locator_noinfo(): ...@@ -486,19 +525,19 @@ def test_expat_locator_noinfo():
parser.feed("</doc>") parser.feed("</doc>")
parser.close() parser.close()
return parser.getSystemId() is None and \ self.assertEquals(parser.getSystemId(), None)
parser.getPublicId() is None and \ self.assertEquals(parser.getPublicId(), None)
parser.getLineNumber() == 1 self.assertEquals(parser.getLineNumber(), 1)
def test_expat_locator_withinfo(): def test_expat_locator_withinfo(self):
result = StringIO() result = StringIO()
xmlgen = XMLGenerator(result) xmlgen = XMLGenerator(result)
parser = create_parser() parser = create_parser()
parser.setContentHandler(xmlgen) parser.setContentHandler(xmlgen)
parser.parse(findfile("test.xml")) parser.parse(findfile("test.xml"))
return parser.getSystemId() == findfile("test.xml") and \ self.assertEquals(parser.getSystemId(), findfile("test.xml"))
parser.getPublicId() is None self.assertEquals(parser.getPublicId(), None)
# =========================================================================== # ===========================================================================
...@@ -507,7 +546,8 @@ def test_expat_locator_withinfo(): ...@@ -507,7 +546,8 @@ def test_expat_locator_withinfo():
# #
# =========================================================================== # ===========================================================================
def test_expat_inpsource_location(): class ErrorReportingTest(unittest.TestCase):
def test_expat_inpsource_location(self):
parser = create_parser() parser = create_parser()
parser.setContentHandler(ContentHandler()) # do nothing parser.setContentHandler(ContentHandler()) # do nothing
source = InputSource() source = InputSource()
...@@ -516,39 +556,34 @@ def test_expat_inpsource_location(): ...@@ -516,39 +556,34 @@ def test_expat_inpsource_location():
source.setSystemId(name) source.setSystemId(name)
try: try:
parser.parse(source) parser.parse(source)
self.fail()
except SAXException, e: except SAXException, e:
return e.getSystemId() == name self.assertEquals(e.getSystemId(), name)
def test_expat_incomplete(): def test_expat_incomplete(self):
parser = create_parser() parser = create_parser()
parser.setContentHandler(ContentHandler()) # do nothing parser.setContentHandler(ContentHandler()) # do nothing
try: self.assertRaises(SAXParseException, parser.parse, StringIO("<foo>"))
parser.parse(StringIO("<foo>"))
except SAXParseException:
return 1 # ok, error found
else:
return 0
def test_sax_parse_exception_str(): def test_sax_parse_exception_str(self):
# pass various values from a locator to the SAXParseException to # pass various values from a locator to the SAXParseException to
# make sure that the __str__() doesn't fall apart when None is # make sure that the __str__() doesn't fall apart when None is
# passed instead of an integer line and column number # passed instead of an integer line and column number
# #
# use "normal" values for the locator: # use "normal" values for the locator:
str(SAXParseException("message", None, str(SAXParseException("message", None,
DummyLocator(1, 1))) self.DummyLocator(1, 1)))
# use None for the line number: # use None for the line number:
str(SAXParseException("message", None, str(SAXParseException("message", None,
DummyLocator(None, 1))) self.DummyLocator(None, 1)))
# use None for the column number: # use None for the column number:
str(SAXParseException("message", None, str(SAXParseException("message", None,
DummyLocator(1, None))) self.DummyLocator(1, None)))
# use None for both: # use None for both:
str(SAXParseException("message", None, str(SAXParseException("message", None,
DummyLocator(None, None))) self.DummyLocator(None, None)))
return 1
class DummyLocator: class DummyLocator:
def __init__(self, lineno, colno): def __init__(self, lineno, colno):
self._lineno = lineno self._lineno = lineno
self._colno = colno self._colno = colno
...@@ -571,167 +606,63 @@ class DummyLocator: ...@@ -571,167 +606,63 @@ class DummyLocator:
# #
# =========================================================================== # ===========================================================================
# ===== AttributesImpl class XmlReaderTest(XmlTestBase):
def verify_empty_attrs(attrs):
try:
attrs.getValue("attr")
gvk = 0
except KeyError:
gvk = 1
try: # ===== AttributesImpl
attrs.getValueByQName("attr") def test_attrs_empty(self):
gvqk = 0 self.verify_empty_attrs(AttributesImpl({}))
except KeyError:
gvqk = 1
try: def test_attrs_wattr(self):
attrs.getNameByQName("attr") self.verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
gnqk = 0
except KeyError:
gnqk = 1
try: def test_nsattrs_empty(self):
attrs.getQNameByName("attr") self.verify_empty_nsattrs(AttributesNSImpl({}, {}))
gqnk = 0
except KeyError:
gqnk = 1
try: def test_nsattrs_wattr(self):
attrs["attr"]
gik = 0
except KeyError:
gik = 1
return attrs.getLength() == 0 and \
attrs.getNames() == [] and \
attrs.getQNames() == [] and \
len(attrs) == 0 and \
not attrs.has_key("attr") and \
attrs.keys() == [] and \
attrs.get("attrs") is None and \
attrs.get("attrs", 25) == 25 and \
attrs.items() == [] and \
attrs.values() == [] and \
gvk and gvqk and gnqk and gik and gqnk
def verify_attrs_wattr(attrs):
return attrs.getLength() == 1 and \
attrs.getNames() == ["attr"] and \
attrs.getQNames() == ["attr"] and \
len(attrs) == 1 and \
attrs.has_key("attr") and \
attrs.keys() == ["attr"] and \
attrs.get("attr") == "val" and \
attrs.get("attr", 25) == "val" and \
attrs.items() == [("attr", "val")] and \
attrs.values() == ["val"] and \
attrs.getValue("attr") == "val" and \
attrs.getValueByQName("attr") == "val" and \
attrs.getNameByQName("attr") == "attr" and \
attrs["attr"] == "val" and \
attrs.getQNameByName("attr") == "attr"
def test_attrs_empty():
return verify_empty_attrs(AttributesImpl({}))
def test_attrs_wattr():
return verify_attrs_wattr(AttributesImpl({"attr" : "val"}))
# ===== AttributesImpl
def verify_empty_nsattrs(attrs):
try:
attrs.getValue((ns_uri, "attr"))
gvk = 0
except KeyError:
gvk = 1
try:
attrs.getValueByQName("ns:attr")
gvqk = 0
except KeyError:
gvqk = 1
try:
attrs.getNameByQName("ns:attr")
gnqk = 0
except KeyError:
gnqk = 1
try:
attrs.getQNameByName((ns_uri, "attr"))
gqnk = 0
except KeyError:
gqnk = 1
try:
attrs[(ns_uri, "attr")]
gik = 0
except KeyError:
gik = 1
return attrs.getLength() == 0 and \
attrs.getNames() == [] and \
attrs.getQNames() == [] and \
len(attrs) == 0 and \
not attrs.has_key((ns_uri, "attr")) and \
attrs.keys() == [] and \
attrs.get((ns_uri, "attr")) is None and \
attrs.get((ns_uri, "attr"), 25) == 25 and \
attrs.items() == [] and \
attrs.values() == [] and \
gvk and gvqk and gnqk and gik and gqnk
def test_nsattrs_empty():
return verify_empty_nsattrs(AttributesNSImpl({}, {}))
def test_nsattrs_wattr():
attrs = AttributesNSImpl({(ns_uri, "attr") : "val"}, attrs = AttributesNSImpl({(ns_uri, "attr") : "val"},
{(ns_uri, "attr") : "ns:attr"}) {(ns_uri, "attr") : "ns:attr"})
return attrs.getLength() == 1 and \ self.assertEquals(attrs.getLength(), 1)
attrs.getNames() == [(ns_uri, "attr")] and \ self.assertEquals(attrs.getNames(), [(ns_uri, "attr")])
attrs.getQNames() == ["ns:attr"] and \ self.assertEquals(attrs.getQNames(), ["ns:attr"])
len(attrs) == 1 and \ self.assertEquals(len(attrs), 1)
attrs.has_key((ns_uri, "attr")) and \ self.assertTrue(attrs.has_key((ns_uri, "attr")))
attrs.keys() == [(ns_uri, "attr")] and \ self.assertEquals(attrs.keys(), [(ns_uri, "attr")])
attrs.get((ns_uri, "attr")) == "val" and \ self.assertEquals(attrs.get((ns_uri, "attr")), "val")
attrs.get((ns_uri, "attr"), 25) == "val" and \ self.assertEquals(attrs.get((ns_uri, "attr"), 25), "val")
attrs.items() == [((ns_uri, "attr"), "val")] and \ self.assertEquals(attrs.items(), [((ns_uri, "attr"), "val")])
attrs.values() == ["val"] and \ self.assertEquals(attrs.values(), ["val"])
attrs.getValue((ns_uri, "attr")) == "val" and \ self.assertEquals(attrs.getValue((ns_uri, "attr")), "val")
attrs.getValueByQName("ns:attr") == "val" and \ self.assertEquals(attrs.getValueByQName("ns:attr"), "val")
attrs.getNameByQName("ns:attr") == (ns_uri, "attr") and \ self.assertEquals(attrs.getNameByQName("ns:attr"), (ns_uri, "attr"))
attrs[(ns_uri, "attr")] == "val" and \ self.assertEquals(attrs[(ns_uri, "attr")], "val")
attrs.getQNameByName((ns_uri, "attr")) == "ns:attr" self.assertEquals(attrs.getQNameByName((ns_uri, "attr")), "ns:attr")
# During the development of Python 2.5, an attempt to move the "xml" # During the development of Python 2.5, an attempt to move the "xml"
# package implementation to a new package ("xmlcore") proved painful. # package implementation to a new package ("xmlcore") proved painful.
# The goal of this change was to allow applications to be able to # The goal of this change was to allow applications to be able to
# obtain and rely on behavior in the standard library implementation # obtain and rely on behavior in the standard library implementation
# of the XML support without needing to be concerned about the # of the XML support without needing to be concerned about the
# availability of the PyXML implementation. # availability of the PyXML implementation.
# #
# While the existing import hackery in Lib/xml/__init__.py can cause # While the existing import hackery in Lib/xml/__init__.py can cause
# PyXML's _xmlpus package to supplant the "xml" package, that only # PyXML's _xmlpus package to supplant the "xml" package, that only
# works because either implementation uses the "xml" package name for # works because either implementation uses the "xml" package name for
# imports. # imports.
# #
# The move resulted in a number of problems related to the fact that # The move resulted in a number of problems related to the fact that
# the import machinery's "package context" is based on the name that's # the import machinery's "package context" is based on the name that's
# being imported rather than the __name__ of the actual package # being imported rather than the __name__ of the actual package
# containment; it wasn't possible for the "xml" package to be replaced # containment; it wasn't possible for the "xml" package to be replaced
# by a simple module that indirected imports to the "xmlcore" package. # by a simple module that indirected imports to the "xmlcore" package.
# #
# The following two tests exercised bugs that were introduced in that # The following two tests exercised bugs that were introduced in that
# attempt. Keeping these tests around will help detect problems with # attempt. Keeping these tests around will help detect problems with
# other attempts to provide reliable access to the standard library's # other attempts to provide reliable access to the standard library's
# implementation of the XML support. # implementation of the XML support.
def test_sf_1511497(): def test_sf_1511497(self):
# Bug report: http://www.python.org/sf/1511497 # Bug report: http://www.python.org/sf/1511497
import sys import sys
old_modules = sys.modules.copy() old_modules = sys.modules.copy()
...@@ -741,48 +672,25 @@ def test_sf_1511497(): ...@@ -741,48 +672,25 @@ def test_sf_1511497():
try: try:
import xml.sax.expatreader import xml.sax.expatreader
module = xml.sax.expatreader module = xml.sax.expatreader
return module.__name__ == "xml.sax.expatreader" self.assertEquals(module.__name__, "xml.sax.expatreader")
finally: finally:
sys.modules.update(old_modules) sys.modules.update(old_modules)
def test_sf_1513611(): def test_sf_1513611(self):
# Bug report: http://www.python.org/sf/1513611 # Bug report: http://www.python.org/sf/1513611
sio = StringIO("invalid") sio = StringIO("invalid")
parser = make_parser() parser = make_parser()
from xml.sax import SAXParseException from xml.sax import SAXParseException
try: self.assertRaises(SAXParseException, parser.parse, sio)
parser.parse(sio)
except SAXParseException:
return True
else:
return False
# ===== Main program
def make_test_output(): def unittest_main():
parser = create_parser() run_unittest(MakeParserTest,
result = StringIO() SaxutilsTest,
xmlgen = XMLGenerator(result) XmlgenTest,
ExpatReaderTest,
parser.setContentHandler(xmlgen) ErrorReportingTest,
parser.parse(findfile("test"+os.extsep+"xml")) XmlReaderTest)
outf = open(findfile("test"+os.extsep+"xml"+os.extsep+"out"), "w") if __name__ == "__main__":
outf.write(result.getvalue()) unittest_main()
outf.close()
items = locals().items()
items.sort()
for (name, value) in items:
if name[ : 5] == "test_":
confirm(value(), name)
# We delete the items variable so that the assignment to items above
# doesn't pick up the old value of items (which messes with attempts
# to find reference leaks).
del items
if verbose:
print "%d tests, %d failures" % (tests, len(failures))
if failures:
raise TestFailed("%d of %d tests failed: %s"
% (len(failures), tests, ", ".join(failures)))
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment