Source code for xml4h.impls.interface

from xml4h import nodes, exceptions


[docs]class XmlImplAdapter(object): """ Base class that defines how *xml4h* interacts with an underlying XML library that the adaptor "wraps" to provide additional (or at least different) functionality. This class should be treated as an abstract class. It provides some common implementation code used by all *xml4h* adapter implementations, but mostly it sketches out the methods the real implementaiton subclasses must provide. """ # List of extra features supported (or not) by an adapter implementation SUPPORTED_FEATURES = { 'xpath': False, } @classmethod
[docs] def has_feature(cls, feature_name): """ :return: *True* if a named feature is supported by this adapter. """ return cls.SUPPORTED_FEATURES.get(feature_name.lower(), False)
@classmethod
[docs] def ignore_whitespace_text_nodes(cls, wrapped_node): """ Find and delete any text nodes containing nothing but whitespace in in the given node and its descendents. This is useful for cleaning up excess low-value text nodes in a document DOM after parsing a pretty-printed XML document. """ for child in wrapped_node.children: if child.is_text and child.value.strip() == '': child.delete() else: cls.ignore_whitespace_text_nodes(child)
@classmethod def create_document(cls, root_tagname, ns_uri=None, **kwargs): # Use implementation's method to create base document and root element impl_doc = cls.new_impl_document(root_tagname, ns_uri, **kwargs) adapter = cls(impl_doc) wrapped_doc = nodes.Document(impl_doc, adapter) # Automatically add namespace URI to root Element as attribute if ns_uri is not None: adapter.set_node_attribute_value(wrapped_doc.root.impl_node, 'xmlns', ns_uri, ns_uri=nodes.Node.XMLNS_URI) return wrapped_doc @classmethod def wrap_document(cls, document_node): adapter = cls(document_node) return nodes.Document(document_node, adapter) @classmethod def wrap_node(cls, node, document): if node is None: return None adapter = cls(document) impl_class = adapter.map_node_to_class(node) return impl_class(node, adapter) @classmethod
[docs] def is_available(cls): """ :return: *True* if this adapter's underlying XML library is available \ in the Python environment. """ raise NotImplementedError("Implementation missing for %s" % cls)
@classmethod def parse_string(cls, xml_str, ignore_whitespace_text_nodes=True): raise NotImplementedError("Implementation missing for %s" % cls) @classmethod def parse_file(cls, xml_file, ignore_whitespace_text_nodes=True): raise NotImplementedError("Implementation missing for %s" % cls) def __init__(self, document): if not isinstance(document, object): raise Exception( 'Cannot instantiate adapter with invalid document: %s' % document) self._impl_document = document self._auto_ns_prefix_count = 0 @property def impl_document(self): return self._impl_document @property def impl_root_element(self): return self.get_impl_root(self.impl_document) def get_ns_uri_for_prefix(self, node, prefix): if prefix == 'xmlns': return nodes.Node.XMLNS_URI elif prefix is None: attr_name = 'xmlns' else: attr_name = 'xmlns:%s' % prefix uri = self.lookup_ns_uri_by_attr_name(node, attr_name) if uri is None: if attr_name == 'xmlns': # Default namespace URI return nodes.Node.XMLNS_URI raise Exception( "Unknown namespace URI for attribute name '%s'" % attr_name) return uri def get_ns_prefix_for_uri(self, node, uri, auto_generate_prefix=False): if uri == nodes.Node.XMLNS_URI: return 'xmlns' prefix = self.lookup_ns_prefix_for_uri(node, uri) if not prefix and auto_generate_prefix: prefix = 'autoprefix%d' % self._auto_ns_prefix_count self._auto_ns_prefix_count += 1 return prefix
[docs] def get_ns_info_from_node_name(self, name, impl_node): """ Return a three-element tuple with the prefix, local name, and namespace URI for the given element/attribute name (in the context of the given node's hierarchy). If the name has no associated prefix or namespace information, None is return for those tuple members. """ if '}' in name: ns_uri, name = name.split('}') ns_uri = ns_uri[1:] prefix = self.get_ns_prefix_for_uri(impl_node, ns_uri) elif ':' in name: prefix, name = name.split(':') ns_uri = self.get_ns_uri_for_prefix(impl_node, prefix) if ns_uri is None: raise Exception( "Prefix '%s' does not have a defined namespace URI" % prefix) else: prefix, ns_uri = None, None return prefix, name, ns_uri # Utility implementation methods
@classmethod def new_impl_document(cls, root_tagname, ns_uri=None, **kwargs): raise NotImplementedError("Implementation missing for %s" % cls) def map_node_to_class(self, node): raise NotImplementedError("Implementation missing for %s" % self) def get_impl_root(self, node): raise NotImplementedError("Implementation missing for %s" % self) # Document implementation methods def new_impl_element(self, tagname, ns_uri=None, parent=None): raise NotImplementedError("Implementation missing for %s" % self) def new_impl_text(self, text): raise NotImplementedError("Implementation missing for %s" % self) def new_impl_comment(self, text): raise NotImplementedError("Implementation missing for %s" % self) def new_impl_instruction(self, target, data): raise NotImplementedError("Implementation missing for %s" % self) def new_impl_cdata(self, text): raise NotImplementedError("Implementation missing for %s" % self)
[docs] def find_node_elements(self, node, name='*', ns_uri='*'): """ :return: element node descendents of the given node that match the \ search constraints. :param node: a node object from the underlying XML library. :param string name: only elements with a matching name will be returned. If the value is ``*`` all names will match. :param string ns_uri: only elements with a matching namespace URI will be returned. If the value is ``*`` all namespaces will match. """ raise NotImplementedError("Implementation missing for %s" % self)
def xpath_on_node(self, node, xpath, **kwargs): if not self.has_feature('xpath'): raise exceptions.FeatureUnavailableException('xpath') raise NotImplementedError("Implementation missing for %s" % self) # Node implementation methods def get_node_namespace_uri(self, node): raise NotImplementedError("Implementation missing for %s" % self) def set_node_namespace_uri(self, node, ns_uri): raise NotImplementedError("Implementation missing for %s" % self) def get_node_parent(self, node): raise NotImplementedError("Implementation missing for %s" % self) def get_node_children(self, node): raise NotImplementedError("Implementation missing for %s" % self) def get_node_name(self, node): raise NotImplementedError("Implementation missing for %s" % self) def set_node_name(self, node, name): raise NotImplementedError("Implementation missing for %s" % self) def get_node_local_name(self, node): raise NotImplementedError("Implementation missing for %s" % self) def get_node_name_prefix(self, node): raise NotImplementedError("Implementation missing for %s" % self) def get_node_value(self, node): raise NotImplementedError("Implementation missing for %s" % self) def set_node_value(self, node, value): raise NotImplementedError("Implementation missing for %s" % self) def get_node_text(self, node): raise NotImplementedError("Implementation missing for %s" % self) def set_node_text(self, node, text): raise NotImplementedError("Implementation missing for %s" % self) def get_node_attributes(self, element, ns_uri=None): raise NotImplementedError("Implementation missing for %s" % self) def has_node_attribute(self, element, name, ns_uri=None): raise NotImplementedError("Implementation missing for %s" % self) def get_node_attribute_node(self, element, name, ns_uri=None): raise NotImplementedError("Implementation missing for %s" % self) def get_node_attribute_value(self, element, name, ns_uri=None): raise NotImplementedError("Implementation missing for %s" % self) def set_node_attribute_value(self, element, name, value, ns_uri=None): raise NotImplementedError("Implementation missing for %s" % self) def remove_node_attribute(self, element, name, ns_uri=None): raise NotImplementedError("Implementation missing for %s" % self) def add_node_child(self, parent, child, before_sibling=None): raise NotImplementedError("Implementation missing for %s" % self) def import_node(self, parent, node, clone=False): raise NotImplementedError("Implementation missing for %s" % self) def clone_node(self, node, deep=True): raise NotImplementedError("Implementation missing for %s" % self) def remove_node_child(self, parent, child, destroy_node=True): raise NotImplementedError("Implementation missing for %s" % self) def lookup_ns_uri_by_attr_name(self, node, name): raise NotImplementedError("Implementation missing for %s" % self) def lookup_ns_prefix_for_uri(self, node, uri): raise NotImplementedError("Implementation missing for %s" % self)

Project Versions