diff options
author | Martin v. Löwis <martin@v.loewis.de> | 2001-03-13 10:50:13 (GMT) |
---|---|---|
committer | Martin v. Löwis <martin@v.loewis.de> | 2001-03-13 10:50:13 (GMT) |
commit | 126f2f62db541565bebc83859ac329836d7d3f00 (patch) | |
tree | 5b5f01713f08c3af3db0f4d5563099448ff01caa /Lib/xml | |
parent | a8f7e5976126c4d0a3acef512e75a87b560ac2ec (diff) | |
download | cpython-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')
-rw-r--r-- | Lib/xml/dom/minidom.py | 88 | ||||
-rw-r--r-- | Lib/xml/dom/pulldom.py | 36 |
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): |