update
This commit is contained in:
27
.CondaPkg/env/Lib/xml/dom/NodeFilter.py
vendored
27
.CondaPkg/env/Lib/xml/dom/NodeFilter.py
vendored
@@ -1,27 +0,0 @@
|
||||
# This is the Python mapping for interface NodeFilter from
|
||||
# DOM2-Traversal-Range. It contains only constants.
|
||||
|
||||
class NodeFilter:
|
||||
"""
|
||||
This is the DOM2 NodeFilter interface. It contains only constants.
|
||||
"""
|
||||
FILTER_ACCEPT = 1
|
||||
FILTER_REJECT = 2
|
||||
FILTER_SKIP = 3
|
||||
|
||||
SHOW_ALL = 0xFFFFFFFF
|
||||
SHOW_ELEMENT = 0x00000001
|
||||
SHOW_ATTRIBUTE = 0x00000002
|
||||
SHOW_TEXT = 0x00000004
|
||||
SHOW_CDATA_SECTION = 0x00000008
|
||||
SHOW_ENTITY_REFERENCE = 0x00000010
|
||||
SHOW_ENTITY = 0x00000020
|
||||
SHOW_PROCESSING_INSTRUCTION = 0x00000040
|
||||
SHOW_COMMENT = 0x00000080
|
||||
SHOW_DOCUMENT = 0x00000100
|
||||
SHOW_DOCUMENT_TYPE = 0x00000200
|
||||
SHOW_DOCUMENT_FRAGMENT = 0x00000400
|
||||
SHOW_NOTATION = 0x00000800
|
||||
|
||||
def acceptNode(self, node):
|
||||
raise NotImplementedError
|
||||
140
.CondaPkg/env/Lib/xml/dom/__init__.py
vendored
140
.CondaPkg/env/Lib/xml/dom/__init__.py
vendored
@@ -1,140 +0,0 @@
|
||||
"""W3C Document Object Model implementation for Python.
|
||||
|
||||
The Python mapping of the Document Object Model is documented in the
|
||||
Python Library Reference in the section on the xml.dom package.
|
||||
|
||||
This package contains the following modules:
|
||||
|
||||
minidom -- A simple implementation of the Level 1 DOM with namespace
|
||||
support added (based on the Level 2 specification) and other
|
||||
minor Level 2 functionality.
|
||||
|
||||
pulldom -- DOM builder supporting on-demand tree-building for selected
|
||||
subtrees of the document.
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class Node:
|
||||
"""Class giving the NodeType constants."""
|
||||
__slots__ = ()
|
||||
|
||||
# DOM implementations may use this as a base class for their own
|
||||
# Node implementations. If they don't, the constants defined here
|
||||
# should still be used as the canonical definitions as they match
|
||||
# the values given in the W3C recommendation. Client code can
|
||||
# safely refer to these values in all tests of Node.nodeType
|
||||
# values.
|
||||
|
||||
ELEMENT_NODE = 1
|
||||
ATTRIBUTE_NODE = 2
|
||||
TEXT_NODE = 3
|
||||
CDATA_SECTION_NODE = 4
|
||||
ENTITY_REFERENCE_NODE = 5
|
||||
ENTITY_NODE = 6
|
||||
PROCESSING_INSTRUCTION_NODE = 7
|
||||
COMMENT_NODE = 8
|
||||
DOCUMENT_NODE = 9
|
||||
DOCUMENT_TYPE_NODE = 10
|
||||
DOCUMENT_FRAGMENT_NODE = 11
|
||||
NOTATION_NODE = 12
|
||||
|
||||
|
||||
#ExceptionCode
|
||||
INDEX_SIZE_ERR = 1
|
||||
DOMSTRING_SIZE_ERR = 2
|
||||
HIERARCHY_REQUEST_ERR = 3
|
||||
WRONG_DOCUMENT_ERR = 4
|
||||
INVALID_CHARACTER_ERR = 5
|
||||
NO_DATA_ALLOWED_ERR = 6
|
||||
NO_MODIFICATION_ALLOWED_ERR = 7
|
||||
NOT_FOUND_ERR = 8
|
||||
NOT_SUPPORTED_ERR = 9
|
||||
INUSE_ATTRIBUTE_ERR = 10
|
||||
INVALID_STATE_ERR = 11
|
||||
SYNTAX_ERR = 12
|
||||
INVALID_MODIFICATION_ERR = 13
|
||||
NAMESPACE_ERR = 14
|
||||
INVALID_ACCESS_ERR = 15
|
||||
VALIDATION_ERR = 16
|
||||
|
||||
|
||||
class DOMException(Exception):
|
||||
"""Abstract base class for DOM exceptions.
|
||||
Exceptions with specific codes are specializations of this class."""
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
if self.__class__ is DOMException:
|
||||
raise RuntimeError(
|
||||
"DOMException should not be instantiated directly")
|
||||
Exception.__init__(self, *args, **kw)
|
||||
|
||||
def _get_code(self):
|
||||
return self.code
|
||||
|
||||
|
||||
class IndexSizeErr(DOMException):
|
||||
code = INDEX_SIZE_ERR
|
||||
|
||||
class DomstringSizeErr(DOMException):
|
||||
code = DOMSTRING_SIZE_ERR
|
||||
|
||||
class HierarchyRequestErr(DOMException):
|
||||
code = HIERARCHY_REQUEST_ERR
|
||||
|
||||
class WrongDocumentErr(DOMException):
|
||||
code = WRONG_DOCUMENT_ERR
|
||||
|
||||
class InvalidCharacterErr(DOMException):
|
||||
code = INVALID_CHARACTER_ERR
|
||||
|
||||
class NoDataAllowedErr(DOMException):
|
||||
code = NO_DATA_ALLOWED_ERR
|
||||
|
||||
class NoModificationAllowedErr(DOMException):
|
||||
code = NO_MODIFICATION_ALLOWED_ERR
|
||||
|
||||
class NotFoundErr(DOMException):
|
||||
code = NOT_FOUND_ERR
|
||||
|
||||
class NotSupportedErr(DOMException):
|
||||
code = NOT_SUPPORTED_ERR
|
||||
|
||||
class InuseAttributeErr(DOMException):
|
||||
code = INUSE_ATTRIBUTE_ERR
|
||||
|
||||
class InvalidStateErr(DOMException):
|
||||
code = INVALID_STATE_ERR
|
||||
|
||||
class SyntaxErr(DOMException):
|
||||
code = SYNTAX_ERR
|
||||
|
||||
class InvalidModificationErr(DOMException):
|
||||
code = INVALID_MODIFICATION_ERR
|
||||
|
||||
class NamespaceErr(DOMException):
|
||||
code = NAMESPACE_ERR
|
||||
|
||||
class InvalidAccessErr(DOMException):
|
||||
code = INVALID_ACCESS_ERR
|
||||
|
||||
class ValidationErr(DOMException):
|
||||
code = VALIDATION_ERR
|
||||
|
||||
class UserDataHandler:
|
||||
"""Class giving the operation constants for UserDataHandler.handle()."""
|
||||
|
||||
# Based on DOM Level 3 (WD 9 April 2002)
|
||||
|
||||
NODE_CLONED = 1
|
||||
NODE_IMPORTED = 2
|
||||
NODE_DELETED = 3
|
||||
NODE_RENAMED = 4
|
||||
|
||||
XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace"
|
||||
XMLNS_NAMESPACE = "http://www.w3.org/2000/xmlns/"
|
||||
XHTML_NAMESPACE = "http://www.w3.org/1999/xhtml"
|
||||
EMPTY_NAMESPACE = None
|
||||
EMPTY_PREFIX = None
|
||||
|
||||
from .domreg import getDOMImplementation, registerDOMImplementation
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
99
.CondaPkg/env/Lib/xml/dom/domreg.py
vendored
99
.CondaPkg/env/Lib/xml/dom/domreg.py
vendored
@@ -1,99 +0,0 @@
|
||||
"""Registration facilities for DOM. This module should not be used
|
||||
directly. Instead, the functions getDOMImplementation and
|
||||
registerDOMImplementation should be imported from xml.dom."""
|
||||
|
||||
# This is a list of well-known implementations. Well-known names
|
||||
# should be published by posting to xml-sig@python.org, and are
|
||||
# subsequently recorded in this file.
|
||||
|
||||
import sys
|
||||
|
||||
well_known_implementations = {
|
||||
'minidom':'xml.dom.minidom',
|
||||
'4DOM': 'xml.dom.DOMImplementation',
|
||||
}
|
||||
|
||||
# DOM implementations not officially registered should register
|
||||
# themselves with their
|
||||
|
||||
registered = {}
|
||||
|
||||
def registerDOMImplementation(name, factory):
|
||||
"""registerDOMImplementation(name, factory)
|
||||
|
||||
Register the factory function with the name. The factory function
|
||||
should return an object which implements the DOMImplementation
|
||||
interface. The factory function can either return the same object,
|
||||
or a new one (e.g. if that implementation supports some
|
||||
customization)."""
|
||||
|
||||
registered[name] = factory
|
||||
|
||||
def _good_enough(dom, features):
|
||||
"_good_enough(dom, features) -> Return 1 if the dom offers the features"
|
||||
for f,v in features:
|
||||
if not dom.hasFeature(f,v):
|
||||
return 0
|
||||
return 1
|
||||
|
||||
def getDOMImplementation(name=None, features=()):
|
||||
"""getDOMImplementation(name = None, features = ()) -> DOM implementation.
|
||||
|
||||
Return a suitable DOM implementation. The name is either
|
||||
well-known, the module name of a DOM implementation, or None. If
|
||||
it is not None, imports the corresponding module and returns
|
||||
DOMImplementation object if the import succeeds.
|
||||
|
||||
If name is not given, consider the available implementations to
|
||||
find one with the required feature set. If no implementation can
|
||||
be found, raise an ImportError. The features list must be a sequence
|
||||
of (feature, version) pairs which are passed to hasFeature."""
|
||||
|
||||
import os
|
||||
creator = None
|
||||
mod = well_known_implementations.get(name)
|
||||
if mod:
|
||||
mod = __import__(mod, {}, {}, ['getDOMImplementation'])
|
||||
return mod.getDOMImplementation()
|
||||
elif name:
|
||||
return registered[name]()
|
||||
elif not sys.flags.ignore_environment and "PYTHON_DOM" in os.environ:
|
||||
return getDOMImplementation(name = os.environ["PYTHON_DOM"])
|
||||
|
||||
# User did not specify a name, try implementations in arbitrary
|
||||
# order, returning the one that has the required features
|
||||
if isinstance(features, str):
|
||||
features = _parse_feature_string(features)
|
||||
for creator in registered.values():
|
||||
dom = creator()
|
||||
if _good_enough(dom, features):
|
||||
return dom
|
||||
|
||||
for creator in well_known_implementations.keys():
|
||||
try:
|
||||
dom = getDOMImplementation(name = creator)
|
||||
except Exception: # typically ImportError, or AttributeError
|
||||
continue
|
||||
if _good_enough(dom, features):
|
||||
return dom
|
||||
|
||||
raise ImportError("no suitable DOM implementation found")
|
||||
|
||||
def _parse_feature_string(s):
|
||||
features = []
|
||||
parts = s.split()
|
||||
i = 0
|
||||
length = len(parts)
|
||||
while i < length:
|
||||
feature = parts[i]
|
||||
if feature[0] in "0123456789":
|
||||
raise ValueError("bad feature name: %r" % (feature,))
|
||||
i = i + 1
|
||||
version = None
|
||||
if i < length:
|
||||
v = parts[i]
|
||||
if v[0] in "0123456789":
|
||||
i = i + 1
|
||||
version = v
|
||||
features.append((feature, version))
|
||||
return tuple(features)
|
||||
965
.CondaPkg/env/Lib/xml/dom/expatbuilder.py
vendored
965
.CondaPkg/env/Lib/xml/dom/expatbuilder.py
vendored
@@ -1,965 +0,0 @@
|
||||
"""Facility to use the Expat parser to load a minidom instance
|
||||
from a string or file.
|
||||
|
||||
This avoids all the overhead of SAX and pulldom to gain performance.
|
||||
"""
|
||||
|
||||
# Warning!
|
||||
#
|
||||
# This module is tightly bound to the implementation details of the
|
||||
# minidom DOM and can't be used with other DOM implementations. This
|
||||
# is due, in part, to a lack of appropriate methods in the DOM (there is
|
||||
# no way to create Entity and Notation nodes via the DOM Level 2
|
||||
# interface), and for performance. The latter is the cause of some fairly
|
||||
# cryptic code.
|
||||
#
|
||||
# Performance hacks:
|
||||
#
|
||||
# - .character_data_handler() has an extra case in which continuing
|
||||
# data is appended to an existing Text node; this can be a
|
||||
# speedup since pyexpat can break up character data into multiple
|
||||
# callbacks even though we set the buffer_text attribute on the
|
||||
# parser. This also gives us the advantage that we don't need a
|
||||
# separate normalization pass.
|
||||
#
|
||||
# - Determining that a node exists is done using an identity comparison
|
||||
# with None rather than a truth test; this avoids searching for and
|
||||
# calling any methods on the node object if it exists. (A rather
|
||||
# nice speedup is achieved this way as well!)
|
||||
|
||||
from xml.dom import xmlbuilder, minidom, Node
|
||||
from xml.dom import EMPTY_NAMESPACE, EMPTY_PREFIX, XMLNS_NAMESPACE
|
||||
from xml.parsers import expat
|
||||
from xml.dom.minidom import _append_child, _set_attribute_node
|
||||
from xml.dom.NodeFilter import NodeFilter
|
||||
|
||||
TEXT_NODE = Node.TEXT_NODE
|
||||
CDATA_SECTION_NODE = Node.CDATA_SECTION_NODE
|
||||
DOCUMENT_NODE = Node.DOCUMENT_NODE
|
||||
|
||||
FILTER_ACCEPT = xmlbuilder.DOMBuilderFilter.FILTER_ACCEPT
|
||||
FILTER_REJECT = xmlbuilder.DOMBuilderFilter.FILTER_REJECT
|
||||
FILTER_SKIP = xmlbuilder.DOMBuilderFilter.FILTER_SKIP
|
||||
FILTER_INTERRUPT = xmlbuilder.DOMBuilderFilter.FILTER_INTERRUPT
|
||||
|
||||
theDOMImplementation = minidom.getDOMImplementation()
|
||||
|
||||
# Expat typename -> TypeInfo
|
||||
_typeinfo_map = {
|
||||
"CDATA": minidom.TypeInfo(None, "cdata"),
|
||||
"ENUM": minidom.TypeInfo(None, "enumeration"),
|
||||
"ENTITY": minidom.TypeInfo(None, "entity"),
|
||||
"ENTITIES": minidom.TypeInfo(None, "entities"),
|
||||
"ID": minidom.TypeInfo(None, "id"),
|
||||
"IDREF": minidom.TypeInfo(None, "idref"),
|
||||
"IDREFS": minidom.TypeInfo(None, "idrefs"),
|
||||
"NMTOKEN": minidom.TypeInfo(None, "nmtoken"),
|
||||
"NMTOKENS": minidom.TypeInfo(None, "nmtokens"),
|
||||
}
|
||||
|
||||
class ElementInfo(object):
|
||||
__slots__ = '_attr_info', '_model', 'tagName'
|
||||
|
||||
def __init__(self, tagName, model=None):
|
||||
self.tagName = tagName
|
||||
self._attr_info = []
|
||||
self._model = model
|
||||
|
||||
def __getstate__(self):
|
||||
return self._attr_info, self._model, self.tagName
|
||||
|
||||
def __setstate__(self, state):
|
||||
self._attr_info, self._model, self.tagName = state
|
||||
|
||||
def getAttributeType(self, aname):
|
||||
for info in self._attr_info:
|
||||
if info[1] == aname:
|
||||
t = info[-2]
|
||||
if t[0] == "(":
|
||||
return _typeinfo_map["ENUM"]
|
||||
else:
|
||||
return _typeinfo_map[info[-2]]
|
||||
return minidom._no_type
|
||||
|
||||
def getAttributeTypeNS(self, namespaceURI, localName):
|
||||
return minidom._no_type
|
||||
|
||||
def isElementContent(self):
|
||||
if self._model:
|
||||
type = self._model[0]
|
||||
return type not in (expat.model.XML_CTYPE_ANY,
|
||||
expat.model.XML_CTYPE_MIXED)
|
||||
else:
|
||||
return False
|
||||
|
||||
def isEmpty(self):
|
||||
if self._model:
|
||||
return self._model[0] == expat.model.XML_CTYPE_EMPTY
|
||||
else:
|
||||
return False
|
||||
|
||||
def isId(self, aname):
|
||||
for info in self._attr_info:
|
||||
if info[1] == aname:
|
||||
return info[-2] == "ID"
|
||||
return False
|
||||
|
||||
def isIdNS(self, euri, ename, auri, aname):
|
||||
# not sure this is meaningful
|
||||
return self.isId((auri, aname))
|
||||
|
||||
def _intern(builder, s):
|
||||
return builder._intern_setdefault(s, s)
|
||||
|
||||
def _parse_ns_name(builder, name):
|
||||
assert ' ' in name
|
||||
parts = name.split(' ')
|
||||
intern = builder._intern_setdefault
|
||||
if len(parts) == 3:
|
||||
uri, localname, prefix = parts
|
||||
prefix = intern(prefix, prefix)
|
||||
qname = "%s:%s" % (prefix, localname)
|
||||
qname = intern(qname, qname)
|
||||
localname = intern(localname, localname)
|
||||
elif len(parts) == 2:
|
||||
uri, localname = parts
|
||||
prefix = EMPTY_PREFIX
|
||||
qname = localname = intern(localname, localname)
|
||||
else:
|
||||
raise ValueError("Unsupported syntax: spaces in URIs not supported: %r" % name)
|
||||
return intern(uri, uri), localname, prefix, qname
|
||||
|
||||
|
||||
class ExpatBuilder:
|
||||
"""Document builder that uses Expat to build a ParsedXML.DOM document
|
||||
instance."""
|
||||
|
||||
def __init__(self, options=None):
|
||||
if options is None:
|
||||
options = xmlbuilder.Options()
|
||||
self._options = options
|
||||
if self._options.filter is not None:
|
||||
self._filter = FilterVisibilityController(self._options.filter)
|
||||
else:
|
||||
self._filter = None
|
||||
# This *really* doesn't do anything in this case, so
|
||||
# override it with something fast & minimal.
|
||||
self._finish_start_element = id
|
||||
self._parser = None
|
||||
self.reset()
|
||||
|
||||
def createParser(self):
|
||||
"""Create a new parser object."""
|
||||
return expat.ParserCreate()
|
||||
|
||||
def getParser(self):
|
||||
"""Return the parser object, creating a new one if needed."""
|
||||
if not self._parser:
|
||||
self._parser = self.createParser()
|
||||
self._intern_setdefault = self._parser.intern.setdefault
|
||||
self._parser.buffer_text = True
|
||||
self._parser.ordered_attributes = True
|
||||
self._parser.specified_attributes = True
|
||||
self.install(self._parser)
|
||||
return self._parser
|
||||
|
||||
def reset(self):
|
||||
"""Free all data structures used during DOM construction."""
|
||||
self.document = theDOMImplementation.createDocument(
|
||||
EMPTY_NAMESPACE, None, None)
|
||||
self.curNode = self.document
|
||||
self._elem_info = self.document._elem_info
|
||||
self._cdata = False
|
||||
|
||||
def install(self, parser):
|
||||
"""Install the callbacks needed to build the DOM into the parser."""
|
||||
# This creates circular references!
|
||||
parser.StartDoctypeDeclHandler = self.start_doctype_decl_handler
|
||||
parser.StartElementHandler = self.first_element_handler
|
||||
parser.EndElementHandler = self.end_element_handler
|
||||
parser.ProcessingInstructionHandler = self.pi_handler
|
||||
if self._options.entities:
|
||||
parser.EntityDeclHandler = self.entity_decl_handler
|
||||
parser.NotationDeclHandler = self.notation_decl_handler
|
||||
if self._options.comments:
|
||||
parser.CommentHandler = self.comment_handler
|
||||
if self._options.cdata_sections:
|
||||
parser.StartCdataSectionHandler = self.start_cdata_section_handler
|
||||
parser.EndCdataSectionHandler = self.end_cdata_section_handler
|
||||
parser.CharacterDataHandler = self.character_data_handler_cdata
|
||||
else:
|
||||
parser.CharacterDataHandler = self.character_data_handler
|
||||
parser.ExternalEntityRefHandler = self.external_entity_ref_handler
|
||||
parser.XmlDeclHandler = self.xml_decl_handler
|
||||
parser.ElementDeclHandler = self.element_decl_handler
|
||||
parser.AttlistDeclHandler = self.attlist_decl_handler
|
||||
|
||||
def parseFile(self, file):
|
||||
"""Parse a document from a file object, returning the document
|
||||
node."""
|
||||
parser = self.getParser()
|
||||
first_buffer = True
|
||||
try:
|
||||
while 1:
|
||||
buffer = file.read(16*1024)
|
||||
if not buffer:
|
||||
break
|
||||
parser.Parse(buffer, False)
|
||||
if first_buffer and self.document.documentElement:
|
||||
self._setup_subset(buffer)
|
||||
first_buffer = False
|
||||
parser.Parse(b"", True)
|
||||
except ParseEscape:
|
||||
pass
|
||||
doc = self.document
|
||||
self.reset()
|
||||
self._parser = None
|
||||
return doc
|
||||
|
||||
def parseString(self, string):
|
||||
"""Parse a document from a string, returning the document node."""
|
||||
parser = self.getParser()
|
||||
try:
|
||||
parser.Parse(string, True)
|
||||
self._setup_subset(string)
|
||||
except ParseEscape:
|
||||
pass
|
||||
doc = self.document
|
||||
self.reset()
|
||||
self._parser = None
|
||||
return doc
|
||||
|
||||
def _setup_subset(self, buffer):
|
||||
"""Load the internal subset if there might be one."""
|
||||
if self.document.doctype:
|
||||
extractor = InternalSubsetExtractor()
|
||||
extractor.parseString(buffer)
|
||||
subset = extractor.getSubset()
|
||||
self.document.doctype.internalSubset = subset
|
||||
|
||||
def start_doctype_decl_handler(self, doctypeName, systemId, publicId,
|
||||
has_internal_subset):
|
||||
doctype = self.document.implementation.createDocumentType(
|
||||
doctypeName, publicId, systemId)
|
||||
doctype.ownerDocument = self.document
|
||||
_append_child(self.document, doctype)
|
||||
self.document.doctype = doctype
|
||||
if self._filter and self._filter.acceptNode(doctype) == FILTER_REJECT:
|
||||
self.document.doctype = None
|
||||
del self.document.childNodes[-1]
|
||||
doctype = None
|
||||
self._parser.EntityDeclHandler = None
|
||||
self._parser.NotationDeclHandler = None
|
||||
if has_internal_subset:
|
||||
if doctype is not None:
|
||||
doctype.entities._seq = []
|
||||
doctype.notations._seq = []
|
||||
self._parser.CommentHandler = None
|
||||
self._parser.ProcessingInstructionHandler = None
|
||||
self._parser.EndDoctypeDeclHandler = self.end_doctype_decl_handler
|
||||
|
||||
def end_doctype_decl_handler(self):
|
||||
if self._options.comments:
|
||||
self._parser.CommentHandler = self.comment_handler
|
||||
self._parser.ProcessingInstructionHandler = self.pi_handler
|
||||
if not (self._elem_info or self._filter):
|
||||
self._finish_end_element = id
|
||||
|
||||
def pi_handler(self, target, data):
|
||||
node = self.document.createProcessingInstruction(target, data)
|
||||
_append_child(self.curNode, node)
|
||||
if self._filter and self._filter.acceptNode(node) == FILTER_REJECT:
|
||||
self.curNode.removeChild(node)
|
||||
|
||||
def character_data_handler_cdata(self, data):
|
||||
childNodes = self.curNode.childNodes
|
||||
if self._cdata:
|
||||
if ( self._cdata_continue
|
||||
and childNodes[-1].nodeType == CDATA_SECTION_NODE):
|
||||
childNodes[-1].appendData(data)
|
||||
return
|
||||
node = self.document.createCDATASection(data)
|
||||
self._cdata_continue = True
|
||||
elif childNodes and childNodes[-1].nodeType == TEXT_NODE:
|
||||
node = childNodes[-1]
|
||||
value = node.data + data
|
||||
node.data = value
|
||||
return
|
||||
else:
|
||||
node = minidom.Text()
|
||||
node.data = data
|
||||
node.ownerDocument = self.document
|
||||
_append_child(self.curNode, node)
|
||||
|
||||
def character_data_handler(self, data):
|
||||
childNodes = self.curNode.childNodes
|
||||
if childNodes and childNodes[-1].nodeType == TEXT_NODE:
|
||||
node = childNodes[-1]
|
||||
node.data = node.data + data
|
||||
return
|
||||
node = minidom.Text()
|
||||
node.data = node.data + data
|
||||
node.ownerDocument = self.document
|
||||
_append_child(self.curNode, node)
|
||||
|
||||
def entity_decl_handler(self, entityName, is_parameter_entity, value,
|
||||
base, systemId, publicId, notationName):
|
||||
if is_parameter_entity:
|
||||
# we don't care about parameter entities for the DOM
|
||||
return
|
||||
if not self._options.entities:
|
||||
return
|
||||
node = self.document._create_entity(entityName, publicId,
|
||||
systemId, notationName)
|
||||
if value is not None:
|
||||
# internal entity
|
||||
# node *should* be readonly, but we'll cheat
|
||||
child = self.document.createTextNode(value)
|
||||
node.childNodes.append(child)
|
||||
self.document.doctype.entities._seq.append(node)
|
||||
if self._filter and self._filter.acceptNode(node) == FILTER_REJECT:
|
||||
del self.document.doctype.entities._seq[-1]
|
||||
|
||||
def notation_decl_handler(self, notationName, base, systemId, publicId):
|
||||
node = self.document._create_notation(notationName, publicId, systemId)
|
||||
self.document.doctype.notations._seq.append(node)
|
||||
if self._filter and self._filter.acceptNode(node) == FILTER_ACCEPT:
|
||||
del self.document.doctype.notations._seq[-1]
|
||||
|
||||
def comment_handler(self, data):
|
||||
node = self.document.createComment(data)
|
||||
_append_child(self.curNode, node)
|
||||
if self._filter and self._filter.acceptNode(node) == FILTER_REJECT:
|
||||
self.curNode.removeChild(node)
|
||||
|
||||
def start_cdata_section_handler(self):
|
||||
self._cdata = True
|
||||
self._cdata_continue = False
|
||||
|
||||
def end_cdata_section_handler(self):
|
||||
self._cdata = False
|
||||
self._cdata_continue = False
|
||||
|
||||
def external_entity_ref_handler(self, context, base, systemId, publicId):
|
||||
return 1
|
||||
|
||||
def first_element_handler(self, name, attributes):
|
||||
if self._filter is None and not self._elem_info:
|
||||
self._finish_end_element = id
|
||||
self.getParser().StartElementHandler = self.start_element_handler
|
||||
self.start_element_handler(name, attributes)
|
||||
|
||||
def start_element_handler(self, name, attributes):
|
||||
node = self.document.createElement(name)
|
||||
_append_child(self.curNode, node)
|
||||
self.curNode = node
|
||||
|
||||
if attributes:
|
||||
for i in range(0, len(attributes), 2):
|
||||
a = minidom.Attr(attributes[i], EMPTY_NAMESPACE,
|
||||
None, EMPTY_PREFIX)
|
||||
value = attributes[i+1]
|
||||
a.value = value
|
||||
a.ownerDocument = self.document
|
||||
_set_attribute_node(node, a)
|
||||
|
||||
if node is not self.document.documentElement:
|
||||
self._finish_start_element(node)
|
||||
|
||||
def _finish_start_element(self, node):
|
||||
if self._filter:
|
||||
# To be general, we'd have to call isSameNode(), but this
|
||||
# is sufficient for minidom:
|
||||
if node is self.document.documentElement:
|
||||
return
|
||||
filt = self._filter.startContainer(node)
|
||||
if filt == FILTER_REJECT:
|
||||
# ignore this node & all descendents
|
||||
Rejecter(self)
|
||||
elif filt == FILTER_SKIP:
|
||||
# ignore this node, but make it's children become
|
||||
# children of the parent node
|
||||
Skipper(self)
|
||||
else:
|
||||
return
|
||||
self.curNode = node.parentNode
|
||||
node.parentNode.removeChild(node)
|
||||
node.unlink()
|
||||
|
||||
# If this ever changes, Namespaces.end_element_handler() needs to
|
||||
# be changed to match.
|
||||
#
|
||||
def end_element_handler(self, name):
|
||||
curNode = self.curNode
|
||||
self.curNode = curNode.parentNode
|
||||
self._finish_end_element(curNode)
|
||||
|
||||
def _finish_end_element(self, curNode):
|
||||
info = self._elem_info.get(curNode.tagName)
|
||||
if info:
|
||||
self._handle_white_text_nodes(curNode, info)
|
||||
if self._filter:
|
||||
if curNode is self.document.documentElement:
|
||||
return
|
||||
if self._filter.acceptNode(curNode) == FILTER_REJECT:
|
||||
self.curNode.removeChild(curNode)
|
||||
curNode.unlink()
|
||||
|
||||
def _handle_white_text_nodes(self, node, info):
|
||||
if (self._options.whitespace_in_element_content
|
||||
or not info.isElementContent()):
|
||||
return
|
||||
|
||||
# We have element type information and should remove ignorable
|
||||
# whitespace; identify for text nodes which contain only
|
||||
# whitespace.
|
||||
L = []
|
||||
for child in node.childNodes:
|
||||
if child.nodeType == TEXT_NODE and not child.data.strip():
|
||||
L.append(child)
|
||||
|
||||
# Remove ignorable whitespace from the tree.
|
||||
for child in L:
|
||||
node.removeChild(child)
|
||||
|
||||
def element_decl_handler(self, name, model):
|
||||
info = self._elem_info.get(name)
|
||||
if info is None:
|
||||
self._elem_info[name] = ElementInfo(name, model)
|
||||
else:
|
||||
assert info._model is None
|
||||
info._model = model
|
||||
|
||||
def attlist_decl_handler(self, elem, name, type, default, required):
|
||||
info = self._elem_info.get(elem)
|
||||
if info is None:
|
||||
info = ElementInfo(elem)
|
||||
self._elem_info[elem] = info
|
||||
info._attr_info.append(
|
||||
[None, name, None, None, default, 0, type, required])
|
||||
|
||||
def xml_decl_handler(self, version, encoding, standalone):
|
||||
self.document.version = version
|
||||
self.document.encoding = encoding
|
||||
# This is still a little ugly, thanks to the pyexpat API. ;-(
|
||||
if standalone >= 0:
|
||||
if standalone:
|
||||
self.document.standalone = True
|
||||
else:
|
||||
self.document.standalone = False
|
||||
|
||||
|
||||
# Don't include FILTER_INTERRUPT, since that's checked separately
|
||||
# where allowed.
|
||||
_ALLOWED_FILTER_RETURNS = (FILTER_ACCEPT, FILTER_REJECT, FILTER_SKIP)
|
||||
|
||||
class FilterVisibilityController(object):
|
||||
"""Wrapper around a DOMBuilderFilter which implements the checks
|
||||
to make the whatToShow filter attribute work."""
|
||||
|
||||
__slots__ = 'filter',
|
||||
|
||||
def __init__(self, filter):
|
||||
self.filter = filter
|
||||
|
||||
def startContainer(self, node):
|
||||
mask = self._nodetype_mask[node.nodeType]
|
||||
if self.filter.whatToShow & mask:
|
||||
val = self.filter.startContainer(node)
|
||||
if val == FILTER_INTERRUPT:
|
||||
raise ParseEscape
|
||||
if val not in _ALLOWED_FILTER_RETURNS:
|
||||
raise ValueError(
|
||||
"startContainer() returned illegal value: " + repr(val))
|
||||
return val
|
||||
else:
|
||||
return FILTER_ACCEPT
|
||||
|
||||
def acceptNode(self, node):
|
||||
mask = self._nodetype_mask[node.nodeType]
|
||||
if self.filter.whatToShow & mask:
|
||||
val = self.filter.acceptNode(node)
|
||||
if val == FILTER_INTERRUPT:
|
||||
raise ParseEscape
|
||||
if val == FILTER_SKIP:
|
||||
# move all child nodes to the parent, and remove this node
|
||||
parent = node.parentNode
|
||||
for child in node.childNodes[:]:
|
||||
parent.appendChild(child)
|
||||
# node is handled by the caller
|
||||
return FILTER_REJECT
|
||||
if val not in _ALLOWED_FILTER_RETURNS:
|
||||
raise ValueError(
|
||||
"acceptNode() returned illegal value: " + repr(val))
|
||||
return val
|
||||
else:
|
||||
return FILTER_ACCEPT
|
||||
|
||||
_nodetype_mask = {
|
||||
Node.ELEMENT_NODE: NodeFilter.SHOW_ELEMENT,
|
||||
Node.ATTRIBUTE_NODE: NodeFilter.SHOW_ATTRIBUTE,
|
||||
Node.TEXT_NODE: NodeFilter.SHOW_TEXT,
|
||||
Node.CDATA_SECTION_NODE: NodeFilter.SHOW_CDATA_SECTION,
|
||||
Node.ENTITY_REFERENCE_NODE: NodeFilter.SHOW_ENTITY_REFERENCE,
|
||||
Node.ENTITY_NODE: NodeFilter.SHOW_ENTITY,
|
||||
Node.PROCESSING_INSTRUCTION_NODE: NodeFilter.SHOW_PROCESSING_INSTRUCTION,
|
||||
Node.COMMENT_NODE: NodeFilter.SHOW_COMMENT,
|
||||
Node.DOCUMENT_NODE: NodeFilter.SHOW_DOCUMENT,
|
||||
Node.DOCUMENT_TYPE_NODE: NodeFilter.SHOW_DOCUMENT_TYPE,
|
||||
Node.DOCUMENT_FRAGMENT_NODE: NodeFilter.SHOW_DOCUMENT_FRAGMENT,
|
||||
Node.NOTATION_NODE: NodeFilter.SHOW_NOTATION,
|
||||
}
|
||||
|
||||
|
||||
class FilterCrutch(object):
|
||||
__slots__ = '_builder', '_level', '_old_start', '_old_end'
|
||||
|
||||
def __init__(self, builder):
|
||||
self._level = 0
|
||||
self._builder = builder
|
||||
parser = builder._parser
|
||||
self._old_start = parser.StartElementHandler
|
||||
self._old_end = parser.EndElementHandler
|
||||
parser.StartElementHandler = self.start_element_handler
|
||||
parser.EndElementHandler = self.end_element_handler
|
||||
|
||||
class Rejecter(FilterCrutch):
|
||||
__slots__ = ()
|
||||
|
||||
def __init__(self, builder):
|
||||
FilterCrutch.__init__(self, builder)
|
||||
parser = builder._parser
|
||||
for name in ("ProcessingInstructionHandler",
|
||||
"CommentHandler",
|
||||
"CharacterDataHandler",
|
||||
"StartCdataSectionHandler",
|
||||
"EndCdataSectionHandler",
|
||||
"ExternalEntityRefHandler",
|
||||
):
|
||||
setattr(parser, name, None)
|
||||
|
||||
def start_element_handler(self, *args):
|
||||
self._level = self._level + 1
|
||||
|
||||
def end_element_handler(self, *args):
|
||||
if self._level == 0:
|
||||
# restore the old handlers
|
||||
parser = self._builder._parser
|
||||
self._builder.install(parser)
|
||||
parser.StartElementHandler = self._old_start
|
||||
parser.EndElementHandler = self._old_end
|
||||
else:
|
||||
self._level = self._level - 1
|
||||
|
||||
class Skipper(FilterCrutch):
|
||||
__slots__ = ()
|
||||
|
||||
def start_element_handler(self, *args):
|
||||
node = self._builder.curNode
|
||||
self._old_start(*args)
|
||||
if self._builder.curNode is not node:
|
||||
self._level = self._level + 1
|
||||
|
||||
def end_element_handler(self, *args):
|
||||
if self._level == 0:
|
||||
# We're popping back out of the node we're skipping, so we
|
||||
# shouldn't need to do anything but reset the handlers.
|
||||
self._builder._parser.StartElementHandler = self._old_start
|
||||
self._builder._parser.EndElementHandler = self._old_end
|
||||
self._builder = None
|
||||
else:
|
||||
self._level = self._level - 1
|
||||
self._old_end(*args)
|
||||
|
||||
|
||||
# framework document used by the fragment builder.
|
||||
# Takes a string for the doctype, subset string, and namespace attrs string.
|
||||
|
||||
_FRAGMENT_BUILDER_INTERNAL_SYSTEM_ID = \
|
||||
"http://xml.python.org/entities/fragment-builder/internal"
|
||||
|
||||
_FRAGMENT_BUILDER_TEMPLATE = (
|
||||
'''\
|
||||
<!DOCTYPE wrapper
|
||||
%%s [
|
||||
<!ENTITY fragment-builder-internal
|
||||
SYSTEM "%s">
|
||||
%%s
|
||||
]>
|
||||
<wrapper %%s
|
||||
>&fragment-builder-internal;</wrapper>'''
|
||||
% _FRAGMENT_BUILDER_INTERNAL_SYSTEM_ID)
|
||||
|
||||
|
||||
class FragmentBuilder(ExpatBuilder):
|
||||
"""Builder which constructs document fragments given XML source
|
||||
text and a context node.
|
||||
|
||||
The context node is expected to provide information about the
|
||||
namespace declarations which are in scope at the start of the
|
||||
fragment.
|
||||
"""
|
||||
|
||||
def __init__(self, context, options=None):
|
||||
if context.nodeType == DOCUMENT_NODE:
|
||||
self.originalDocument = context
|
||||
self.context = context
|
||||
else:
|
||||
self.originalDocument = context.ownerDocument
|
||||
self.context = context
|
||||
ExpatBuilder.__init__(self, options)
|
||||
|
||||
def reset(self):
|
||||
ExpatBuilder.reset(self)
|
||||
self.fragment = None
|
||||
|
||||
def parseFile(self, file):
|
||||
"""Parse a document fragment from a file object, returning the
|
||||
fragment node."""
|
||||
return self.parseString(file.read())
|
||||
|
||||
def parseString(self, string):
|
||||
"""Parse a document fragment from a string, returning the
|
||||
fragment node."""
|
||||
self._source = string
|
||||
parser = self.getParser()
|
||||
doctype = self.originalDocument.doctype
|
||||
ident = ""
|
||||
if doctype:
|
||||
subset = doctype.internalSubset or self._getDeclarations()
|
||||
if doctype.publicId:
|
||||
ident = ('PUBLIC "%s" "%s"'
|
||||
% (doctype.publicId, doctype.systemId))
|
||||
elif doctype.systemId:
|
||||
ident = 'SYSTEM "%s"' % doctype.systemId
|
||||
else:
|
||||
subset = ""
|
||||
nsattrs = self._getNSattrs() # get ns decls from node's ancestors
|
||||
document = _FRAGMENT_BUILDER_TEMPLATE % (ident, subset, nsattrs)
|
||||
try:
|
||||
parser.Parse(document, True)
|
||||
except:
|
||||
self.reset()
|
||||
raise
|
||||
fragment = self.fragment
|
||||
self.reset()
|
||||
## self._parser = None
|
||||
return fragment
|
||||
|
||||
def _getDeclarations(self):
|
||||
"""Re-create the internal subset from the DocumentType node.
|
||||
|
||||
This is only needed if we don't already have the
|
||||
internalSubset as a string.
|
||||
"""
|
||||
doctype = self.context.ownerDocument.doctype
|
||||
s = ""
|
||||
if doctype:
|
||||
for i in range(doctype.notations.length):
|
||||
notation = doctype.notations.item(i)
|
||||
if s:
|
||||
s = s + "\n "
|
||||
s = "%s<!NOTATION %s" % (s, notation.nodeName)
|
||||
if notation.publicId:
|
||||
s = '%s PUBLIC "%s"\n "%s">' \
|
||||
% (s, notation.publicId, notation.systemId)
|
||||
else:
|
||||
s = '%s SYSTEM "%s">' % (s, notation.systemId)
|
||||
for i in range(doctype.entities.length):
|
||||
entity = doctype.entities.item(i)
|
||||
if s:
|
||||
s = s + "\n "
|
||||
s = "%s<!ENTITY %s" % (s, entity.nodeName)
|
||||
if entity.publicId:
|
||||
s = '%s PUBLIC "%s"\n "%s"' \
|
||||
% (s, entity.publicId, entity.systemId)
|
||||
elif entity.systemId:
|
||||
s = '%s SYSTEM "%s"' % (s, entity.systemId)
|
||||
else:
|
||||
s = '%s "%s"' % (s, entity.firstChild.data)
|
||||
if entity.notationName:
|
||||
s = "%s NOTATION %s" % (s, entity.notationName)
|
||||
s = s + ">"
|
||||
return s
|
||||
|
||||
def _getNSattrs(self):
|
||||
return ""
|
||||
|
||||
def external_entity_ref_handler(self, context, base, systemId, publicId):
|
||||
if systemId == _FRAGMENT_BUILDER_INTERNAL_SYSTEM_ID:
|
||||
# this entref is the one that we made to put the subtree
|
||||
# in; all of our given input is parsed in here.
|
||||
old_document = self.document
|
||||
old_cur_node = self.curNode
|
||||
parser = self._parser.ExternalEntityParserCreate(context)
|
||||
# put the real document back, parse into the fragment to return
|
||||
self.document = self.originalDocument
|
||||
self.fragment = self.document.createDocumentFragment()
|
||||
self.curNode = self.fragment
|
||||
try:
|
||||
parser.Parse(self._source, True)
|
||||
finally:
|
||||
self.curNode = old_cur_node
|
||||
self.document = old_document
|
||||
self._source = None
|
||||
return -1
|
||||
else:
|
||||
return ExpatBuilder.external_entity_ref_handler(
|
||||
self, context, base, systemId, publicId)
|
||||
|
||||
|
||||
class Namespaces:
|
||||
"""Mix-in class for builders; adds support for namespaces."""
|
||||
|
||||
def _initNamespaces(self):
|
||||
# list of (prefix, uri) ns declarations. Namespace attrs are
|
||||
# constructed from this and added to the element's attrs.
|
||||
self._ns_ordered_prefixes = []
|
||||
|
||||
def createParser(self):
|
||||
"""Create a new namespace-handling parser."""
|
||||
parser = expat.ParserCreate(namespace_separator=" ")
|
||||
parser.namespace_prefixes = True
|
||||
return parser
|
||||
|
||||
def install(self, parser):
|
||||
"""Insert the namespace-handlers onto the parser."""
|
||||
ExpatBuilder.install(self, parser)
|
||||
if self._options.namespace_declarations:
|
||||
parser.StartNamespaceDeclHandler = (
|
||||
self.start_namespace_decl_handler)
|
||||
|
||||
def start_namespace_decl_handler(self, prefix, uri):
|
||||
"""Push this namespace declaration on our storage."""
|
||||
self._ns_ordered_prefixes.append((prefix, uri))
|
||||
|
||||
def start_element_handler(self, name, attributes):
|
||||
if ' ' in name:
|
||||
uri, localname, prefix, qname = _parse_ns_name(self, name)
|
||||
else:
|
||||
uri = EMPTY_NAMESPACE
|
||||
qname = name
|
||||
localname = None
|
||||
prefix = EMPTY_PREFIX
|
||||
node = minidom.Element(qname, uri, prefix, localname)
|
||||
node.ownerDocument = self.document
|
||||
_append_child(self.curNode, node)
|
||||
self.curNode = node
|
||||
|
||||
if self._ns_ordered_prefixes:
|
||||
for prefix, uri in self._ns_ordered_prefixes:
|
||||
if prefix:
|
||||
a = minidom.Attr(_intern(self, 'xmlns:' + prefix),
|
||||
XMLNS_NAMESPACE, prefix, "xmlns")
|
||||
else:
|
||||
a = minidom.Attr("xmlns", XMLNS_NAMESPACE,
|
||||
"xmlns", EMPTY_PREFIX)
|
||||
a.value = uri
|
||||
a.ownerDocument = self.document
|
||||
_set_attribute_node(node, a)
|
||||
del self._ns_ordered_prefixes[:]
|
||||
|
||||
if attributes:
|
||||
node._ensure_attributes()
|
||||
_attrs = node._attrs
|
||||
_attrsNS = node._attrsNS
|
||||
for i in range(0, len(attributes), 2):
|
||||
aname = attributes[i]
|
||||
value = attributes[i+1]
|
||||
if ' ' in aname:
|
||||
uri, localname, prefix, qname = _parse_ns_name(self, aname)
|
||||
a = minidom.Attr(qname, uri, localname, prefix)
|
||||
_attrs[qname] = a
|
||||
_attrsNS[(uri, localname)] = a
|
||||
else:
|
||||
a = minidom.Attr(aname, EMPTY_NAMESPACE,
|
||||
aname, EMPTY_PREFIX)
|
||||
_attrs[aname] = a
|
||||
_attrsNS[(EMPTY_NAMESPACE, aname)] = a
|
||||
a.ownerDocument = self.document
|
||||
a.value = value
|
||||
a.ownerElement = node
|
||||
|
||||
if __debug__:
|
||||
# This only adds some asserts to the original
|
||||
# end_element_handler(), so we only define this when -O is not
|
||||
# used. If changing one, be sure to check the other to see if
|
||||
# it needs to be changed as well.
|
||||
#
|
||||
def end_element_handler(self, name):
|
||||
curNode = self.curNode
|
||||
if ' ' in name:
|
||||
uri, localname, prefix, qname = _parse_ns_name(self, name)
|
||||
assert (curNode.namespaceURI == uri
|
||||
and curNode.localName == localname
|
||||
and curNode.prefix == prefix), \
|
||||
"element stack messed up! (namespace)"
|
||||
else:
|
||||
assert curNode.nodeName == name, \
|
||||
"element stack messed up - bad nodeName"
|
||||
assert curNode.namespaceURI == EMPTY_NAMESPACE, \
|
||||
"element stack messed up - bad namespaceURI"
|
||||
self.curNode = curNode.parentNode
|
||||
self._finish_end_element(curNode)
|
||||
|
||||
|
||||
class ExpatBuilderNS(Namespaces, ExpatBuilder):
|
||||
"""Document builder that supports namespaces."""
|
||||
|
||||
def reset(self):
|
||||
ExpatBuilder.reset(self)
|
||||
self._initNamespaces()
|
||||
|
||||
|
||||
class FragmentBuilderNS(Namespaces, FragmentBuilder):
|
||||
"""Fragment builder that supports namespaces."""
|
||||
|
||||
def reset(self):
|
||||
FragmentBuilder.reset(self)
|
||||
self._initNamespaces()
|
||||
|
||||
def _getNSattrs(self):
|
||||
"""Return string of namespace attributes from this element and
|
||||
ancestors."""
|
||||
# XXX This needs to be re-written to walk the ancestors of the
|
||||
# context to build up the namespace information from
|
||||
# declarations, elements, and attributes found in context.
|
||||
# Otherwise we have to store a bunch more data on the DOM
|
||||
# (though that *might* be more reliable -- not clear).
|
||||
attrs = ""
|
||||
context = self.context
|
||||
L = []
|
||||
while context:
|
||||
if hasattr(context, '_ns_prefix_uri'):
|
||||
for prefix, uri in context._ns_prefix_uri.items():
|
||||
# add every new NS decl from context to L and attrs string
|
||||
if prefix in L:
|
||||
continue
|
||||
L.append(prefix)
|
||||
if prefix:
|
||||
declname = "xmlns:" + prefix
|
||||
else:
|
||||
declname = "xmlns"
|
||||
if attrs:
|
||||
attrs = "%s\n %s='%s'" % (attrs, declname, uri)
|
||||
else:
|
||||
attrs = " %s='%s'" % (declname, uri)
|
||||
context = context.parentNode
|
||||
return attrs
|
||||
|
||||
|
||||
class ParseEscape(Exception):
|
||||
"""Exception raised to short-circuit parsing in InternalSubsetExtractor."""
|
||||
pass
|
||||
|
||||
class InternalSubsetExtractor(ExpatBuilder):
|
||||
"""XML processor which can rip out the internal document type subset."""
|
||||
|
||||
subset = None
|
||||
|
||||
def getSubset(self):
|
||||
"""Return the internal subset as a string."""
|
||||
return self.subset
|
||||
|
||||
def parseFile(self, file):
|
||||
try:
|
||||
ExpatBuilder.parseFile(self, file)
|
||||
except ParseEscape:
|
||||
pass
|
||||
|
||||
def parseString(self, string):
|
||||
try:
|
||||
ExpatBuilder.parseString(self, string)
|
||||
except ParseEscape:
|
||||
pass
|
||||
|
||||
def install(self, parser):
|
||||
parser.StartDoctypeDeclHandler = self.start_doctype_decl_handler
|
||||
parser.StartElementHandler = self.start_element_handler
|
||||
|
||||
def start_doctype_decl_handler(self, name, publicId, systemId,
|
||||
has_internal_subset):
|
||||
if has_internal_subset:
|
||||
parser = self.getParser()
|
||||
self.subset = []
|
||||
parser.DefaultHandler = self.subset.append
|
||||
parser.EndDoctypeDeclHandler = self.end_doctype_decl_handler
|
||||
else:
|
||||
raise ParseEscape()
|
||||
|
||||
def end_doctype_decl_handler(self):
|
||||
s = ''.join(self.subset).replace('\r\n', '\n').replace('\r', '\n')
|
||||
self.subset = s
|
||||
raise ParseEscape()
|
||||
|
||||
def start_element_handler(self, name, attrs):
|
||||
raise ParseEscape()
|
||||
|
||||
|
||||
def parse(file, namespaces=True):
|
||||
"""Parse a document, returning the resulting Document node.
|
||||
|
||||
'file' may be either a file name or an open file object.
|
||||
"""
|
||||
if namespaces:
|
||||
builder = ExpatBuilderNS()
|
||||
else:
|
||||
builder = ExpatBuilder()
|
||||
|
||||
if isinstance(file, str):
|
||||
with open(file, 'rb') as fp:
|
||||
result = builder.parseFile(fp)
|
||||
else:
|
||||
result = builder.parseFile(file)
|
||||
return result
|
||||
|
||||
|
||||
def parseString(string, namespaces=True):
|
||||
"""Parse a document from a string, returning the resulting
|
||||
Document node.
|
||||
"""
|
||||
if namespaces:
|
||||
builder = ExpatBuilderNS()
|
||||
else:
|
||||
builder = ExpatBuilder()
|
||||
return builder.parseString(string)
|
||||
|
||||
|
||||
def parseFragment(file, context, namespaces=True):
|
||||
"""Parse a fragment of a document, given the context from which it
|
||||
was originally extracted. context should be the parent of the
|
||||
node(s) which are in the fragment.
|
||||
|
||||
'file' may be either a file name or an open file object.
|
||||
"""
|
||||
if namespaces:
|
||||
builder = FragmentBuilderNS(context)
|
||||
else:
|
||||
builder = FragmentBuilder(context)
|
||||
|
||||
if isinstance(file, str):
|
||||
with open(file, 'rb') as fp:
|
||||
result = builder.parseFile(fp)
|
||||
else:
|
||||
result = builder.parseFile(file)
|
||||
return result
|
||||
|
||||
|
||||
def parseFragmentString(string, context, namespaces=True):
|
||||
"""Parse a fragment of a document from a string, given the context
|
||||
from which it was originally extracted. context should be the
|
||||
parent of the node(s) which are in the fragment.
|
||||
"""
|
||||
if namespaces:
|
||||
builder = FragmentBuilderNS(context)
|
||||
else:
|
||||
builder = FragmentBuilder(context)
|
||||
return builder.parseString(string)
|
||||
|
||||
|
||||
def makeBuilder(options):
|
||||
"""Create a builder based on an Options object."""
|
||||
if options.namespaces:
|
||||
return ExpatBuilderNS(options)
|
||||
else:
|
||||
return ExpatBuilder(options)
|
||||
109
.CondaPkg/env/Lib/xml/dom/minicompat.py
vendored
109
.CondaPkg/env/Lib/xml/dom/minicompat.py
vendored
@@ -1,109 +0,0 @@
|
||||
"""Python version compatibility support for minidom.
|
||||
|
||||
This module contains internal implementation details and
|
||||
should not be imported; use xml.dom.minidom instead.
|
||||
"""
|
||||
|
||||
# This module should only be imported using "import *".
|
||||
#
|
||||
# The following names are defined:
|
||||
#
|
||||
# NodeList -- lightest possible NodeList implementation
|
||||
#
|
||||
# EmptyNodeList -- lightest possible NodeList that is guaranteed to
|
||||
# remain empty (immutable)
|
||||
#
|
||||
# StringTypes -- tuple of defined string types
|
||||
#
|
||||
# defproperty -- function used in conjunction with GetattrMagic;
|
||||
# using these together is needed to make them work
|
||||
# as efficiently as possible in both Python 2.2+
|
||||
# and older versions. For example:
|
||||
#
|
||||
# class MyClass(GetattrMagic):
|
||||
# def _get_myattr(self):
|
||||
# return something
|
||||
#
|
||||
# defproperty(MyClass, "myattr",
|
||||
# "return some value")
|
||||
#
|
||||
# For Python 2.2 and newer, this will construct a
|
||||
# property object on the class, which avoids
|
||||
# needing to override __getattr__(). It will only
|
||||
# work for read-only attributes.
|
||||
#
|
||||
# For older versions of Python, inheriting from
|
||||
# GetattrMagic will use the traditional
|
||||
# __getattr__() hackery to achieve the same effect,
|
||||
# but less efficiently.
|
||||
#
|
||||
# defproperty() should be used for each version of
|
||||
# the relevant _get_<property>() function.
|
||||
|
||||
__all__ = ["NodeList", "EmptyNodeList", "StringTypes", "defproperty"]
|
||||
|
||||
import xml.dom
|
||||
|
||||
StringTypes = (str,)
|
||||
|
||||
|
||||
class NodeList(list):
|
||||
__slots__ = ()
|
||||
|
||||
def item(self, index):
|
||||
if 0 <= index < len(self):
|
||||
return self[index]
|
||||
|
||||
def _get_length(self):
|
||||
return len(self)
|
||||
|
||||
def _set_length(self, value):
|
||||
raise xml.dom.NoModificationAllowedErr(
|
||||
"attempt to modify read-only attribute 'length'")
|
||||
|
||||
length = property(_get_length, _set_length,
|
||||
doc="The number of nodes in the NodeList.")
|
||||
|
||||
# For backward compatibility
|
||||
def __setstate__(self, state):
|
||||
if state is None:
|
||||
state = []
|
||||
self[:] = state
|
||||
|
||||
|
||||
class EmptyNodeList(tuple):
|
||||
__slots__ = ()
|
||||
|
||||
def __add__(self, other):
|
||||
NL = NodeList()
|
||||
NL.extend(other)
|
||||
return NL
|
||||
|
||||
def __radd__(self, other):
|
||||
NL = NodeList()
|
||||
NL.extend(other)
|
||||
return NL
|
||||
|
||||
def item(self, index):
|
||||
return None
|
||||
|
||||
def _get_length(self):
|
||||
return 0
|
||||
|
||||
def _set_length(self, value):
|
||||
raise xml.dom.NoModificationAllowedErr(
|
||||
"attempt to modify read-only attribute 'length'")
|
||||
|
||||
length = property(_get_length, _set_length,
|
||||
doc="The number of nodes in the NodeList.")
|
||||
|
||||
|
||||
def defproperty(klass, name, doc):
|
||||
get = getattr(klass, ("_get_" + name))
|
||||
def set(self, value, name=name):
|
||||
raise xml.dom.NoModificationAllowedErr(
|
||||
"attempt to modify read-only attribute " + repr(name))
|
||||
assert not hasattr(klass, "_set_" + name), \
|
||||
"expected not to find _set_" + name
|
||||
prop = property(get, set, doc=doc)
|
||||
setattr(klass, name, prop)
|
||||
2013
.CondaPkg/env/Lib/xml/dom/minidom.py
vendored
2013
.CondaPkg/env/Lib/xml/dom/minidom.py
vendored
File diff suppressed because it is too large
Load Diff
336
.CondaPkg/env/Lib/xml/dom/pulldom.py
vendored
336
.CondaPkg/env/Lib/xml/dom/pulldom.py
vendored
@@ -1,336 +0,0 @@
|
||||
import xml.sax
|
||||
import xml.sax.handler
|
||||
|
||||
START_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 = None
|
||||
document = None
|
||||
|
||||
def __init__(self, documentFactory=None):
|
||||
from xml.dom import XML_NAMESPACE
|
||||
self.documentFactory = documentFactory
|
||||
self.firstEvent = [None, None]
|
||||
self.lastEvent = self.firstEvent
|
||||
self.elementStack = []
|
||||
self.push = self.elementStack.append
|
||||
try:
|
||||
self.pop = self.elementStack.pop
|
||||
except AttributeError:
|
||||
# use class' pop instead
|
||||
pass
|
||||
self._ns_contexts = [{XML_NAMESPACE:'xml'}] # contains uri -> prefix dicts
|
||||
self._current_context = self._ns_contexts[-1]
|
||||
self.pending_events = []
|
||||
|
||||
def pop(self):
|
||||
result = self.elementStack[-1]
|
||||
del self.elementStack[-1]
|
||||
return result
|
||||
|
||||
def setDocumentLocator(self, locator):
|
||||
self._locator = locator
|
||||
|
||||
def 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 None
|
||||
|
||||
def 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)] = value
|
||||
self._xmlns_attrs = []
|
||||
uri, localname = name
|
||||
if 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 + ":" + localname
|
||||
else:
|
||||
tagName = localname
|
||||
if 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
|
||||
# localname
|
||||
if self.document:
|
||||
node = self.document.createElement(localname)
|
||||
else:
|
||||
node = self.buildDocument(None, localname)
|
||||
|
||||
for aname,value in attrs.items():
|
||||
a_uri, a_localname = aname
|
||||
if a_uri == xmlns_uri:
|
||||
if a_localname == 'xmlns':
|
||||
qname = a_localname
|
||||
else:
|
||||
qname = 'xmlns:' + a_localname
|
||||
attr = self.document.createAttributeNS(a_uri, qname)
|
||||
node.setAttributeNodeNS(attr)
|
||||
elif a_uri:
|
||||
prefix = self._current_context[a_uri]
|
||||
if prefix:
|
||||
qname = prefix + ":" + a_localname
|
||||
else:
|
||||
qname = a_localname
|
||||
attr = self.document.createAttributeNS(a_uri, qname)
|
||||
node.setAttributeNodeNS(attr)
|
||||
else:
|
||||
attr = self.document.createAttribute(a_localname)
|
||||
node.setAttributeNode(attr)
|
||||
attr.value = value
|
||||
|
||||
self.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 = value
|
||||
node.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.minidom
|
||||
self.documentFactory = xml.dom.minidom.Document.implementation
|
||||
|
||||
def buildDocument(self, uri, tagname):
|
||||
# Can't do that in startDocument, since we need the tagname
|
||||
# XXX: obtain DocumentType
|
||||
node = self.documentFactory.createDocument(uri, tagname, None)
|
||||
self.document = node
|
||||
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):
|
||||
self.lastEvent[1] = [(END_DOCUMENT, self.document), None]
|
||||
self.pop()
|
||||
|
||||
def clear(self):
|
||||
"clear(): Explicitly release parsing structures"
|
||||
self.document = None
|
||||
|
||||
class ErrorHandler:
|
||||
def warning(self, exception):
|
||||
print(exception)
|
||||
def error(self, exception):
|
||||
raise exception
|
||||
def fatalError(self, exception):
|
||||
raise exception
|
||||
|
||||
class DOMEventStream:
|
||||
def __init__(self, stream, parser, bufsize):
|
||||
self.stream = stream
|
||||
self.parser = parser
|
||||
self.bufsize = bufsize
|
||||
if not hasattr(self.parser, 'feed'):
|
||||
self.getEvent = self._slurp
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.pulldom = PullDOM()
|
||||
# This content handler relies on namespace support
|
||||
self.parser.setFeature(xml.sax.handler.feature_namespaces, 1)
|
||||
self.parser.setContentHandler(self.pulldom)
|
||||
|
||||
def __next__(self):
|
||||
rc = self.getEvent()
|
||||
if rc:
|
||||
return rc
|
||||
raise StopIteration
|
||||
|
||||
def __iter__(self):
|
||||
return self
|
||||
|
||||
def expandNode(self, node):
|
||||
event = self.getEvent()
|
||||
parents = [node]
|
||||
while event:
|
||||
token, cur_node = event
|
||||
if cur_node is node:
|
||||
return
|
||||
if 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 effect
|
||||
if not self.pulldom.firstEvent[1]:
|
||||
self.pulldom.lastEvent = self.pulldom.firstEvent
|
||||
while not self.pulldom.firstEvent[1]:
|
||||
buf = self.stream.read(self.bufsize)
|
||||
if not buf:
|
||||
self.parser.close()
|
||||
return None
|
||||
self.parser.feed(buf)
|
||||
rc = self.pulldom.firstEvent[1][0]
|
||||
self.pulldom.firstEvent[1] = self.pulldom.firstEvent[1][1]
|
||||
return rc
|
||||
|
||||
def _slurp(self):
|
||||
""" Fallback replacement for getEvent() using the
|
||||
standard SAX2 interface, which means we slurp the
|
||||
SAX events into memory (no performance gain, but
|
||||
we are compatible to all SAX parsers).
|
||||
"""
|
||||
self.parser.parse(self.stream)
|
||||
self.getEvent = self._emit
|
||||
return self._emit()
|
||||
|
||||
def _emit(self):
|
||||
""" Fallback replacement for getEvent() that emits
|
||||
the events that _slurp() read previously.
|
||||
"""
|
||||
rc = self.pulldom.firstEvent[1][0]
|
||||
self.pulldom.firstEvent[1] = self.pulldom.firstEvent[1][1]
|
||||
return rc
|
||||
|
||||
def clear(self):
|
||||
"""clear(): Explicitly release parsing objects"""
|
||||
self.pulldom.clear()
|
||||
del self.pulldom
|
||||
self.parser = None
|
||||
self.stream = None
|
||||
|
||||
class 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) - 20
|
||||
|
||||
def parse(stream_or_string, parser=None, bufsize=None):
|
||||
if bufsize is None:
|
||||
bufsize = default_bufsize
|
||||
if isinstance(stream_or_string, str):
|
||||
stream = open(stream_or_string, 'rb')
|
||||
else:
|
||||
stream = stream_or_string
|
||||
if not parser:
|
||||
parser = xml.sax.make_parser()
|
||||
return DOMEventStream(stream, parser, bufsize)
|
||||
|
||||
def parseString(string, parser=None):
|
||||
from io import StringIO
|
||||
|
||||
bufsize = len(string)
|
||||
buf = StringIO(string)
|
||||
if not parser:
|
||||
parser = xml.sax.make_parser()
|
||||
return DOMEventStream(buf, parser, bufsize)
|
||||
387
.CondaPkg/env/Lib/xml/dom/xmlbuilder.py
vendored
387
.CondaPkg/env/Lib/xml/dom/xmlbuilder.py
vendored
@@ -1,387 +0,0 @@
|
||||
"""Implementation of the DOM Level 3 'LS-Load' feature."""
|
||||
|
||||
import copy
|
||||
import xml.dom
|
||||
|
||||
from xml.dom.NodeFilter import NodeFilter
|
||||
|
||||
|
||||
__all__ = ["DOMBuilder", "DOMEntityResolver", "DOMInputSource"]
|
||||
|
||||
|
||||
class Options:
|
||||
"""Features object that has variables set for each DOMBuilder feature.
|
||||
|
||||
The DOMBuilder class uses an instance of this class to pass settings to
|
||||
the ExpatBuilder class.
|
||||
"""
|
||||
|
||||
# Note that the DOMBuilder class in LoadSave constrains which of these
|
||||
# values can be set using the DOM Level 3 LoadSave feature.
|
||||
|
||||
namespaces = 1
|
||||
namespace_declarations = True
|
||||
validation = False
|
||||
external_parameter_entities = True
|
||||
external_general_entities = True
|
||||
external_dtd_subset = True
|
||||
validate_if_schema = False
|
||||
validate = False
|
||||
datatype_normalization = False
|
||||
create_entity_ref_nodes = True
|
||||
entities = True
|
||||
whitespace_in_element_content = True
|
||||
cdata_sections = True
|
||||
comments = True
|
||||
charset_overrides_xml_encoding = True
|
||||
infoset = False
|
||||
supported_mediatypes_only = False
|
||||
|
||||
errorHandler = None
|
||||
filter = None
|
||||
|
||||
|
||||
class DOMBuilder:
|
||||
entityResolver = None
|
||||
errorHandler = None
|
||||
filter = None
|
||||
|
||||
ACTION_REPLACE = 1
|
||||
ACTION_APPEND_AS_CHILDREN = 2
|
||||
ACTION_INSERT_AFTER = 3
|
||||
ACTION_INSERT_BEFORE = 4
|
||||
|
||||
_legal_actions = (ACTION_REPLACE, ACTION_APPEND_AS_CHILDREN,
|
||||
ACTION_INSERT_AFTER, ACTION_INSERT_BEFORE)
|
||||
|
||||
def __init__(self):
|
||||
self._options = Options()
|
||||
|
||||
def _get_entityResolver(self):
|
||||
return self.entityResolver
|
||||
def _set_entityResolver(self, entityResolver):
|
||||
self.entityResolver = entityResolver
|
||||
|
||||
def _get_errorHandler(self):
|
||||
return self.errorHandler
|
||||
def _set_errorHandler(self, errorHandler):
|
||||
self.errorHandler = errorHandler
|
||||
|
||||
def _get_filter(self):
|
||||
return self.filter
|
||||
def _set_filter(self, filter):
|
||||
self.filter = filter
|
||||
|
||||
def setFeature(self, name, state):
|
||||
if self.supportsFeature(name):
|
||||
state = state and 1 or 0
|
||||
try:
|
||||
settings = self._settings[(_name_xform(name), state)]
|
||||
except KeyError:
|
||||
raise xml.dom.NotSupportedErr(
|
||||
"unsupported feature: %r" % (name,)) from None
|
||||
else:
|
||||
for name, value in settings:
|
||||
setattr(self._options, name, value)
|
||||
else:
|
||||
raise xml.dom.NotFoundErr("unknown feature: " + repr(name))
|
||||
|
||||
def supportsFeature(self, name):
|
||||
return hasattr(self._options, _name_xform(name))
|
||||
|
||||
def canSetFeature(self, name, state):
|
||||
key = (_name_xform(name), state and 1 or 0)
|
||||
return key in self._settings
|
||||
|
||||
# This dictionary maps from (feature,value) to a list of
|
||||
# (option,value) pairs that should be set on the Options object.
|
||||
# If a (feature,value) setting is not in this dictionary, it is
|
||||
# not supported by the DOMBuilder.
|
||||
#
|
||||
_settings = {
|
||||
("namespace_declarations", 0): [
|
||||
("namespace_declarations", 0)],
|
||||
("namespace_declarations", 1): [
|
||||
("namespace_declarations", 1)],
|
||||
("validation", 0): [
|
||||
("validation", 0)],
|
||||
("external_general_entities", 0): [
|
||||
("external_general_entities", 0)],
|
||||
("external_general_entities", 1): [
|
||||
("external_general_entities", 1)],
|
||||
("external_parameter_entities", 0): [
|
||||
("external_parameter_entities", 0)],
|
||||
("external_parameter_entities", 1): [
|
||||
("external_parameter_entities", 1)],
|
||||
("validate_if_schema", 0): [
|
||||
("validate_if_schema", 0)],
|
||||
("create_entity_ref_nodes", 0): [
|
||||
("create_entity_ref_nodes", 0)],
|
||||
("create_entity_ref_nodes", 1): [
|
||||
("create_entity_ref_nodes", 1)],
|
||||
("entities", 0): [
|
||||
("create_entity_ref_nodes", 0),
|
||||
("entities", 0)],
|
||||
("entities", 1): [
|
||||
("entities", 1)],
|
||||
("whitespace_in_element_content", 0): [
|
||||
("whitespace_in_element_content", 0)],
|
||||
("whitespace_in_element_content", 1): [
|
||||
("whitespace_in_element_content", 1)],
|
||||
("cdata_sections", 0): [
|
||||
("cdata_sections", 0)],
|
||||
("cdata_sections", 1): [
|
||||
("cdata_sections", 1)],
|
||||
("comments", 0): [
|
||||
("comments", 0)],
|
||||
("comments", 1): [
|
||||
("comments", 1)],
|
||||
("charset_overrides_xml_encoding", 0): [
|
||||
("charset_overrides_xml_encoding", 0)],
|
||||
("charset_overrides_xml_encoding", 1): [
|
||||
("charset_overrides_xml_encoding", 1)],
|
||||
("infoset", 0): [],
|
||||
("infoset", 1): [
|
||||
("namespace_declarations", 0),
|
||||
("validate_if_schema", 0),
|
||||
("create_entity_ref_nodes", 0),
|
||||
("entities", 0),
|
||||
("cdata_sections", 0),
|
||||
("datatype_normalization", 1),
|
||||
("whitespace_in_element_content", 1),
|
||||
("comments", 1),
|
||||
("charset_overrides_xml_encoding", 1)],
|
||||
("supported_mediatypes_only", 0): [
|
||||
("supported_mediatypes_only", 0)],
|
||||
("namespaces", 0): [
|
||||
("namespaces", 0)],
|
||||
("namespaces", 1): [
|
||||
("namespaces", 1)],
|
||||
}
|
||||
|
||||
def getFeature(self, name):
|
||||
xname = _name_xform(name)
|
||||
try:
|
||||
return getattr(self._options, xname)
|
||||
except AttributeError:
|
||||
if name == "infoset":
|
||||
options = self._options
|
||||
return (options.datatype_normalization
|
||||
and options.whitespace_in_element_content
|
||||
and options.comments
|
||||
and options.charset_overrides_xml_encoding
|
||||
and not (options.namespace_declarations
|
||||
or options.validate_if_schema
|
||||
or options.create_entity_ref_nodes
|
||||
or options.entities
|
||||
or options.cdata_sections))
|
||||
raise xml.dom.NotFoundErr("feature %s not known" % repr(name))
|
||||
|
||||
def parseURI(self, uri):
|
||||
if self.entityResolver:
|
||||
input = self.entityResolver.resolveEntity(None, uri)
|
||||
else:
|
||||
input = DOMEntityResolver().resolveEntity(None, uri)
|
||||
return self.parse(input)
|
||||
|
||||
def parse(self, input):
|
||||
options = copy.copy(self._options)
|
||||
options.filter = self.filter
|
||||
options.errorHandler = self.errorHandler
|
||||
fp = input.byteStream
|
||||
if fp is None and options.systemId:
|
||||
import urllib.request
|
||||
fp = urllib.request.urlopen(input.systemId)
|
||||
return self._parse_bytestream(fp, options)
|
||||
|
||||
def parseWithContext(self, input, cnode, action):
|
||||
if action not in self._legal_actions:
|
||||
raise ValueError("not a legal action")
|
||||
raise NotImplementedError("Haven't written this yet...")
|
||||
|
||||
def _parse_bytestream(self, stream, options):
|
||||
import xml.dom.expatbuilder
|
||||
builder = xml.dom.expatbuilder.makeBuilder(options)
|
||||
return builder.parseFile(stream)
|
||||
|
||||
|
||||
def _name_xform(name):
|
||||
return name.lower().replace('-', '_')
|
||||
|
||||
|
||||
class DOMEntityResolver(object):
|
||||
__slots__ = '_opener',
|
||||
|
||||
def resolveEntity(self, publicId, systemId):
|
||||
assert systemId is not None
|
||||
source = DOMInputSource()
|
||||
source.publicId = publicId
|
||||
source.systemId = systemId
|
||||
source.byteStream = self._get_opener().open(systemId)
|
||||
|
||||
# determine the encoding if the transport provided it
|
||||
source.encoding = self._guess_media_encoding(source)
|
||||
|
||||
# determine the base URI is we can
|
||||
import posixpath, urllib.parse
|
||||
parts = urllib.parse.urlparse(systemId)
|
||||
scheme, netloc, path, params, query, fragment = parts
|
||||
# XXX should we check the scheme here as well?
|
||||
if path and not path.endswith("/"):
|
||||
path = posixpath.dirname(path) + "/"
|
||||
parts = scheme, netloc, path, params, query, fragment
|
||||
source.baseURI = urllib.parse.urlunparse(parts)
|
||||
|
||||
return source
|
||||
|
||||
def _get_opener(self):
|
||||
try:
|
||||
return self._opener
|
||||
except AttributeError:
|
||||
self._opener = self._create_opener()
|
||||
return self._opener
|
||||
|
||||
def _create_opener(self):
|
||||
import urllib.request
|
||||
return urllib.request.build_opener()
|
||||
|
||||
def _guess_media_encoding(self, source):
|
||||
info = source.byteStream.info()
|
||||
if "Content-Type" in info:
|
||||
for param in info.getplist():
|
||||
if param.startswith("charset="):
|
||||
return param.split("=", 1)[1].lower()
|
||||
|
||||
|
||||
class DOMInputSource(object):
|
||||
__slots__ = ('byteStream', 'characterStream', 'stringData',
|
||||
'encoding', 'publicId', 'systemId', 'baseURI')
|
||||
|
||||
def __init__(self):
|
||||
self.byteStream = None
|
||||
self.characterStream = None
|
||||
self.stringData = None
|
||||
self.encoding = None
|
||||
self.publicId = None
|
||||
self.systemId = None
|
||||
self.baseURI = None
|
||||
|
||||
def _get_byteStream(self):
|
||||
return self.byteStream
|
||||
def _set_byteStream(self, byteStream):
|
||||
self.byteStream = byteStream
|
||||
|
||||
def _get_characterStream(self):
|
||||
return self.characterStream
|
||||
def _set_characterStream(self, characterStream):
|
||||
self.characterStream = characterStream
|
||||
|
||||
def _get_stringData(self):
|
||||
return self.stringData
|
||||
def _set_stringData(self, data):
|
||||
self.stringData = data
|
||||
|
||||
def _get_encoding(self):
|
||||
return self.encoding
|
||||
def _set_encoding(self, encoding):
|
||||
self.encoding = encoding
|
||||
|
||||
def _get_publicId(self):
|
||||
return self.publicId
|
||||
def _set_publicId(self, publicId):
|
||||
self.publicId = publicId
|
||||
|
||||
def _get_systemId(self):
|
||||
return self.systemId
|
||||
def _set_systemId(self, systemId):
|
||||
self.systemId = systemId
|
||||
|
||||
def _get_baseURI(self):
|
||||
return self.baseURI
|
||||
def _set_baseURI(self, uri):
|
||||
self.baseURI = uri
|
||||
|
||||
|
||||
class DOMBuilderFilter:
|
||||
"""Element filter which can be used to tailor construction of
|
||||
a DOM instance.
|
||||
"""
|
||||
|
||||
# There's really no need for this class; concrete implementations
|
||||
# should just implement the endElement() and startElement()
|
||||
# methods as appropriate. Using this makes it easy to only
|
||||
# implement one of them.
|
||||
|
||||
FILTER_ACCEPT = 1
|
||||
FILTER_REJECT = 2
|
||||
FILTER_SKIP = 3
|
||||
FILTER_INTERRUPT = 4
|
||||
|
||||
whatToShow = NodeFilter.SHOW_ALL
|
||||
|
||||
def _get_whatToShow(self):
|
||||
return self.whatToShow
|
||||
|
||||
def acceptNode(self, element):
|
||||
return self.FILTER_ACCEPT
|
||||
|
||||
def startContainer(self, element):
|
||||
return self.FILTER_ACCEPT
|
||||
|
||||
del NodeFilter
|
||||
|
||||
|
||||
class DocumentLS:
|
||||
"""Mixin to create documents that conform to the load/save spec."""
|
||||
|
||||
async_ = False
|
||||
|
||||
def _get_async(self):
|
||||
return False
|
||||
|
||||
def _set_async(self, flag):
|
||||
if flag:
|
||||
raise xml.dom.NotSupportedErr(
|
||||
"asynchronous document loading is not supported")
|
||||
|
||||
def abort(self):
|
||||
# What does it mean to "clear" a document? Does the
|
||||
# documentElement disappear?
|
||||
raise NotImplementedError(
|
||||
"haven't figured out what this means yet")
|
||||
|
||||
def load(self, uri):
|
||||
raise NotImplementedError("haven't written this yet")
|
||||
|
||||
def loadXML(self, source):
|
||||
raise NotImplementedError("haven't written this yet")
|
||||
|
||||
def saveXML(self, snode):
|
||||
if snode is None:
|
||||
snode = self
|
||||
elif snode.ownerDocument is not self:
|
||||
raise xml.dom.WrongDocumentErr()
|
||||
return snode.toxml()
|
||||
|
||||
|
||||
class DOMImplementationLS:
|
||||
MODE_SYNCHRONOUS = 1
|
||||
MODE_ASYNCHRONOUS = 2
|
||||
|
||||
def createDOMBuilder(self, mode, schemaType):
|
||||
if schemaType is not None:
|
||||
raise xml.dom.NotSupportedErr(
|
||||
"schemaType not yet supported")
|
||||
if mode == self.MODE_SYNCHRONOUS:
|
||||
return DOMBuilder()
|
||||
if mode == self.MODE_ASYNCHRONOUS:
|
||||
raise xml.dom.NotSupportedErr(
|
||||
"asynchronous builders are not supported")
|
||||
raise ValueError("unknown value for mode")
|
||||
|
||||
def createDOMWriter(self):
|
||||
raise NotImplementedError(
|
||||
"the writer interface hasn't been written yet!")
|
||||
|
||||
def createDOMInputSource(self):
|
||||
return DOMInputSource()
|
||||
Reference in New Issue
Block a user