📄 minidom.py
字号:
"""\
minidom.py -- a lightweight DOM implementation.
parse("foo.xml")
parseString("<foo><bar/></foo>")
Todo:
=====
* convenience methods for getting elements and text.
* more testing
* bring some of the writer and linearizer code into conformance with this
interface
* SAX 2 namespaces
"""
import string
_string = string
del string
from xml.dom import HierarchyRequestErr
# localize the types, and allow support for Unicode values if available:
import types
_TupleType = types.TupleType
try:
_StringTypes = (types.StringType, types.UnicodeType)
except AttributeError:
_StringTypes = (types.StringType,)
del types
import xml.dom
_Node = xml.dom.Node
class Node(_Node):
allnodes = {}
_debug = 0
_makeParentNodes = 1
debug = None
childNodeTypes = ()
namespaceURI = None # this is non-null only for elements and attributes
def __init__(self):
self.childNodes = []
self.parentNode = self.ownerDocument = None
if Node._debug:
index = repr(id(self)) + repr(self.__class__)
Node.allnodes[index] = repr(self.__dict__)
if Node.debug is None:
Node.debug = _get_StringIO()
#open("debug4.out", "w")
Node.debug.write("create %s\n" % index)
def __getattr__(self, key):
if key[0:2] == "__":
raise AttributeError, key
# getattr should never call getattr!
if self.__dict__.has_key("inGetAttr"):
del self.inGetAttr
raise AttributeError, key
prefix, attrname = key[:5], key[5:]
if prefix == "_get_":
self.inGetAttr = 1
if hasattr(self, attrname):
del self.inGetAttr
return (lambda self=self, attrname=attrname:
getattr(self, attrname))
else:
del self.inGetAttr
raise AttributeError, key
else:
self.inGetAttr = 1
try:
func = getattr(self, "_get_" + key)
except AttributeError:
raise AttributeError, key
del self.inGetAttr
return func()
def __nonzero__(self):
return 1
def toxml(self):
writer = _get_StringIO()
self.writexml(writer)
return writer.getvalue()
def toprettyxml(self, indent="\t", newl="\n"):
# indent = the indentation string to prepend, per level
# newl = the newline string to append
writer = _get_StringIO()
self.writexml(writer, "", indent, newl)
return writer.getvalue()
def hasChildNodes(self):
if self.childNodes:
return 1
else:
return 0
def _get_firstChild(self):
if self.childNodes:
return self.childNodes[0]
def _get_lastChild(self):
if self.childNodes:
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))
if newChild.parentNode is not None:
newChild.parentNode.removeChild(newChild)
if refChild is None:
self.appendChild(newChild)
else:
index = self.childNodes.index(refChild)
self.childNodes.insert(index, newChild)
newChild.nextSibling = refChild
refChild.previousSibling = newChild
if index:
node = self.childNodes[index-1]
node.nextSibling = newChild
newChild.previousSibling = node
else:
newChild.previousSibling = None
if self._makeParentNodes:
newChild.parentNode = self
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))
if node.parentNode is not None:
node.parentNode.removeChild(node)
if self.childNodes:
last = self.lastChild
node.previousSibling = last
last.nextSibling = node
else:
node.previousSibling = None
node.nextSibling = None
self.childNodes.append(node)
if self._makeParentNodes:
node.parentNode = self
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))
if newChild.parentNode is not None:
newChild.parentNode.removeChild(newChild)
if newChild is oldChild:
return
index = self.childNodes.index(oldChild)
self.childNodes[index] = newChild
if self._makeParentNodes:
newChild.parentNode = self
oldChild.parentNode = None
newChild.nextSibling = oldChild.nextSibling
newChild.previousSibling = oldChild.previousSibling
oldChild.nextSibling = None
oldChild.previousSibling = None
if newChild.previousSibling:
newChild.previousSibling.nextSibling = newChild
if newChild.nextSibling:
newChild.nextSibling.previousSibling = newChild
return oldChild
def removeChild(self, oldChild):
self.childNodes.remove(oldChild)
if oldChild.nextSibling is not None:
oldChild.nextSibling.previousSibling = oldChild.previousSibling
if oldChild.previousSibling is not None:
oldChild.previousSibling.nextSibling = oldChild.nextSibling
oldChild.nextSibling = oldChild.previousSibling = None
if self._makeParentNodes:
oldChild.parentNode = None
return oldChild
def normalize(self):
L = []
for child in self.childNodes:
if child.nodeType == Node.TEXT_NODE:
data = child.data
if data and L and L[-1].nodeType == child.nodeType:
# collapse text node
node = L[-1]
node.data = node.nodeValue = node.data + child.data
node.nextSibling = child.nextSibling
child.unlink()
elif data:
if L:
L[-1].nextSibling = child
child.previousSibling = L[-1]
else:
child.previousSibling = None
L.append(child)
else:
# empty text node; discard
child.unlink()
else:
if L:
L[-1].nextSibling = child
child.previousSibling = L[-1]
else:
child.previousSibling = None
L.append(child)
if child.nodeType == Node.ELEMENT_NODE:
child.normalize()
self.childNodes[:] = L
def cloneNode(self, deep):
import new
clone = new.instance(self.__class__, self.__dict__.copy())
if self._makeParentNodes:
clone.parentNode = None
clone.childNodes = []
if deep:
for child in self.childNodes:
clone.appendChild(child.cloneNode(1))
return clone
# DOM Level 3 (Working Draft 2001-Jan-26)
def isSameNode(self, other):
return self is other
# minidom-specific API:
def unlink(self):
self.parentNode = self.ownerDocument = None
for child in self.childNodes:
child.unlink()
self.childNodes = None
self.previousSibling = None
self.nextSibling = None
if Node._debug:
index = repr(id(self)) + repr(self.__class__)
self.debug.write("Deleting: %s\n" % index)
del Node.allnodes[index]
def _write_data(writer, data):
"Writes datachars to writer."
replace = _string.replace
data = replace(data, "&", "&")
data = replace(data, "<", "<")
data = replace(data, "\"", """)
data = replace(data, ">", ">")
writer.write(data)
def _getElementsByTagNameHelper(parent, name, rc):
for node in parent.childNodes:
if node.nodeType == Node.ELEMENT_NODE and \
(name == "*" or node.tagName == name):
rc.append(node)
_getElementsByTagNameHelper(node, name, rc)
return rc
def _getElementsByTagNameNSHelper(parent, nsURI, localName, rc):
for node in parent.childNodes:
if node.nodeType == Node.ELEMENT_NODE:
if ((localName == "*" or node.localName == localName) and
(nsURI == "*" or node.namespaceURI == nsURI)):
rc.append(node)
_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
ownerElement = None
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -