Source code for zope.structuredtext.stdom

##############################################################################
#
# Copyright (c) 2001 Zope Foundation and Contributors.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
"""DOM implementation in StructuredText: read-only methods
"""

# Node type codes
# ---------------

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

# Exception codes
# ---------------

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

# Exceptions
# ----------


[docs] class DOMException(Exception): pass
[docs] class IndexSizeException(DOMException): code = INDEX_SIZE_ERR
[docs] class DOMStringSizeException(DOMException): code = DOMSTRING_SIZE_ERR
[docs] class HierarchyRequestException(DOMException): code = HIERARCHY_REQUEST_ERR
[docs] class WrongDocumentException(DOMException): code = WRONG_DOCUMENT_ERR
[docs] class InvalidCharacterException(DOMException): code = INVALID_CHARACTER_ERR
[docs] class NoDataAllowedException(DOMException): code = NO_DATA_ALLOWED_ERR
[docs] class NoModificationAllowedException(DOMException): code = NO_MODIFICATION_ALLOWED_ERR
[docs] class NotFoundException(DOMException): code = NOT_FOUND_ERR
[docs] class NotSupportedException(DOMException): code = NOT_SUPPORTED_ERR
[docs] class InUseAttributeException(DOMException): code = INUSE_ATTRIBUTE_ERR
# Node classes # ------------
[docs] class ParentNode: """ A node that can have children, or, more precisely, that implements the child access methods of the DOM. """
[docs] def getChildNodes(self, type=type, sts=str): """ Returns a NodeList that contains all children of this node. If there are no children, this is a empty NodeList """ r = [] for n in self.getChildren(): if isinstance(n, sts): n = TextNode(n) r.append(n.__of__(self)) return NodeList(r)
[docs] def getFirstChild(self, type=type, sts=str): """ The first child of this node. If there is no such node this returns None """ raise NotImplementedError()
[docs] def getLastChild(self, type=type, sts=str): """ The last child of this node. If there is no such node this returns None. """ raise NotImplementedError()
[docs] class NodeWrapper(ParentNode): """ This is an acquisition-like wrapper that provides parent access for DOM sans circular references! """ def __init__(self, aq_self, aq_parent): self.aq_self = aq_self self.aq_parent = aq_parent def __getattr__(self, name): return getattr(self.aq_self, name)
[docs] def getParentNode(self): """ The parent of this node. All nodes except Document DocumentFragment and Attr may have a parent """ raise NotImplementedError()
def _getDOMIndex(self, children, getattr=getattr): i = 0 self = self.aq_self for child in children: if getattr(child, 'aq_self', child) is self: self._DOMIndex = i return i i = i + 1
[docs] def getPreviousSibling(self): """ The node immediately preceding this node. If there is no such node, this returns None. """ children = self.aq_parent.getChildren() if not children: # pragma: no cover return None index = getattr(self, '_DOMIndex', None) if index is None: index = self._getDOMIndex(children) if index is None: return None # pragma: no cover index = index - 1 if index < 0: return None try: n = children[index] except IndexError: # pragma: no cover return None else: if isinstance(n, str): n = TextNode(n) n._DOMIndex = index return n.__of__(self)
[docs] def getNextSibling(self): """ The node immediately preceding this node. If there is no such node, this returns None. """ children = self.aq_parent.getChildren() if not children: # pragma: no cover return None index = getattr(self, '_DOMIndex', None) if index is None: # pragma: no cover index = self._getDOMIndex(children) if index is None: return None index = index + 1 try: n = children[index] except IndexError: # pragma: no cover return None else: if isinstance(n, str): # pragma: no cover n = TextNode(n) n._DOMIndex = index return n.__of__(self)
[docs] def getOwnerDocument(self): """ The Document object associated with this node, if any. """ raise NotImplementedError()
[docs] class Node(ParentNode): """Node Interface """ # Get a DOM wrapper with a parent link def __of__(self, parent): return NodeWrapper(self, parent) # DOM attributes
[docs] def getNodeName(self): """The name of this node, depending on its type """
[docs] def getNodeValue(self): """The value of this node, depending on its type """
[docs] def getParentNode(self): """ The parent of this node. All nodes except Document DocumentFragment and Attr may have a parent """
[docs] def getChildren(self): """Get a Python sequence of children """ raise NotImplementedError()
[docs] def getPreviousSibling(self): """ The node immediately preceding this node. If there is no such node, this returns None. """
[docs] def getNextSibling(self): """ The node immediately preceding this node. If there is no such node, this returns None. """
[docs] def getAttributes(self): """ Returns a NamedNodeMap containing the attributes of this node (if it is an element) or None otherwise. """
[docs] def getOwnerDocument(self): """The Document object associated with this node, if any. """
# DOM Methods # -----------
[docs] def hasChildNodes(self): """ Returns true if the node has any children, false if it doesn't. """ raise NotImplementedError()
_NODE_TYPE = None
[docs] def getNodeType(self): """A code representing the type of the node.""" return self._NODE_TYPE
[docs] class TextNode(Node): def __init__(self, str): self._value = str _NODE_TYPE = TEXT_NODE
[docs] def getNodeName(self): return '#text'
[docs] def getNodeValue(self): return self._value
[docs] class Element(Node): """Element interface """ # Element Attributes # ------------------
[docs] def getTagName(self): """The name of the element""" return self.__class__.__name__
getNodeName = getTagName _NODE_TYPE = ELEMENT_NODE
[docs] def getNodeValue(self): r = [] for c in self.getChildren(): if not isinstance(c, str): c = c.getNodeValue() r.append(c) return ''.join(r)
[docs] def getParentNode(self): """ The parent of this node. All nodes except Document DocumentFragment and Attr may have a parent """
# Element Methods # --------------- _attributes = ()
[docs] def getAttribute(self, name): """Retrieves an attribute value by name.""" return getattr(self, name, None)
[docs] def getAttributeNode(self, name): """ Retrieves an Attr node by name or None if there is no such attribute. """ if hasattr(self, name): return Attr(name, getattr(self, name))
[docs] def getAttributes(self): d = {} for a in self._attributes: d[a] = getattr(self, a, '') return NamedNodeMap(d)
[docs] def getElementsByTagName(self, tagname): """ Returns a NodeList of all the Elements with a given tag name in the order in which they would be encountered in a preorder traversal of the Document tree. Parameter: tagname The name of the tag to match (* = all tags). Return Value: A new NodeList object containing all the matched Elements. """ raise NotImplementedError()
[docs] class NodeList: """NodeList interface - Provides the abstraction of an ordered collection of nodes. Python extensions: can use sequence-style 'len', 'getitem', and 'for..in' constructs. """ def __init__(self, list=None): self._data = list or [] def __getitem__(self, index, type=type, sts=str): return self._data[index]
[docs] def item(self, index): """Returns the index-th item in the collection """ raise NotImplementedError()
[docs] def getLength(self): """The length of the NodeList """ return len(self._data)
__len__ = getLength
[docs] class NamedNodeMap: """ NamedNodeMap interface - Is used to represent collections of nodes that can be accessed by name. NamedNodeMaps are not maintained in any particular order. Python extensions: can use sequence-style 'len', 'getitem', and 'for..in' constructs, and mapping-style 'getitem'. """ def __init__(self, data=None): self._data = data if data is not None else {}
[docs] def item(self, index): """Returns the index-th item in the map. This is arbitrary because maps have no order. """ raise NotImplementedError()
def __getitem__(self, key): raise NotImplementedError()
[docs] def getLength(self): """ The length of the NodeList """ raise NotImplementedError()
__len__ = getLength
[docs] def getNamedItem(self, name): """ Retrieves a node specified by name. Parameters: name Name of a node to retrieve. Return Value A Node (of any type) with the specified name, or None if the specified name did not identify any node in the map. """ raise NotImplementedError()
[docs] class Attr(Node): """ Attr interface - The Attr interface represents an attriubte in an Element object. Attr objects inherit the Node Interface """ def __init__(self, name, value, specified=1): self.name = name self.value = value self.specified = specified
[docs] def getNodeName(self): """ The name of this node, depending on its type """ raise NotImplementedError()
getName = getNodeName
[docs] def getNodeValue(self): """ The value of this node, depending on its type """ raise NotImplementedError()
_NODE_TYPE = ATTRIBUTE_NODE
[docs] def getSpecified(self): """ If this attribute was explicitly given a value in the original document, this is true; otherwise, it is false. """ raise NotImplementedError()