# test for xml.dom.minidom
from StringIO
import StringIO
from test
.test_support
import verbose
from xml
.dom
.minidom
import parse
, Node
, Document
, parseString
from xml
.dom
.minidom
import getDOMImplementation
if __name__
== "__main__":
tstfile
= os
.path
.join(os
.path
.dirname(base
), "test"+os
.extsep
+"xml")
def confirm(test
, testname
= "Test"):
print "Failed " + testname
dom
= parse(StringIO(open(tstfile
).read()))
confirm(isinstance(dom
,Document
))
def testGetElementsByTagName():
confirm(dom
.getElementsByTagName("LI") == \
dom
.documentElement
.getElementsByTagName("LI"))
dom
= parseString("<doc><foo/></doc>")
root
= dom
.documentElement
elem
= root
.childNodes
[0]
nelem
= dom
.createElement("element")
root
.insertBefore(nelem
, elem
)
confirm(len(root
.childNodes
) == 2
and root
.childNodes
.length
== 2
and root
.childNodes
[0] is nelem
and root
.childNodes
.item(0) is nelem
and root
.childNodes
[1] is elem
and root
.childNodes
.item(1) is elem
and root
.firstChild
is nelem
and root
.lastChild
is elem
and root
.toxml() == "<doc><element/><foo/></doc>"
, "testInsertBefore -- node properly placed in tree")
nelem
= dom
.createElement("element")
root
.insertBefore(nelem
, None)
confirm(len(root
.childNodes
) == 3
and root
.childNodes
.length
== 3
and root
.childNodes
[1] is elem
and root
.childNodes
.item(1) is elem
and root
.childNodes
[2] is nelem
and root
.childNodes
.item(2) is nelem
and root
.lastChild
is nelem
and nelem
.previousSibling
is elem
and root
.toxml() == "<doc><element/><foo/><element/></doc>"
, "testInsertBefore -- node properly placed in tree")
nelem2
= dom
.createElement("bar")
root
.insertBefore(nelem2
, nelem
)
confirm(len(root
.childNodes
) == 4
and root
.childNodes
.length
== 4
and root
.childNodes
[2] is nelem2
and root
.childNodes
.item(2) is nelem2
and root
.childNodes
[3] is nelem
and root
.childNodes
.item(3) is nelem
and nelem2
.nextSibling
is nelem
and nelem
.previousSibling
is nelem2
and root
.toxml() == "<doc><element/><foo/><bar/><element/></doc>"
, "testInsertBefore -- node properly placed in tree")
def _create_fragment_test_nodes():
dom
= parseString("<doc/>")
orig
= dom
.createTextNode("original")
c1
= dom
.createTextNode("foo")
c2
= dom
.createTextNode("bar")
c3
= dom
.createTextNode("bat")
dom
.documentElement
.appendChild(orig
)
frag
= dom
.createDocumentFragment()
return dom
, orig
, c1
, c2
, c3
, frag
def testInsertBeforeFragment():
dom
, orig
, c1
, c2
, c3
, frag
= _create_fragment_test_nodes()
dom
.documentElement
.insertBefore(frag
, None)
confirm(tuple(dom
.documentElement
.childNodes
) == (orig
, c1
, c2
, c3
),
"insertBefore(<fragment>, None)")
dom
, orig
, c1
, c2
, c3
, frag
= _create_fragment_test_nodes()
dom
.documentElement
.insertBefore(frag
, orig
)
confirm(tuple(dom
.documentElement
.childNodes
) == (c1
, c2
, c3
, orig
),
"insertBefore(<fragment>, orig)")
dom
.documentElement
.appendChild(dom
.createComment(u
"Hello"))
confirm(dom
.documentElement
.childNodes
[-1].nodeName
== "#comment")
confirm(dom
.documentElement
.childNodes
[-1].data
== "Hello")
def testAppendChildFragment():
dom
, orig
, c1
, c2
, c3
, frag
= _create_fragment_test_nodes()
dom
.documentElement
.appendChild(frag
)
confirm(tuple(dom
.documentElement
.childNodes
) == (orig
, c1
, c2
, c3
),
"appendChild(<fragment>)")
def testReplaceChildFragment():
dom
, orig
, c1
, c2
, c3
, frag
= _create_fragment_test_nodes()
dom
.documentElement
.replaceChild(frag
, orig
)
confirm(tuple(dom
.documentElement
.childNodes
) == (c1
, c2
, c3
),
"replaceChild(<fragment>)")
elem
= dom
.createElement('element')
text
= dom
.createTextNode('text')
try: dom
.appendChild(text
)
except xml
.dom
.HierarchyRequestErr
: pass
print "dom.appendChild didn't raise HierarchyRequestErr"
try: dom
.insertBefore(text
, elem
)
except xml
.dom
.HierarchyRequestErr
: pass
print "dom.appendChild didn't raise HierarchyRequestErr"
try: dom
.replaceChild(text
, elem
)
except xml
.dom
.HierarchyRequestErr
: pass
print "dom.appendChild didn't raise HierarchyRequestErr"
nodemap
= elem
.attributes
try: nodemap
.setNamedItem(text
)
except xml
.dom
.HierarchyRequestErr
: pass
print "NamedNodeMap.setNamedItem didn't raise HierarchyRequestErr"
try: nodemap
.setNamedItemNS(text
)
except xml
.dom
.HierarchyRequestErr
: pass
print "NamedNodeMap.setNamedItemNS didn't raise HierarchyRequestErr"
def testNamedNodeMapSetItem():
elem
= dom
.createElement('element')
confirm(a
.ownerDocument
is dom
,
"NamedNodeMap.__setitem__() sets ownerDocument")
confirm(a
.ownerElement
is elem
,
"NamedNodeMap.__setitem__() sets ownerElement")
confirm(a
.value
== "bar",
"NamedNodeMap.__setitem__() sets value")
confirm(a
.nodeValue
== "bar",
"NamedNodeMap.__setitem__() sets nodeValue")
confirm(dom
)# should not be zero
dom
.appendChild(dom
.createComment("foo"))
confirm(not dom
.childNodes
[-1].childNodes
)
dom
.appendChild(dom
.createElement("abc"))
confirm(dom
.documentElement
)
dom
= parseString("<abc/>")
el
.setAttribute("spam", "jam2")
confirm(el
.toxml() == '<abc spam="jam2"/>', "testAAA")
a
= el
.getAttributeNode("spam")
confirm(a
.ownerDocument
is dom
,
"setAttribute() sets ownerDocument")
confirm(a
.ownerElement
is dom
.documentElement
,
"setAttribute() sets ownerElement")
dom
= parseString("<abc/>")
el
.setAttribute("spam", "jam")
el
.setAttribute("spam", "jam2")
confirm(el
.toxml() == '<abc spam="jam2"/>', "testAAB")
child
= dom
.appendChild(dom
.createElement("abc"))
child
.setAttribute("def", "ghi")
confirm(child
.getAttribute("def") == "ghi")
confirm(child
.attributes
["def"].value
== "ghi")
child
.setAttribute("jkl", "mno")
confirm(child
.getAttribute("jkl") == "mno")
confirm(child
.attributes
["jkl"].value
== "mno")
confirm(len(child
.attributes
) == 2)
child
.setAttribute("def", "newval")
confirm(child
.getAttribute("def") == "newval")
confirm(child
.attributes
["def"].value
== "newval")
confirm(len(child
.attributes
) == 2)
child
= dom
.appendChild(dom
.createElement("abc"))
confirm(len(child
.attributes
) == 0)
child
.setAttribute("def", "ghi")
confirm(len(child
.attributes
) == 1)
del child
.attributes
["def"]
confirm(len(child
.attributes
) == 0)
child
= dom
.appendChild(dom
.createElement("abc"))
child
.setAttribute("def", "ghi")
confirm(len(child
.attributes
) == 1)
child
.removeAttribute("def")
confirm(len(child
.attributes
) == 0)
dom
.createElementNS("http://www.python.org", "python:abc"))
child
.setAttributeNS("http://www.w3.org", "xmlns:python",
child
.setAttributeNS("http://www.python.org", "python:abcattr", "foo")
confirm(len(child
.attributes
) == 2)
child
.removeAttributeNS("http://www.python.org", "abcattr")
confirm(len(child
.attributes
) == 1)
def testRemoveAttributeNode():
child
= dom
.appendChild(dom
.createElement("foo"))
child
.setAttribute("spam", "jam")
confirm(len(child
.attributes
) == 1)
node
= child
.getAttributeNode("spam")
child
.removeAttributeNode(node
)
confirm(len(child
.attributes
) == 0
and child
.getAttributeNode("spam") is None)
dom
= parseString("<abc/>")
el
.setAttribute("spam", "jam")
confirm(len(el
.attributes
) == 1)
el
.setAttribute("spam", "bam")
# Set this attribute to be an ID and make sure that doesn't change
# when changing the value:
el
.setIdAttribute("spam")
confirm(len(el
.attributes
) == 1
and el
.attributes
["spam"].value
== "bam"
and el
.attributes
["spam"].nodeValue
== "bam"
and el
.getAttribute("spam") == "bam"
and el
.getAttributeNode("spam").isId
)
el
.attributes
["spam"] = "ham"
confirm(len(el
.attributes
) == 1
and el
.attributes
["spam"].value
== "ham"
and el
.attributes
["spam"].nodeValue
== "ham"
and el
.getAttribute("spam") == "ham"
and el
.attributes
["spam"].isId
)
el
.setAttribute("spam2", "bam")
confirm(len(el
.attributes
) == 2
and el
.attributes
["spam"].value
== "ham"
and el
.attributes
["spam"].nodeValue
== "ham"
and el
.getAttribute("spam") == "ham"
and el
.attributes
["spam2"].value
== "bam"
and el
.attributes
["spam2"].nodeValue
== "bam"
and el
.getAttribute("spam2") == "bam")
el
.attributes
["spam2"] = "bam2"
confirm(len(el
.attributes
) == 2
and el
.attributes
["spam"].value
== "ham"
and el
.attributes
["spam"].nodeValue
== "ham"
and el
.getAttribute("spam") == "ham"
and el
.attributes
["spam2"].value
== "bam2"
and el
.attributes
["spam2"].nodeValue
== "bam2"
and el
.getAttribute("spam2") == "bam2")
def testGetAttrValues(): pass
def testGetAttrLength(): pass
def testGetAttribute(): pass
def testGetAttributeNS(): pass
def testGetAttributeNode(): pass
def testGetElementsByTagNameNS():
d
="""<foo xmlns:minidom='http://pyxml.sf.net/minidom'>
elems
= dom
.getElementsByTagNameNS("http://pyxml.sf.net/minidom", "myelem")
and elems
[0].namespaceURI
== "http://pyxml.sf.net/minidom"
and elems
[0].localName
== "myelem"
and elems
[0].prefix
== "minidom"
and elems
[0].tagName
== "minidom:myelem"
and elems
[0].nodeName
== "minidom:myelem")
def get_empty_nodelist_from_elements_by_tagName_ns_helper(doc
, nsuri
, lname
):
nodelist
= doc
.getElementsByTagNameNS(nsuri
, lname
)
confirm(len(nodelist
) == 0)
def testGetEmptyNodeListFromElementsByTagNameNS():
doc
= parseString('<doc/>')
get_empty_nodelist_from_elements_by_tagName_ns_helper(
doc
, 'http://xml.python.org/namespaces/a', 'localname')
get_empty_nodelist_from_elements_by_tagName_ns_helper(
get_empty_nodelist_from_elements_by_tagName_ns_helper(
doc
, 'http://xml.python.org/namespaces/a', '*')
doc
= parseString('<doc xmlns="http://xml.python.org/splat"><e/></doc>')
get_empty_nodelist_from_elements_by_tagName_ns_helper(
doc
, "http://xml.python.org/splat", "not-there")
get_empty_nodelist_from_elements_by_tagName_ns_helper(
get_empty_nodelist_from_elements_by_tagName_ns_helper(
doc
, "http://somewhere.else.net/not-there", "e")
def testElementReprAndStr():
el
= dom
.appendChild(dom
.createElement("abc"))
confirm(string1
== string2
)
# commented out until Fredrick's fix is checked in
def _testElementReprAndStrUnicode():
el
= dom
.appendChild(dom
.createElement(u
"abc"))
confirm(string1
== string2
)
# commented out until Fredrick's fix is checked in
def _testElementReprAndStrUnicodeNS():
dom
.createElementNS(u
"http://www.slashdot.org", u
"slash:abc"))
confirm(string1
== string2
)
confirm(string1
.find("slash:abc") != -1)
el
= dom
.appendChild(dom
.createElement(u
"abc"))
node
= el
.setAttribute("abc", "def")
confirm(str(node
) == repr(node
))
def testTextNodeRepr(): pass
str = '<?xml version="1.0" ?><a b="c"/>'
str = '<?xml version="1.0" ?>\n<a b="c"/>\n'
domstr
= dom
.toprettyxml(newl
="\r\n")
confirm(domstr
== str.replace("\n", "\r\n"))
def testProcessingInstruction():
dom
= parseString('<e><?mypi \t\n data \t\n ?></e>')
pi
= dom
.documentElement
.firstChild
confirm(pi
.target
== "mypi"
and pi
.data
== "data \t\n "
and pi
.nodeName
== "mypi"
and pi
.nodeType
== Node
.PROCESSING_INSTRUCTION_NODE
and pi
.attributes
is None
and not pi
.hasChildNodes()
and len(pi
.childNodes
) == 0
and pi
.firstChild
is None
and pi
.namespaceURI
== xml
.dom
.EMPTY_NAMESPACE
)
def testProcessingInstructionRepr(): pass
def testWriteText(): pass
def testDocumentElement(): pass
def testTooManyDocumentElements():
doc
= parseString("<doc/>")
elem
= doc
.createElement("extra")
except xml
.dom
.HierarchyRequestErr
:
print "Failed to catch expected exception when" \
" adding extra document element."
def testCreateElementNS(): pass
def testCreateAttributeNS(): pass
def testParseString(): pass
def testAttrListItem(): pass
def testAttrListItems(): pass
def testAttrListItemNS(): pass
def testAttrListKeys(): pass
def testAttrListKeysNS(): pass
def testRemoveNamedItem():
doc
= parseString("<doc a=''/>")
a1
= e
.getAttributeNode("a")
a2
= attrs
.removeNamedItem("a")
confirm(a1
.isSameNode(a2
))
attrs
.removeNamedItem("a")
except xml
.dom
.NotFoundErr
:
def testRemoveNamedItemNS():
doc
= parseString("<doc xmlns:a='http://xml.python.org/' a:b=''/>")
a1
= e
.getAttributeNodeNS("http://xml.python.org/", "b")
a2
= attrs
.removeNamedItemNS("http://xml.python.org/", "b")
confirm(a1
.isSameNode(a2
))
attrs
.removeNamedItemNS("http://xml.python.org/", "b")
except xml
.dom
.NotFoundErr
:
def testAttrListValues(): pass
def testAttrListLength(): pass
def testAttrList__getitem__(): pass
def testAttrList__setitem__(): pass
def testSetAttrValueandNodeValue(): pass
def testParseElement(): pass
def testParseAttributes(): pass
def testParseElementNamespaces(): pass
def testParseAttributeNamespaces(): pass
def testParseProcessingInstructions(): pass
def testChildNodes(): pass
def testFirstChild(): pass
def testHasChildNodes(): pass
def testCloneElementShallow():
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")
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")
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")
def _testCloneElementCopiesAttributes(e1
, e2
, test
):
confirm(keys1
== keys2
, "clone of element has same attribute keys")
for i
in range(len(keys1
)):
and a1
.nodeValue
== a2
.nodeValue
and a1
.namespaceURI
== a2
.namespaceURI
and a1
.localName
== a2
.localName
, "clone of attribute node has proper attribute values")
confirm(a2
.ownerElement
is e2
,
"clone of attribute node correctly owned")
def testCloneDocumentShallow():
doc
= parseString("<?xml version='1.0'?>\n"
"<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
"testCloneDocumentShallow:"
" shallow cloning of documents makes no sense!")
def testCloneDocumentDeep():
doc
= parseString("<?xml version='1.0'?>\n"
"<!NOTATION notation SYSTEM 'http://xml.python.org/'>\n"
confirm(not (doc
.isSameNode(doc2
) or doc2
.isSameNode(doc
)),
"testCloneDocumentDeep: document objects not distinct")
confirm(len(doc
.childNodes
) == len(doc2
.childNodes
),
"testCloneDocumentDeep: wrong number of Document children")
confirm(doc2
.documentElement
.nodeType
== Node
.ELEMENT_NODE
,
"testCloneDocumentDeep: documentElement not an ELEMENT_NODE")
confirm(doc2
.documentElement
.ownerDocument
.isSameNode(doc2
),
"testCloneDocumentDeep: documentElement owner is not new document")
confirm(not doc
.documentElement
.isSameNode(doc2
.documentElement
),
"testCloneDocumentDeep: documentElement should not be shared")
if doc
.doctype
is not None:
# check the doctype iff the original DOM maintained it
confirm(doc2
.doctype
.nodeType
== Node
.DOCUMENT_TYPE_NODE
,
"testCloneDocumentDeep: doctype not a DOCUMENT_TYPE_NODE")
confirm(doc2
.doctype
.ownerDocument
.isSameNode(doc2
))
confirm(not doc
.doctype
.isSameNode(doc2
.doctype
))
def testCloneDocumentTypeDeepOk():
doctype
= create_nonempty_doctype()
clone
= doctype
.cloneNode(1)
confirm(clone
is not None
and clone
.nodeName
== doctype
.nodeName
and clone
.name
== doctype
.name
and clone
.publicId
== doctype
.publicId
and clone
.systemId
== doctype
.systemId
and len(clone
.entities
) == len(doctype
.entities
)
and clone
.entities
.item(len(clone
.entities
)) is None
and len(clone
.notations
) == len(doctype
.notations
)
and clone
.notations
.item(len(clone
.notations
)) is None
and len(clone
.childNodes
) == 0)
for i
in range(len(doctype
.entities
)):
se
= doctype
.entities
.item(i
)
ce
= clone
.entities
.item(i
)
confirm((not se
.isSameNode(ce
))
and (not ce
.isSameNode(se
))
and ce
.nodeName
== se
.nodeName
and ce
.notationName
== se
.notationName
and ce
.publicId
== se
.publicId
and ce
.systemId
== se
.systemId
and ce
.encoding
== se
.encoding
and ce
.actualEncoding
== se
.actualEncoding
and ce
.version
== se
.version
)
for i
in range(len(doctype
.notations
)):
sn
= doctype
.notations
.item(i
)
cn
= clone
.notations
.item(i
)
confirm((not sn
.isSameNode(cn
))
and (not cn
.isSameNode(sn
))
and cn
.nodeName
== sn
.nodeName
and cn
.publicId
== sn
.publicId
and cn
.systemId
== sn
.systemId
)
def testCloneDocumentTypeDeepNotOk():
doc
= create_doc_with_doctype()
clone
= doc
.doctype
.cloneNode(1)
confirm(clone
is None, "testCloneDocumentTypeDeepNotOk")
def testCloneDocumentTypeShallowOk():
doctype
= create_nonempty_doctype()
clone
= doctype
.cloneNode(0)
confirm(clone
is not None
and clone
.nodeName
== doctype
.nodeName
and clone
.name
== doctype
.name
and clone
.publicId
== doctype
.publicId
and clone
.systemId
== doctype
.systemId
and len(clone
.entities
) == 0
and clone
.entities
.item(0) is None
and len(clone
.notations
) == 0
and clone
.notations
.item(0) is None
and len(clone
.childNodes
) == 0)
def testCloneDocumentTypeShallowNotOk():
doc
= create_doc_with_doctype()
clone
= doc
.doctype
.cloneNode(0)
confirm(clone
is None, "testCloneDocumentTypeShallowNotOk")
def check_import_document(deep
, testName
):
doc1
= parseString("<doc/>")
doc2
= parseString("<doc/>")
doc1
.importNode(doc2
, deep
)
except xml
.dom
.NotSupportedErr
:
raise Exception(testName
+
": expected NotSupportedErr when importing a document")
def testImportDocumentShallow():
check_import_document(0, "testImportDocumentShallow")
def testImportDocumentDeep():
check_import_document(1, "testImportDocumentDeep")
# The tests of DocumentType importing use these helpers to construct
# the documents to work with, since not all DOM builders actually
# create the DocumentType nodes.
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",
entity
.encoding
= "utf-8"
entity
.actualEncoding
= "us-ascii"
doctype
.entities
._seq
.append(entity
)
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
def testImportDocumentTypeShallow():
src
= create_doc_with_doctype()
target
= create_doc_without_doctype()
imported
= target
.importNode(src
.doctype
, 0)
except xml
.dom
.NotSupportedErr
:
"testImportDocumentTypeShallow: expected NotSupportedErr")
def testImportDocumentTypeDeep():
src
= create_doc_with_doctype()
target
= create_doc_without_doctype()
imported
= target
.importNode(src
.doctype
, 1)
except xml
.dom
.NotSupportedErr
:
"testImportDocumentTypeDeep: expected NotSupportedErr")
# Testing attribute clones uses a helper, and should always be deep,
# even if the argument to cloneNode is false.
def check_clone_attribute(deep
, testName
):
doc
= parseString("<doc attr='value'/>")
attr
= doc
.documentElement
.getAttributeNode("attr")
clone
= attr
.cloneNode(deep
)
confirm(not clone
.isSameNode(attr
))
confirm(not attr
.isSameNode(clone
))
confirm(clone
.ownerElement
is None,
testName
+ ": ownerElement should be None")
confirm(clone
.ownerDocument
.isSameNode(attr
.ownerDocument
),
testName
+ ": ownerDocument does not match")
testName
+ ": cloned attribute must have specified == True")
def testCloneAttributeShallow():
check_clone_attribute(0, "testCloneAttributeShallow")
def testCloneAttributeDeep():
check_clone_attribute(1, "testCloneAttributeDeep")
def check_clone_pi(deep
, testName
):
doc
= parseString("<?target data?><doc/>")
assert pi
.nodeType
== Node
.PROCESSING_INSTRUCTION_NODE
clone
= pi
.cloneNode(deep
)
confirm(clone
.target
== pi
.target
and clone
.data
== pi
.data
)
def testClonePIShallow():
check_clone_pi(0, "testClonePIShallow")
check_clone_pi(1, "testClonePIDeep")
doc
= parseString("<doc/>")
root
= doc
.documentElement
root
.appendChild(doc
.createTextNode("first"))
root
.appendChild(doc
.createTextNode("second"))
confirm(len(root
.childNodes
) == 2
and root
.childNodes
.length
== 2, "testNormalize -- preparation")
confirm(len(root
.childNodes
) == 1
and root
.childNodes
.length
== 1
and root
.firstChild
is root
.lastChild
and root
.firstChild
.data
== "firstsecond"
, "testNormalize -- result")
doc
= parseString("<doc/>")
root
= doc
.documentElement
root
.appendChild(doc
.createTextNode(""))
confirm(len(root
.childNodes
) == 0
and root
.childNodes
.length
== 0,
"testNormalize -- single empty node removed")
doc
= parseString("<doc><?pi?>text?<elm/></doc>")
root
= doc
.documentElement
(pi
, text
, elm
) = root
.childNodes
confirm(pi
.nextSibling
is text
and
pi
.previousSibling
is None and
text
.nextSibling
is elm
and
text
.previousSibling
is pi
and
elm
.nextSibling
is None and
elm
.previousSibling
is text
, "testSiblings")
doc
= parseString("<doc><elm1><elm2/><elm2><elm3/></elm2></elm1></doc>")
root
= doc
.documentElement
elm1
= root
.childNodes
[0]
(elm2a
, elm2b
) = elm1
.childNodes
elm3
= elm2b
.childNodes
[0]
confirm(root
.parentNode
is doc
and
elm1
.parentNode
is root
and
elm2a
.parentNode
is elm1
and
elm2b
.parentNode
is elm1
and
elm3
.parentNode
is elm2b
, "testParents")
doc
= parseString("<doc><e/><e/></doc>")
children
= doc
.childNodes
confirm(children
[0] is children
.item(0)
and children
.item(1) is None
and docelem
.childNodes
.item(0) is docelem
.childNodes
[0]
and docelem
.childNodes
.item(1) is docelem
.childNodes
[1]
and docelem
.childNodes
.item(0).childNodes
.item(0) is None,
from xml
.dom
import pulldom
sax2dom
= pulldom
.SAX2DOM()
sax2dom
.startElement("doc", {})
sax2dom
.characters("text")
sax2dom
.startElement("subelm", {})
sax2dom
.characters("text")
sax2dom
.endElement("subelm")
sax2dom
.characters("text")
sax2dom
.endElement("doc")
root
= doc
.documentElement
(text1
, elm1
, text2
) = root
.childNodes
text3
= elm1
.childNodes
[0]
confirm(text1
.previousSibling
is None and
text1
.nextSibling
is elm1
and
elm1
.previousSibling
is text1
and
elm1
.nextSibling
is text2
and
text2
.previousSibling
is elm1
and
text2
.nextSibling
is None and
text3
.previousSibling
is None and
text3
.nextSibling
is None, "testSAX2DOM - siblings")
confirm(root
.parentNode
is doc
and
text1
.parentNode
is root
and
elm1
.parentNode
is root
and
text2
.parentNode
is root
and
text3
.parentNode
is elm1
, "testSAX2DOM - parents")
doc
= parseString('<foo>€</foo>')
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('iso-8859-15') == '<?xml version="1.0" encoding="iso-8859-15"?><foo>\xa4</foo>',
"testEncodings - encoding EURO SIGN")
def handle(self
, operation
, key
, data
, src
, dst
):
dst
.setUserData(key
, data
+ 1, self
)
src
.setUserData(key
, None, None)
n
= dom
.createElement('e')
confirm(n
.getUserData("foo") is None)
n
.setUserData("foo", None, None)
confirm(n
.getUserData("foo") is None)
n
.setUserData("foo", 12, 12)
n
.setUserData("bar", 13, 13)
confirm(n
.getUserData("foo") == 12)
confirm(n
.getUserData("bar") == 13)
n
.setUserData("foo", None, None)
confirm(n
.getUserData("foo") is None)
confirm(n
.getUserData("bar") == 13)
handler
= UserDataHandler()
n
.setUserData("bar", 12, handler
)
and n
.getUserData("bar") is None
and c
.getUserData("bar") == 13)
def testRenameAttribute():
doc
= parseString("<doc a='v'/>")
elem
= doc
.documentElement
attrmap
= elem
.attributes
attr
= elem
.attributes
['a']
attr
= doc
.renameNode(attr
, xml
.dom
.EMPTY_NAMESPACE
, "b")
and attr
.localName
is None
and attr
.namespaceURI
== xml
.dom
.EMPTY_NAMESPACE
and elem
.getAttributeNode("a") is None
and elem
.getAttributeNode("b").isSameNode(attr
)
and attrmap
["b"].isSameNode(attr
)
and attr
.ownerDocument
.isSameNode(doc
)
and attr
.ownerElement
.isSameNode(elem
))
# Rename to have a namespace, no prefix
attr
= doc
.renameNode(attr
, "http://xml.python.org/ns", "c")
and attr
.localName
== "c"
and attr
.namespaceURI
== "http://xml.python.org/ns"
and elem
.getAttributeNode("a") is None
and elem
.getAttributeNode("b") is None
and elem
.getAttributeNode("c").isSameNode(attr
)
and elem
.getAttributeNodeNS(
"http://xml.python.org/ns", "c").isSameNode(attr
)
and attrmap
["c"].isSameNode(attr
)
and attrmap
[("http://xml.python.org/ns", "c")].isSameNode(attr
))
# Rename to have a namespace, with prefix
attr
= doc
.renameNode(attr
, "http://xml.python.org/ns2", "p:d")
confirm(attr
.name
== "p:d"
and attr
.nodeName
== "p:d"
and attr
.localName
== "d"
and attr
.namespaceURI
== "http://xml.python.org/ns2"
and elem
.getAttributeNode("a") is None
and elem
.getAttributeNode("b") is None
and elem
.getAttributeNode("c") is None
and elem
.getAttributeNodeNS(
"http://xml.python.org/ns", "c") is None
and elem
.getAttributeNode("p:d").isSameNode(attr
)
and elem
.getAttributeNodeNS(
"http://xml.python.org/ns2", "d").isSameNode(attr
)
and attrmap
["p:d"].isSameNode(attr
)
and attrmap
[("http://xml.python.org/ns2", "d")].isSameNode(attr
))
# Rename back to a simple non-NS node
attr
= doc
.renameNode(attr
, xml
.dom
.EMPTY_NAMESPACE
, "e")
and attr
.localName
is None
and attr
.namespaceURI
== xml
.dom
.EMPTY_NAMESPACE
and elem
.getAttributeNode("a") is None
and elem
.getAttributeNode("b") is None
and elem
.getAttributeNode("c") is None
and elem
.getAttributeNode("p:d") is None
and elem
.getAttributeNodeNS(
"http://xml.python.org/ns", "c") is None
and elem
.getAttributeNode("e").isSameNode(attr
)
and attrmap
["e"].isSameNode(attr
))
doc
.renameNode(attr
, "http://xml.python.org/ns", "xmlns")
except xml
.dom
.NamespaceErr
:
print "expected NamespaceErr"
checkRenameNodeSharedConstraints(doc
, attr
)
doc
= parseString("<doc/>")
elem
= doc
.documentElement
elem
= doc
.renameNode(elem
, xml
.dom
.EMPTY_NAMESPACE
, "a")
confirm(elem
.tagName
== "a"
and elem
.localName
is None
and elem
.namespaceURI
== xml
.dom
.EMPTY_NAMESPACE
and elem
.ownerDocument
.isSameNode(doc
))
# Rename to have a namespace, no prefix
elem
= doc
.renameNode(elem
, "http://xml.python.org/ns", "b")
confirm(elem
.tagName
== "b"
and elem
.localName
== "b"
and elem
.namespaceURI
== "http://xml.python.org/ns"
and elem
.ownerDocument
.isSameNode(doc
))
# Rename to have a namespace, with prefix
elem
= doc
.renameNode(elem
, "http://xml.python.org/ns2", "p:c")
confirm(elem
.tagName
== "p:c"
and elem
.nodeName
== "p:c"
and elem
.localName
== "c"
and elem
.namespaceURI
== "http://xml.python.org/ns2"
and elem
.ownerDocument
.isSameNode(doc
))
# Rename back to a simple non-NS node
elem
= doc
.renameNode(elem
, xml
.dom
.EMPTY_NAMESPACE
, "d")
confirm(elem
.tagName
== "d"
and elem
.localName
is None
and elem
.namespaceURI
== xml
.dom
.EMPTY_NAMESPACE
and elem
.ownerDocument
.isSameNode(doc
))
checkRenameNodeSharedConstraints(doc
, elem
)
def checkRenameNodeSharedConstraints(doc
, node
):
# Make sure illegal NS usage is detected:
doc
.renameNode(node
, "http://xml.python.org/ns", "xmlns:foo")
except xml
.dom
.NamespaceErr
:
print "expected NamespaceErr"
doc2
= parseString("<doc/>")
doc2
.renameNode(node
, xml
.dom
.EMPTY_NAMESPACE
, "foo")
except xml
.dom
.WrongDocumentErr
:
print "expected WrongDocumentErr"
# We have to create a comment node explicitly since not all DOM
# builders used with minidom add comments to the DOM.
doc
= xml
.dom
.minidom
.getDOMImplementation().createDocument(
xml
.dom
.EMPTY_NAMESPACE
, "e", None)
node
= doc
.createComment("comment")
doc
.renameNode(node
, xml
.dom
.EMPTY_NAMESPACE
, "foo")
except xml
.dom
.NotSupportedErr
:
print "expected NotSupportedErr when renaming comment node"
def checkWholeText(node
, s
):
confirm(t
== s
, "looking for %s, found %s" % (repr(s
), repr(t
)))
doc
= parseString("<doc>a</doc>")
elem
= doc
.documentElement
text
= elem
.childNodes
[0]
assert text
.nodeType
== Node
.TEXT_NODE
checkWholeText(text
, "a")
elem
.appendChild(doc
.createTextNode("b"))
checkWholeText(text
, "ab")
elem
.insertBefore(doc
.createCDATASection("c"), text
)
checkWholeText(text
, "cab")
# make sure we don't cross other nodes
splitter
= doc
.createComment("comment")
elem
.appendChild(splitter
)
text2
= doc
.createTextNode("d")
checkWholeText(text
, "cab")
checkWholeText(text2
, "d")
x
= doc
.createElement("x")
elem
.replaceChild(x
, splitter
)
checkWholeText(text
, "cab")
checkWholeText(text2
, "d")
x
= doc
.createProcessingInstruction("y", "z")
elem
.replaceChild(x
, splitter
)
checkWholeText(text
, "cab")
checkWholeText(text2
, "d")
elem
.removeChild(splitter
)
checkWholeText(text
, "cabd")
checkWholeText(text2
, "cabd")
def testReplaceWholeText():
doc
= parseString("<doc>a<e/>d</doc>")
elem
= doc
.documentElement
splitter
= text1
.nextSibling
elem
.insertBefore(doc
.createTextNode("b"), splitter
)
elem
.insertBefore(doc
.createCDATASection("c"), text1
)
return doc
, elem
, text1
, splitter
, text2
doc
, elem
, text1
, splitter
, text2
= setup()
text
= text1
.replaceWholeText("new content")
checkWholeText(text
, "new content")
checkWholeText(text2
, "d")
confirm(len(elem
.childNodes
) == 3)
doc
, elem
, text1
, splitter
, text2
= setup()
text
= text2
.replaceWholeText("new content")
checkWholeText(text
, "new content")
checkWholeText(text1
, "cab")
confirm(len(elem
.childNodes
) == 5)
doc
, elem
, text1
, splitter
, text2
= setup()
text
= text1
.replaceWholeText("")
checkWholeText(text2
, "d")
and len(elem
.childNodes
) == 2)
" <!ENTITY e1 SYSTEM 'http://xml.python.org/e1'>\n"
" <!ENTITY e2 SYSTEM 'http://xml.python.org/e2'>\n"
" <!ATTLIST doc id ID #IMPLIED \n"
" refs IDREFS #IMPLIED \n"
" enum (a|b) #IMPLIED \n"
" ent ENTITY #IMPLIED \n"
" ents ENTITIES #IMPLIED \n"
" nm NMTOKEN #IMPLIED \n"
" nms NMTOKENS #IMPLIED \n"
" text CDATA #IMPLIED \n"
"]><doc id='name' notid='name' text='splat!' enum='b'"
" ref='name' refs='name name' ent='e1' ents='e1 e2'"
" nm='123' nms='123 abc' />")
elem
= doc
.documentElement
# We don't want to rely on any specific loader at this point, so
# just make sure we can get to all the names, and that the
# DTD-based namespace is right. The names can vary by loader
# since each supports a different level of DTD information.
and t
.namespace
== xml
.dom
.EMPTY_NAMESPACE
)
names
= "id notid text enum ref refs ent ents nm nms".split()
a
= elem
.getAttributeNode(name
)
confirm(hasattr(t
, "name")
and t
.namespace
== xml
.dom
.EMPTY_NAMESPACE
)
def testSetIdAttribute():
doc
= parseString("<doc a1='v' a2='w'/>")
a1
= e
.getAttributeNode("a1")
a2
= e
.getAttributeNode("a2")
confirm(doc
.getElementById("v") is None
confirm(e
.isSameNode(doc
.getElementById("v"))
confirm(e
.isSameNode(doc
.getElementById("v"))
and e
.isSameNode(doc
.getElementById("w"))
# replace the a1 node; the new node should *not* be an ID
a3
= doc
.createAttribute("a1")
confirm(doc
.getElementById("v") is None
and e
.isSameNode(doc
.getElementById("w"))
# renaming an attribute should not affect its ID-ness:
doc
.renameNode(a2
, xml
.dom
.EMPTY_NAMESPACE
, "an")
confirm(e
.isSameNode(doc
.getElementById("w"))
def testSetIdAttributeNS():
NS1
= "http://xml.python.org/ns1"
NS2
= "http://xml.python.org/ns2"
" xmlns:ns1='" + NS1
+ "'"
" xmlns:ns2='" + NS2
+ "'"
" ns1:a1='v' ns2:a2='w'/>")
a1
= e
.getAttributeNodeNS(NS1
, "a1")
a2
= e
.getAttributeNodeNS(NS2
, "a2")
confirm(doc
.getElementById("v") is None
e
.setIdAttributeNS(NS1
, "a1")
confirm(e
.isSameNode(doc
.getElementById("v"))
e
.setIdAttributeNS(NS2
, "a2")
confirm(e
.isSameNode(doc
.getElementById("v"))
and e
.isSameNode(doc
.getElementById("w"))
# replace the a1 node; the new node should *not* be an ID
a3
= doc
.createAttributeNS(NS1
, "a1")
confirm(e
.isSameNode(doc
.getElementById("w")))
confirm(doc
.getElementById("v") is None)
# renaming an attribute should not affect its ID-ness:
doc
.renameNode(a2
, xml
.dom
.EMPTY_NAMESPACE
, "an")
confirm(e
.isSameNode(doc
.getElementById("w"))
def testSetIdAttributeNode():
NS1
= "http://xml.python.org/ns1"
NS2
= "http://xml.python.org/ns2"
" xmlns:ns1='" + NS1
+ "'"
" xmlns:ns2='" + NS2
+ "'"
" ns1:a1='v' ns2:a2='w'/>")
a1
= e
.getAttributeNodeNS(NS1
, "a1")
a2
= e
.getAttributeNodeNS(NS2
, "a2")
confirm(doc
.getElementById("v") is None
confirm(e
.isSameNode(doc
.getElementById("v"))
confirm(e
.isSameNode(doc
.getElementById("v"))
and e
.isSameNode(doc
.getElementById("w"))
# replace the a1 node; the new node should *not* be an ID
a3
= doc
.createAttributeNS(NS1
, "a1")
confirm(e
.isSameNode(doc
.getElementById("w")))
confirm(doc
.getElementById("v") is None)
# renaming an attribute should not affect its ID-ness:
doc
.renameNode(a2
, xml
.dom
.EMPTY_NAMESPACE
, "an")
confirm(e
.isSameNode(doc
.getElementById("w"))
def testPickledDocument():
doc
= parseString("<?xml version='1.0' encoding='us-ascii'?>\n"
"<!DOCTYPE doc PUBLIC 'http://xml.python.org/public'"
" 'http://xml.python.org/system' [\n"
" <!ENTITY ent SYSTEM 'http://xml.python.org/entity'>\n"
"]><doc attr='value'> text\n"
"<?pi sample?> <!-- comment --> <e/> </doc>")
confirm(n1
.nodeType
== n2
.nodeType
and len(n1
.childNodes
) == len(n2
.childNodes
)
and n1
.nodeName
== n2
.nodeName
and not n1
.isSameNode(n2
)
and not n2
.isSameNode(n1
))
if n1
.nodeType
== Node
.DOCUMENT_TYPE_NODE
:
confirm(len(n1
.entities
) == len(n2
.entities
)
and len(n1
.notations
) == len(n2
.notations
))
for i
in range(len(n1
.notations
)):
no1
= n1
.notations
.item(i
)
no2
= n1
.notations
.item(i
)
confirm(no1
.name
== no2
.name
and no1
.publicId
== no2
.publicId
and no1
.systemId
== no2
.systemId
)
statck
.append((no1
, no2
))
for i
in range(len(n1
.entities
)):
confirm(e1
.notationName
== e2
.notationName
and e1
.publicId
== e2
.publicId
and e1
.systemId
== e2
.systemId
)
if n1
.nodeType
!= Node
.DOCUMENT_NODE
:
confirm(n1
.ownerDocument
.isSameNode(doc
)
and n2
.ownerDocument
.isSameNode(doc2
))
for i
in range(len(n1
.childNodes
)):
stack
.append((n1
.childNodes
[i
], n2
.childNodes
[i
]))
# We don't actually have the minidom from the standard library,
# but are picking up the PyXML version from site-packages.
confirm(len(Node
.allnodes
) == 0,
"assertion: len(Node.allnodes) == 0")
print "Garbage left over:"
print Node
.allnodes
.items()[0:10]
# Don't print specific nodes if repeatable results
if name
.startswith("test"):
print "Test Failed: ", name
traceback
.print_exception(*sys
.exc_info())
print repr(sys
.exc_info()[1])
print "\n\n\n**** Check for failures in these tests:"