"""Implementation of the DOM Level 3 'LS-Load' feature."""
from xml
.dom
.minicompat
import *
from xml
.dom
.NodeFilter
import NodeFilter
__all__
= ["DOMBuilder", "DOMEntityResolver", "DOMInputSource"]
"""Features object that has variables set for each DOMBuilder feature.
The DOMBuilder class uses an instance of this class to pass settings to
# Note that the DOMBuilder class in LoadSave constrains which of these
# values can be set using the DOM Level 3 LoadSave feature.
namespace_declarations
= True
external_parameter_entities
= True
external_general_entities
= True
external_dtd_subset
= True
validate_if_schema
= False
datatype_normalization
= False
create_entity_ref_nodes
= True
whitespace_in_element_content
= True
charset_overrides_xml_encoding
= True
supported_mediatypes_only
= False
ACTION_APPEND_AS_CHILDREN
= 2
_legal_actions
= (ACTION_REPLACE
, ACTION_APPEND_AS_CHILDREN
,
ACTION_INSERT_AFTER
, ACTION_INSERT_BEFORE
)
self
._options
= Options()
def _get_entityResolver(self
):
return self
.entityResolver
def _set_entityResolver(self
, entityResolver
):
self
.entityResolver
= entityResolver
def _get_errorHandler(self
):
def _set_errorHandler(self
, errorHandler
):
self
.errorHandler
= errorHandler
def _set_filter(self
, filter):
def setFeature(self
, name
, state
):
if self
.supportsFeature(name
):
settings
= self
._settings
[(_name_xform(name
), state
)]
raise xml
.dom
.NotSupportedErr(
"unsupported feature: %r" % (name
,))
for name
, value
in settings
:
setattr(self
._options
, name
, value
)
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 self
._settings
.has_key(key
)
# 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.
("namespace_declarations", 0): [
("namespace_declarations", 0)],
("namespace_declarations", 1): [
("namespace_declarations", 1)],
("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)],
("create_entity_ref_nodes", 0),
("whitespace_in_element_content", 0): [
("whitespace_in_element_content", 0)],
("whitespace_in_element_content", 1): [
("whitespace_in_element_content", 1)],
("charset_overrides_xml_encoding", 0): [
("charset_overrides_xml_encoding", 0)],
("charset_overrides_xml_encoding", 1): [
("charset_overrides_xml_encoding", 1)],
("namespace_declarations", 0),
("validate_if_schema", 0),
("create_entity_ref_nodes", 0),
("datatype_normalization", 1),
("whitespace_in_element_content", 1),
("charset_overrides_xml_encoding", 1)],
("supported_mediatypes_only", 0): [
("supported_mediatypes_only", 0)],
def getFeature(self
, name
):
xname
= _name_xform(name
)
return getattr(self
._options
, xname
)
return (options
.datatype_normalization
and options
.whitespace_in_element_content
and options
.charset_overrides_xml_encoding
and not (options
.namespace_declarations
or options
.validate_if_schema
or options
.create_entity_ref_nodes
or options
.cdata_sections
))
raise xml
.dom
.NotFoundErr("feature %s not known" % repr(name
))
input = self
.entityResolver
.resolveEntity(None, uri
)
input = DOMEntityResolver().resolveEntity(None, uri
)
options
= copy
.copy(self
._options
)
options
.filter = self
.filter
options
.errorHandler
= self
.errorHandler
if fp
is None and options
.systemId
:
fp
= urllib2
.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
)
return name
.lower().replace('-', '_')
class DOMEntityResolver(NewStyle
):
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
, urlparse
parts
= urlparse
.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
= urlparse
.urlunparse(parts
)
self
._opener
= self
._create
_opener
()
def _create_opener(self
):
return urllib2
.build_opener()
def _guess_media_encoding(self
, source
):
info
= source
.byteStream
.info()
if info
.has_key("Content-Type"):
for param
in info
.getplist():
if param
.startswith("charset="):
return param
.split("=", 1)[1].lower()
class DOMInputSource(NewStyle
):
__slots__
= ('byteStream', 'characterStream', 'stringData',
'encoding', 'publicId', 'systemId', 'baseURI')
self
.characterStream
= None
def _get_byteStream(self
):
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
):
def _set_stringData(self
, data
):
def _set_encoding(self
, encoding
):
def _set_publicId(self
, publicId
):
def _set_systemId(self
, systemId
):
def _set_baseURI(self
, uri
):
"""Element filter which can be used to tailor construction of
# 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
whatToShow
= NodeFilter
.SHOW_ALL
def _get_whatToShow(self
):
def acceptNode(self
, element
):
return self
.FILTER_ACCEPT
def startContainer(self
, element
):
return self
.FILTER_ACCEPT
"""Mixin to create documents that conform to the load/save spec."""
def _set_async(self
, async):
raise xml
.dom
.NotSupportedErr(
"asynchronous document loading is not supported")
# What does it mean to "clear" a document? Does the
# documentElement disappear?
raise NotImplementedError(
"haven't figured out what this means yet")
raise NotImplementedError("haven't written this yet")
def loadXML(self
, source
):
raise NotImplementedError("haven't written this yet")
def saveXML(self
, snode
):
elif snode
.ownerDocument
is not self
:
raise xml
.dom
.WrongDocumentErr()
class DOMImplementationLS
:
def createDOMBuilder(self
, mode
, schemaType
):
if schemaType
is not None:
raise xml
.dom
.NotSupportedErr(
"schemaType not yet supported")
if mode
== self
.MODE_SYNCHRONOUS
:
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
):