File: ParsedStepPattern.py

package info (click to toggle)
python-xml 0.8.4-10.1%2Blenny1
  • links: PTS
  • area: main
  • in suites: lenny
  • size: 4,972 kB
  • ctags: 10,628
  • sloc: python: 46,730; ansic: 14,354; xml: 968; makefile: 201; sh: 20
file content (147 lines) | stat: -rw-r--r-- 5,037 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
########################################################################
#
# File Name:            ParsedStepPattern.py
#
#
"""
Parse class to handle XSLT StepPatterns
WWW: http://4suite.com/4XSLT        e-mail: support@4suite.com

Copyright (c) 1999-2000 Fourthought Inc, USA.   All Rights Reserved.
See  http://4suite.com/COPYRIGHT  for license and copyright information
"""

from xml.dom import Node
from xml.xpath import ParsedToken
from xml.xslt import XsltException, Error

class StepPattern:
    def __init__(self, nodeTest, axisType, parent=None, parentAxis=None):
        self.nodeTest = nodeTest
        self.axisType = axisType
        self.priority = nodeTest.priority
        self.parent = parent
        self.parentAxis = parentAxis

    def getShortcut(self):
        return (self.nodeTest, self.axisType)

    def match(self, context, node, nodeType):
        raise Exception('subclass should override')
        
    def pprint(self, indent=''):
        print indent + str(self)
        self.nodeTest.pprint(indent + '  ')
        self.parent and self.parent.pprint(indent + '  ')

    def __str__(self):
        return '<%s at %x: %s>' % (
            self.__class__.__name__,
            id(self),
            repr(self))

    def __repr__(self):
        st = (self.axisType == Node.ATTRIBUTE_NODE and '@' or '')
        return st + repr(self.nodeTest)

class ParentStepPattern(StepPattern):
    def getShortcut(self):
        return (self, self.axisType)

    def match(self, context, node, axisType):
        # Called when there is another step following
        if self.nodeTest.match(context, node, self.axisType):
            if node.parentNode:
                node = node.parentNode
            elif node.nodeType == Node.ATTRIBUTE_NODE:
                node = node.ownerElement
            return self.parent.match(context, node, self.parentAxis)
        return 0

    def __repr__(self):
        st = '/' + (self.axisType == Node.ATTRIBUTE_NODE and '@' or '')
        return repr(self.parent) + st + repr(self.nodeTest)

class RootParentStepPattern(StepPattern):
    def getShortcut(self):
        return (self, self.axisType)

    def match(self, context, node, axisType):
        if self.nodeTest.match(context, node, axisType):
            return node.parentNode == node.ownerDocument
        return 0

    def __repr__(self):
        prefix = '/' + (self.axisType == Node.ATTRIBUTE_NODE and '@' or '')
        suffix = self.parent and repr(self.parent) or ''
        return prefix + repr(self.nodeTest) + suffix
    
class AncestorStepPattern(StepPattern):
    def getShortcut(self):
        return (self, self.axisType)

    def match(self, context, node, axisType):
        # Called when there is another step following
        if self.nodeTest.match(context, node, self.axisType):
            if node.parentNode:
                node = node.parentNode
            elif node.nodeType == Node.ATTRIBUTE_NODE:
                node = node.ownerElement
            while node:
                if self.parent.match(context, node, self.parentAxis):
                    return 1
                node = node.parentNode
        return 0

    def __repr__(self):
        st = '//' + (self.axisType == Node.ATTRIBUTE_NODE and '@' or '')
        return repr(self.parent) + st + repr(self.nodeTest)
        
class PredicateStepPattern:
    def __init__(self, nodeTest, axisType, predicates):
        self.nodeTest = nodeTest
        self.axisType = axisType
        self.predicates = predicates
        self.priority = 0.5
        
    def getShortcut(self):
        return (self, None)

    def match(self, context, node, axisType):
        if node.parentNode:
            parent = node.parentNode
            node_set = parent.childNodes
        elif node.nodeType == Node.ATTRIBUTE_NODE == self.axisType:
            parent = node.ownerElement
            node_set = parent.attributes.values()
        else:
            # Must be a document, it only matches '/'
            return 0

        # Pass through the NodeTest
        node_set = filter(lambda node,
                                 match=self.nodeTest.match,
                                 context=context,
                                 principalType=self.axisType:
                          match(context, node, principalType),
                          node_set)
        
        # Our axes are forward only
        if node_set:
            original = context.node
            context.node = parent
            node_set = self.predicates.filter(node_set, context, 0)
            context.node = original
        return node in node_set

    def pprint(self, indent=''):
        print indent + '<%s at %x: %s>' % (
            self.__class__.__name__,
            id(self),
            repr(self))
        self.nodeTest.pprint(indent + '  ')
        self.predicates.pprint(indent + '  ')

    def __repr__(self):
        prefix = self.axisType == Node.ATTRIBUTE_NODE and '@' or ''
        return prefix + repr(self.nodeTest) + repr(self.predicates)