Viewing file: ParsedAxisSpecifier.py (8.32 KB) -rw-r--r-- Select action/file-type: (+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
######################################################################## # $Header: /var/local/cvsroot/4Suite/Ft/Xml/XPath/ParsedAxisSpecifier.py,v 1.15 2005/02/09 11:10:54 mbrown Exp $ """ A parsed token that represents an axis specifier.
Copyright 2004 Fourthought, Inc. (USA). Detailed license and copyright information: http://4suite.org/COPYRIGHT Project home, documentation, distributions: http://4suite.org/ """
from xml.dom import Node
from Ft.Xml.XPath import NAMESPACE_NODE
def ParsedAxisSpecifier(axis): try: return g_classMap[axis](axis) except KeyError: raise SyntaxError("Invalid axis: %s" % axis)
class AxisSpecifier:
principalType = Node.ELEMENT_NODE
def __init__(self, axis): self._axis = axis
def select(self, context, nodeTest): """ Always returns a node-set and 0 if forward, 1 if reverse. """ return ([], 0)
def descendants(self, context, nodeTest, node, nodeSet): """Select all of the descendants from the context node""" if context.node.nodeType != Node.ATTRIBUTE_NODE: for child in node.childNodes: if nodeTest(context, child, self.principalType): nodeSet.append(child) if child.childNodes: self.descendants(context, nodeTest, child, nodeSet) return (nodeSet, 0)
def pprint(self, indent=''): print indent + str(self)
def __str__(self): return '<AxisSpecifier at %x: %s>' % (id(self), repr(self))
def __repr__(self): """Always displays verbose expression""" return self._axis
class ParsedAncestorAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the ancestors including the root""" nodeSet = [] parent = ((context.node.nodeType == Node.ATTRIBUTE_NODE) and context.node.ownerElement or context.node.parentNode) while parent: if nodeTest(context, parent, self.principalType): nodeSet.append(parent) parent = parent.parentNode nodeSet.reverse() return (nodeSet, 1)
class ParsedAncestorOrSelfAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the ancestors including ourselves through the root""" node = context.node if nodeTest(context, node, self.principalType): nodeSet = [node] else: nodeSet = [] parent = ((node.nodeType == Node.ATTRIBUTE_NODE) and node.ownerElement or node.parentNode) while parent: if nodeTest(context, parent, self.principalType): nodeSet.append(parent) parent = parent.parentNode nodeSet.reverse() return (nodeSet, 1)
class ParsedAttributeAxisSpecifier(AxisSpecifier):
principalType = Node.ATTRIBUTE_NODE
def select(self, context, nodeTest): """Select all of the attributes from the context node""" result = [ attr for attr in context.node.xpathAttributes if nodeTest(context, attr, self.principalType) ] return (result, 0)
class ParsedChildAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the children of the context node""" result = [ node for node in context.node.childNodes if nodeTest(context, node, self.principalType) ] return (result, 0)
class ParsedDescendantOrSelfAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select the context node and all of its descendants""" if nodeTest(context, context.node, self.principalType): nodeSet = [context.node] else: nodeSet = [] self.descendants(context, nodeTest, context.node, nodeSet) return (nodeSet, 0)
class ParsedDescendantAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): nodeSet = [] self.descendants(context, nodeTest, context.node, nodeSet) return (nodeSet, 0)
class ParsedFollowingSiblingAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the siblings that follow the context node""" result = [] sibling = context.node.nextSibling while sibling: if nodeTest(context, sibling, self.principalType): result.append(sibling) sibling = sibling.nextSibling return (result, 0)
class ParsedFollowingAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """ Select all of the nodes the follow the context node, not including descendants. """ result = [] curr = context.node while curr != (context.node.rootNode): sibling = curr.nextSibling while sibling: if nodeTest(context, sibling, self.principalType): result.append(sibling) self.descendants(context, nodeTest, sibling, result) sibling = sibling.nextSibling curr = ((curr.nodeType == Node.ATTRIBUTE_NODE) and curr.ownerElement or curr.parentNode) return (result, 0)
class ParsedNamespaceAxisSpecifier(AxisSpecifier):
principalType = NAMESPACE_NODE
def select(self, context, nodeTest): """Select all of the namespaces from the context node.""" result = [ xns for xns in context.node.xpathNamespaces if nodeTest(context, xns, self.principalType) ] return (result, 0)
class ParsedParentAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select the parent of the context node""" parent = ((context.node.nodeType == Node.ATTRIBUTE_NODE) and context.node.ownerElement or context.node.parentNode) if parent and nodeTest(context, parent, self.principalType): result = [parent] else: result = [] return (result, 1)
class ParsedPrecedingSiblingAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the siblings that precede the context node""" result = [] sibling = context.node.previousSibling while sibling: if nodeTest(context, sibling, self.principalType): result.append(sibling) sibling = sibling.previousSibling # Put the list in document order result.reverse() return (result, 1)
class ParsedPrecedingAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select all of the nodes the precede the context node, not including ancestors""" # Create a list of lists of descendants of the nodes # that precede the context node. (reverse doc order) doc_list = [] curr = context.node while curr: sib = curr.previousSibling while sib: result = [] if nodeTest(context, sib, self.principalType): result = [sib] self.descendants(context, nodeTest, sib, result) doc_list.append(result) sib = sib.previousSibling curr = curr.nodeType == Node.ATTRIBUTE_NODE and curr.ownerElement or curr.parentNode
# Create a single list in document order result = [] for i in xrange(1, len(doc_list)+1): result.extend(doc_list[-i]) return (result, 1)
class ParsedSelfAxisSpecifier(AxisSpecifier): def select(self, context, nodeTest): """Select the context node""" if nodeTest(context, context.node, self.principalType): return ([context.node], 0) return ([], 0)
g_classMap = { 'ancestor' : ParsedAncestorAxisSpecifier, 'ancestor-or-self' : ParsedAncestorOrSelfAxisSpecifier, 'child' : ParsedChildAxisSpecifier, 'parent' : ParsedParentAxisSpecifier, 'descendant' : ParsedDescendantAxisSpecifier, 'descendant-or-self' : ParsedDescendantOrSelfAxisSpecifier, 'attribute' : ParsedAttributeAxisSpecifier, 'following' : ParsedFollowingAxisSpecifier, 'following-sibling' : ParsedFollowingSiblingAxisSpecifier, 'preceding' : ParsedPrecedingAxisSpecifier, 'preceding-sibling' : ParsedPrecedingSiblingAxisSpecifier, 'namespace' : ParsedNamespaceAxisSpecifier, 'self' : ParsedSelfAxisSpecifier, }
|