summaryrefslogtreecommitdiffstats
path: root/Lib/xml/dom
diff options
context:
space:
mode:
authorMartin v. Löwis <martin@v.loewis.de>2001-03-13 10:50:13 (GMT)
committerMartin v. Löwis <martin@v.loewis.de>2001-03-13 10:50:13 (GMT)
commit126f2f62db541565bebc83859ac329836d7d3f00 (patch)
tree5b5f01713f08c3af3db0f4d5563099448ff01caa /Lib/xml/dom
parenta8f7e5976126c4d0a3acef512e75a87b560ac2ec (diff)
downloadcpython-126f2f62db541565bebc83859ac329836d7d3f00.zip
cpython-126f2f62db541565bebc83859ac329836d7d3f00.tar.gz
cpython-126f2f62db541565bebc83859ac329836d7d3f00.tar.bz2
Patch #407965: Improve Level 2 conformance of minidom
- addition of a DocumentFragment implementation and createDocumentFragment method - proper setting of ownerDocument for all nodes - setting of namespaceURI to None in Element as a class attribute - addition of setAttributeNodeNS and removeAttributeNodeNS as aliases for setAttributeNode and removeAttributeNode - support for inheriting from DOMImplementation to extend it with additional features (to override the Document class) in pulldom: - support for nodes (comment and PI) that occur before he document element; that became necessary as pulldom now delays creation of the document until it has the document element.
Diffstat (limited to 'Lib/xml/dom')
-rw-r--r--Lib/xml/dom/minidom.py88
-rw-r--r--Lib/xml/dom/pulldom.py36
2 files changed, 103 insertions, 21 deletions
diff --git a/Lib/xml/dom/minidom.py b/Lib/xml/dom/minidom.py
index 35adfd5..72ec5e0 100644
--- a/Lib/xml/dom/minidom.py
+++ b/Lib/xml/dom/minidom.py
@@ -38,10 +38,11 @@ class Node(_Node):
_makeParentNodes = 1
debug = None
childNodeTypes = ()
+ namespaceURI = None # this is non-null only for elements and attributes
def __init__(self):
self.childNodes = []
- self.parentNode = None
+ self.parentNode = self.ownerDocument = None
if Node._debug:
index = repr(id(self)) + repr(self.__class__)
Node.allnodes[index] = repr(self.__dict__)
@@ -107,6 +108,11 @@ class Node(_Node):
return self.childNodes[-1]
def insertBefore(self, newChild, refChild):
+ if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
+ for c in newChild.childNodes:
+ self.insertBefore(c, refChild)
+ ### The DOM does not clearly specify what to return in this case
+ return newChild
if newChild.nodeType not in self.childNodeTypes:
raise HierarchyRequestErr, \
"%s cannot be child of %s" % (repr(newChild), repr(self))
@@ -130,6 +136,11 @@ class Node(_Node):
return newChild
def appendChild(self, node):
+ if node.nodeType == self.DOCUMENT_FRAGMENT_NODE:
+ for c in node.childNodes:
+ self.appendChild(c)
+ ### The DOM does not clearly specify what to return in this case
+ return node
if node.nodeType not in self.childNodeTypes:
raise HierarchyRequestErr, \
"%s cannot be child of %s" % (repr(node), repr(self))
@@ -148,6 +159,10 @@ class Node(_Node):
return node
def replaceChild(self, newChild, oldChild):
+ if newChild.nodeType == self.DOCUMENT_FRAGMENT_NODE:
+ refChild = oldChild.nextSibling
+ self.removeChild(oldChild)
+ return self.insertBefore(newChild, refChild)
if newChild.nodeType not in self.childNodeTypes:
raise HierarchyRequestErr, \
"%s cannot be child of %s" % (repr(newChild), repr(self))
@@ -233,7 +248,7 @@ class Node(_Node):
# minidom-specific API:
def unlink(self):
- self.parentNode = None
+ self.parentNode = self.ownerDocument = None
for child in self.childNodes:
child.unlink()
self.childNodes = None
@@ -270,6 +285,21 @@ def _getElementsByTagNameNSHelper(parent, nsURI, localName, rc):
_getElementsByTagNameNSHelper(node, nsURI, localName, rc)
return rc
+class DocumentFragment(Node):
+ nodeType = Node.DOCUMENT_FRAGMENT_NODE
+ nodeName = "#document-fragment"
+ nodeValue = None
+ attributes = None
+ parentNode = None
+ childNodeTypes = (Node.ELEMENT_NODE,
+ Node.TEXT_NODE,
+ Node.CDATA_SECTION_NODE,
+ Node.ENTITY_REFERENCE_NODE,
+ Node.PROCESSING_INSTRUCTION_NODE,
+ Node.COMMENT_NODE,
+ Node.NOTATION_NODE)
+
+
class Attr(Node):
nodeType = Node.ATTRIBUTE_NODE
attributes = None
@@ -409,7 +439,7 @@ class Element(Node):
Node.COMMENT_NODE, Node.TEXT_NODE,
Node.CDATA_SECTION_NODE, Node.ENTITY_REFERENCE_NODE)
- def __init__(self, tagName, namespaceURI="", prefix="",
+ def __init__(self, tagName, namespaceURI=None, prefix="",
localName=None):
Node.__init__(self)
self.tagName = self.nodeName = tagName
@@ -494,6 +524,8 @@ class Element(Node):
# it doesn't represent a change, and should not be returned.
return old
+ setAttributeNodeNS = setAttributeNode
+
def removeAttribute(self, name):
attr = self._attrs[name]
self.removeAttributeNode(attr)
@@ -507,6 +539,8 @@ class Element(Node):
del self._attrs[node.name]
del self._attrsNS[(node.namespaceURI, node.localName)]
+ removeAttributeNodeNS = removeAttributeNode
+
def hasAttribute(self, name):
return self._attrs.has_key(name)
@@ -651,7 +685,7 @@ class DOMImplementation:
if doctype and doctype.parentNode is not None:
raise xml.dom.WrongDocumentErr(
"doctype object owned by another DOM tree")
- doc = Document()
+ doc = self._createDocument()
if doctype is None:
doctype = self.createDocumentType(qualifiedName, None, None)
if not qualifiedName:
@@ -671,7 +705,7 @@ class DOMImplementation:
"illegal use of prefix without namespaces")
element = doc.createElementNS(namespaceURI, qualifiedName)
doc.appendChild(element)
- doctype.parentNode = doc
+ doctype.parentNode = doctype.ownerDocument = doc
doc.doctype = doctype
doc.implementation = self
return doc
@@ -682,6 +716,9 @@ class DOMImplementation:
doctype.systemId = systemId
return doctype
+ # internal
+ def _createDocument(self):
+ return Document()
class Document(Node):
nodeType = Node.DOCUMENT_NODE
@@ -690,6 +727,7 @@ class Document(Node):
attributes = None
doctype = None
parentNode = None
+ previousSibling = nextSibling = None
implementation = DOMImplementation()
childNodeTypes = (Node.ELEMENT_NODE, Node.PROCESSING_INSTRUCTION_NODE,
@@ -728,25 +766,47 @@ class Document(Node):
self.doctype = None
Node.unlink(self)
- createElement = Element
+ def createDocumentFragment(self):
+ d = DocumentFragment()
+ d.ownerDoc = self
+ return d
+
+ def createElement(self, tagName):
+ e = Element(tagName)
+ e.ownerDocument = self
+ return e
- createTextNode = Text
+ def createTextNode(self, data):
+ t = Text(data)
+ t.ownerDocument = self
+ return t
- createComment = Comment
+ def createComment(self, data):
+ c = Comment(data)
+ c.ownerDocument = self
+ return c
- createProcessingInstruction = ProcessingInstruction
+ def createProcessingInstruction(self, target, data):
+ p = ProcessingInstruction(target, data)
+ p.ownerDocument = self
+ return p
- createAttribute = Attr
+ def createAttribute(self, qName):
+ a = Attr(qName)
+ a.ownerDocument = self
+ return a
def createElementNS(self, namespaceURI, qualifiedName):
prefix, localName = _nssplit(qualifiedName)
- return self.createElement(qualifiedName, namespaceURI,
- prefix, localName)
+ e = Element(qualifiedName, namespaceURI, prefix, localName)
+ e.ownerDocument = self
+ return e
def createAttributeNS(self, namespaceURI, qualifiedName):
prefix, localName = _nssplit(qualifiedName)
- return self.createAttribute(qualifiedName, namespaceURI,
- localName, prefix)
+ a = Attr(qualifiedName, namespaceURI, localName, prefix)
+ a.ownerDocument = self
+ return a
def getElementsByTagNameNS(self, namespaceURI, localName):
_getElementsByTagNameNSHelper(self, namespaceURI, localName)
diff --git a/Lib/xml/dom/pulldom.py b/Lib/xml/dom/pulldom.py
index b573ba0..d7280ee 100644
--- a/Lib/xml/dom/pulldom.py
+++ b/Lib/xml/dom/pulldom.py
@@ -33,6 +33,7 @@ class PullDOM(xml.sax.ContentHandler):
pass
self._ns_contexts = [{}] # contains uri -> prefix dicts
self._current_context = self._ns_contexts[-1]
+ self.pending_events = []
def pop(self):
result = self.elementStack[-1]
@@ -115,15 +116,22 @@ class PullDOM(xml.sax.ContentHandler):
self.lastEvent = self.lastEvent[1]
def comment(self, s):
- node = self.document.createComment(s)
- self.lastEvent[1] = [(COMMENT, node), None]
- self.lastEvent = self.lastEvent[1]
+ if self.document:
+ node = self.document.createComment(s)
+ self.lastEvent[1] = [(COMMENT, node), None]
+ self.lastEvent = self.lastEvent[1]
+ else:
+ event = [(COMMENT, s), None]
+ self.pending_events.append(event)
def processingInstruction(self, target, data):
- node = self.document.createProcessingInstruction(target, data)
-
- self.lastEvent[1] = [(PROCESSING_INSTRUCTION, node), None]
- self.lastEvent = self.lastEvent[1]
+ if self.document:
+ node = self.document.createProcessingInstruction(target, data)
+ self.lastEvent[1] = [(PROCESSING_INSTRUCTION, node), None]
+ self.lastEvent = self.lastEvent[1]
+ else:
+ event = [(PROCESSING_INSTRUCTION, target, data), None]
+ self.pending_events.append(event)
def ignorableWhitespace(self, chars):
node = self.document.createTextNode(chars)
@@ -148,6 +156,20 @@ class PullDOM(xml.sax.ContentHandler):
self.lastEvent[1] = [(START_DOCUMENT, node), None]
self.lastEvent = self.lastEvent[1]
self.push(node)
+ # Put everything we have seen so far into the document
+ for e in self.pending_events:
+ if e[0][0] == PROCESSING_INSTRUCTION:
+ _,target,data = e[0]
+ n = self.document.createProcessingInstruction(target, data)
+ e[0] = (PROCESSING_INSTRUCTION, n)
+ elif e[0][0] == COMMENT:
+ n = self.document.createComment(e[0][1])
+ e[0] = (COMMENT, n)
+ else:
+ raise AssertionError("Unknown pending event ",e[0][0])
+ self.lastEvent[1] = e
+ self.lastEvent = e
+ self.pending_events = None
return node.firstChild
def endDocument(self):