import xml.saximport xml.sax.handlerSTART_ELEMENT = "START_ELEMENT"END_ELEMENT = "END_ELEMENT"COMMENT = "COMMENT"START_DOCUMENT = "START_DOCUMENT"END_DOCUMENT = "END_DOCUMENT"PROCESSING_INSTRUCTION = "PROCESSING_INSTRUCTION"IGNORABLE_WHITESPACE = "IGNORABLE_WHITESPACE"CHARACTERS = "CHARACTERS"class PullDOM(xml.sax.ContentHandler):_locator = Nonedocument = Nonedef __init__(self, documentFactory=None):from xml.dom import XML_NAMESPACEself.documentFactory = documentFactoryself.firstEvent = [None, None]self.lastEvent = self.firstEventself.elementStack = []self.push = self.elementStack.appendtry:self.pop = self.elementStack.popexcept AttributeError:# use class' pop insteadpassself._ns_contexts = [{XML_NAMESPACE:'xml'}] # contains uri -> prefix dictsself._current_context = self._ns_contexts[-1]self.pending_events = []def pop(self):result = self.elementStack[-1]del self.elementStack[-1]return resultdef setDocumentLocator(self, locator):self._locator = locatordef startPrefixMapping(self, prefix, uri):if not hasattr(self, '_xmlns_attrs'):self._xmlns_attrs = []self._xmlns_attrs.append((prefix or 'xmlns', uri))self._ns_contexts.append(self._current_context.copy())self._current_context[uri] = prefix or Nonedef endPrefixMapping(self, prefix):self._current_context = self._ns_contexts.pop()def startElementNS(self, name, tagName , attrs):# Retrieve xml namespace declaration attributes.xmlns_uri = 'http://www.w3.org/2000/xmlns/'xmlns_attrs = getattr(self, '_xmlns_attrs', None)if xmlns_attrs is not None:for aname, value in xmlns_attrs:attrs._attrs[(xmlns_uri, aname)] = valueself._xmlns_attrs = []uri, localname = nameif uri:# When using namespaces, the reader may or may not# provide us with the original name. If not, create# *a* valid tagName from the current context.if tagName is None:prefix = self._current_context[uri]if prefix:tagName = prefix + ":" + localnameelse:tagName = localnameif self.document:node = self.document.createElementNS(uri, tagName)else:node = self.buildDocument(uri, tagName)else:# When the tagname is not prefixed, it just appears as# localnameif self.document:node = self.document.createElement(localname)else:node = self.buildDocument(None, localname)for aname,value in attrs.items():a_uri, a_localname = anameif a_uri == xmlns_uri:if a_localname == 'xmlns':qname = a_localnameelse:qname = 'xmlns:' + a_localnameattr = self.document.createAttributeNS(a_uri, qname)node.setAttributeNodeNS(attr)elif a_uri:prefix = self._current_context[a_uri]if prefix:qname = prefix + ":" + a_localnameelse:qname = a_localnameattr = self.document.createAttributeNS(a_uri, qname)node.setAttributeNodeNS(attr)else:attr = self.document.createAttribute(a_localname)node.setAttributeNode(attr)attr.value = valueself.lastEvent[1] = [(START_ELEMENT, node), None]self.lastEvent = self.lastEvent[1]self.push(node)def endElementNS(self, name, tagName):self.lastEvent[1] = [(END_ELEMENT, self.pop()), None]self.lastEvent = self.lastEvent[1]def startElement(self, name, attrs):if self.document:node = self.document.createElement(name)else:node = self.buildDocument(None, name)for aname,value in attrs.items():attr = self.document.createAttribute(aname)attr.value = valuenode.setAttributeNode(attr)self.lastEvent[1] = [(START_ELEMENT, node), None]self.lastEvent = self.lastEvent[1]self.push(node)def endElement(self, name):self.lastEvent[1] = [(END_ELEMENT, self.pop()), None]self.lastEvent = self.lastEvent[1]def comment(self, s):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):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)self.lastEvent[1] = [(IGNORABLE_WHITESPACE, node), None]self.lastEvent = self.lastEvent[1]def characters(self, chars):node = self.document.createTextNode(chars)self.lastEvent[1] = [(CHARACTERS, node), None]self.lastEvent = self.lastEvent[1]def startDocument(self):if self.documentFactory is None:import xml.dom.minidomself.documentFactory = xml.dom.minidom.Document.implementationdef buildDocument(self, uri, tagname):# Can't do that in startDocument, since we need the tagname# XXX: obtain DocumentTypenode = self.documentFactory.createDocument(uri, tagname, None)self.document = nodeself.lastEvent[1] = [(START_DOCUMENT, node), None]self.lastEvent = self.lastEvent[1]self.push(node)# Put everything we have seen so far into the documentfor 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] = eself.lastEvent = eself.pending_events = Nonereturn node.firstChilddef endDocument(self):self.lastEvent[1] = [(END_DOCUMENT, self.document), None]self.pop()def clear(self):"clear(): Explicitly release parsing structures"self.document = Noneclass ErrorHandler:def warning(self, exception):print(exception)def error(self, exception):raise exceptiondef fatalError(self, exception):raise exceptionclass DOMEventStream:def __init__(self, stream, parser, bufsize):self.stream = streamself.parser = parserself.bufsize = bufsizeif not hasattr(self.parser, 'feed'):self.getEvent = self._slurpself.reset()def reset(self):self.pulldom = PullDOM()# This content handler relies on namespace supportself.parser.setFeature(xml.sax.handler.feature_namespaces, 1)self.parser.setContentHandler(self.pulldom)def __getitem__(self, pos):import warningswarnings.warn("DOMEventStream's __getitem__ method ignores 'pos' parameter. ""Use iterator protocol instead.",DeprecationWarning,stacklevel=2)rc = self.getEvent()if rc:return rcraise IndexErrordef __next__(self):rc = self.getEvent()if rc:return rcraise StopIterationdef __iter__(self):return selfdef expandNode(self, node):event = self.getEvent()parents = [node]while event:token, cur_node = eventif cur_node is node:returnif token != END_ELEMENT:parents[-1].appendChild(cur_node)if token == START_ELEMENT:parents.append(cur_node)elif token == END_ELEMENT:del parents[-1]event = self.getEvent()def getEvent(self):# use IncrementalParser interface, so we get the desired# pull effectif not self.pulldom.firstEvent[1]:self.pulldom.lastEvent = self.pulldom.firstEventwhile not self.pulldom.firstEvent[1]:buf = self.stream.read(self.bufsize)if not buf:self.parser.close()return Noneself.parser.feed(buf)rc = self.pulldom.firstEvent[1][0]self.pulldom.firstEvent[1] = self.pulldom.firstEvent[1][1]return rcdef _slurp(self):""" Fallback replacement for getEvent() using thestandard SAX2 interface, which means we slurp theSAX events into memory (no performance gain, butwe are compatible to all SAX parsers)."""self.parser.parse(self.stream)self.getEvent = self._emitreturn self._emit()def _emit(self):""" Fallback replacement for getEvent() that emitsthe events that _slurp() read previously."""rc = self.pulldom.firstEvent[1][0]self.pulldom.firstEvent[1] = self.pulldom.firstEvent[1][1]return rcdef clear(self):"""clear(): Explicitly release parsing objects"""self.pulldom.clear()del self.pulldomself.parser = Noneself.stream = Noneclass SAX2DOM(PullDOM):def startElementNS(self, name, tagName , attrs):PullDOM.startElementNS(self, name, tagName, attrs)curNode = self.elementStack[-1]parentNode = self.elementStack[-2]parentNode.appendChild(curNode)def startElement(self, name, attrs):PullDOM.startElement(self, name, attrs)curNode = self.elementStack[-1]parentNode = self.elementStack[-2]parentNode.appendChild(curNode)def processingInstruction(self, target, data):PullDOM.processingInstruction(self, target, data)node = self.lastEvent[0][1]parentNode = self.elementStack[-1]parentNode.appendChild(node)def ignorableWhitespace(self, chars):PullDOM.ignorableWhitespace(self, chars)node = self.lastEvent[0][1]parentNode = self.elementStack[-1]parentNode.appendChild(node)def characters(self, chars):PullDOM.characters(self, chars)node = self.lastEvent[0][1]parentNode = self.elementStack[-1]parentNode.appendChild(node)default_bufsize = (2 ** 14) - 20def parse(stream_or_string, parser=None, bufsize=None):if bufsize is None:bufsize = default_bufsizeif isinstance(stream_or_string, str):stream = open(stream_or_string, 'rb')else:stream = stream_or_stringif not parser:parser = xml.sax.make_parser()return DOMEventStream(stream, parser, bufsize)def parseString(string, parser=None):from io import StringIObufsize = len(string)buf = StringIO(string)if not parser:parser = xml.sax.make_parser()return DOMEventStream(buf, parser, bufsize)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。