~landscape/zope3/newer-from-ztk

« back to all changes in this revision

Viewing changes to src/twisted/words/xish/xpath.py

  • Committer: Thomas Hervé
  • Date: 2009-07-08 13:52:04 UTC
  • Revision ID: thomas@canonical.com-20090708135204-df5eesrthifpylf8
Remove twisted copy

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
# -*- test-case-name: twisted.words.test.test_xpath -*-
2
 
#
3
 
# Copyright (c) 2001-2005 Twisted Matrix Laboratories.
4
 
# See LICENSE for details.
5
 
 
6
 
 
7
 
try:
8
 
    import cStringIO as StringIO
9
 
except ImportError:
10
 
    import StringIO
11
 
 
12
 
def _isStr(s):
13
 
    """ Internal method to determine if an object is a string """
14
 
    return isinstance(s, type('')) or isinstance(s, type(u''))
15
 
 
16
 
class LiteralValue(str):
17
 
    def value(self, elem):
18
 
        return self
19
 
    
20
 
class IndexValue:
21
 
    def __init__(self, index):
22
 
        self.index = int(index) - 1
23
 
 
24
 
    def value(self, elem):
25
 
        return elem.children[self.index]
26
 
 
27
 
class AttribValue:
28
 
    def __init__(self, attribname):        
29
 
        self.attribname = attribname
30
 
        if self.attribname == "xmlns":
31
 
            self.value = self.value_ns
32
 
 
33
 
    def value_ns(self, elem):
34
 
        return elem.uri 
35
 
 
36
 
    def value(self, elem):
37
 
        if self.attribname in elem.attributes:
38
 
            return elem.attributes[self.attribname]
39
 
        else:
40
 
            return None
41
 
 
42
 
class CompareValue:
43
 
    def __init__(self, lhs, op, rhs):
44
 
        self.lhs = lhs
45
 
        self.rhs = rhs
46
 
        if op == "=":
47
 
            self.value = self._compareEqual
48
 
        else:
49
 
            self.value = self._compareNotEqual
50
 
 
51
 
    def _compareEqual(self, elem):
52
 
        return self.lhs.value(elem) == self.rhs.value(elem)
53
 
 
54
 
    def _compareNotEqual(self, elem):
55
 
        return self.lhs.value(elem) != self.rhs.value(elem)
56
 
 
57
 
def Function(fname):
58
 
    """ Internal method which selects the function object """
59
 
    klassname = "_%s_Function" % fname
60
 
    c = globals()[klassname]()
61
 
    return c
62
 
 
63
 
class _not_Function:
64
 
    def __init__(self):
65
 
        self.baseValue = None
66
 
 
67
 
    def setParams(self, baseValue):
68
 
        self.baseValue = baseValue
69
 
        
70
 
    def value(self, elem):
71
 
        return not self.baseValue.value(elem)
72
 
 
73
 
class _text_Function:
74
 
    def setParams(self):
75
 
        pass
76
 
    
77
 
    def value(self, elem):
78
 
        return str(elem)
79
 
 
80
 
class _Location:
81
 
    def __init__(self):
82
 
        self.predicates = []
83
 
        self.elementName  = None
84
 
        self.childLocation = None
85
 
 
86
 
    def matchesPredicates(self, elem):
87
 
        if self.elementName != None and self.elementName != elem.name:
88
 
            return 0
89
 
                
90
 
        for p in self.predicates:
91
 
            if not p.value(elem):
92
 
                return 0
93
 
 
94
 
        return 1
95
 
 
96
 
    def matches(self, elem):
97
 
        if not self.matchesPredicates(elem):
98
 
            return 0
99
 
 
100
 
        if self.childLocation != None:
101
 
            for c in elem.elements():
102
 
                if self.childLocation.matches(c):
103
 
                    return 1
104
 
        else:
105
 
            return 1
106
 
 
107
 
        return 0
108
 
 
109
 
    def queryForString(self, elem, resultbuf):
110
 
        if not self.matchesPredicates(elem):
111
 
            return 
112
 
 
113
 
        if self.childLocation != None:
114
 
            for c in elem.elements():
115
 
                self.childLocation.queryForString(c, resultbuf)
116
 
        else:            
117
 
            resultbuf.write(str(elem))
118
 
 
119
 
    def queryForNodes(self, elem, resultlist):
120
 
        if not self.matchesPredicates(elem):
121
 
            return 
122
 
 
123
 
        if self.childLocation != None:
124
 
            for c in elem.elements():
125
 
                self.childLocation.queryForNodes(c, resultlist)
126
 
        else:
127
 
            resultlist.append(elem)
128
 
 
129
 
    def queryForStringList(self, elem, resultlist):
130
 
        if not self.matchesPredicates(elem):
131
 
            return
132
 
 
133
 
        if self.childLocation != None:
134
 
            for c in elem.elements():
135
 
                self.childLocation.queryForStringList(c, resultlist)
136
 
        else:
137
 
            for c in elem.children:
138
 
                if _isStr(c): resultlist.append(c)
139
 
 
140
 
class _AnyLocation:
141
 
    def __init__(self):
142
 
        self.predicates = []
143
 
        self.elementName = None
144
 
        self.childLocation = None
145
 
 
146
 
    def matchesPredicates(self, elem):
147
 
        for p in self.predicates:
148
 
            if not p.value(elem):
149
 
                return 0
150
 
        return 1
151
 
 
152
 
    def listParents(self, elem, parentlist):
153
 
        if elem.parent != None:
154
 
            self.listParents(elem.parent, parentlist)
155
 
        parentlist.append(elem.name)
156
 
 
157
 
    def isRootMatch(self, elem):
158
 
        if (self.elementName == None or self.elementName == elem.name) and \
159
 
           self.matchesPredicates(elem):
160
 
            if self.childLocation != None:
161
 
                for c in elem.elements():
162
 
                    if self.childLocation.matches(c):
163
 
                        return True
164
 
            else:
165
 
                return True
166
 
        return False
167
 
 
168
 
    def findFirstRootMatch(self, elem):
169
 
        if (self.elementName == None or self.elementName == elem.name) and \
170
 
           self.matchesPredicates(elem):
171
 
            # Thus far, the name matches and the predicates match,
172
 
            # now check into the children and find the first one
173
 
            # that matches the rest of the structure
174
 
            # the rest of the structure
175
 
            if self.childLocation != None:
176
 
                for c in elem.elements():
177
 
                    if self.childLocation.matches(c):
178
 
                        return c
179
 
                return None
180
 
            else:
181
 
                # No children locations; this is a match!
182
 
                return elem
183
 
        else:
184
 
            # Ok, predicates or name didn't match, so we need to start
185
 
            # down each child and treat it as the root and try
186
 
            # again
187
 
            for c in elem.elements():
188
 
                if self.matches(c):
189
 
                    return c
190
 
            # No children matched...
191
 
            return None
192
 
 
193
 
    def matches(self, elem):
194
 
        if self.isRootMatch(elem):
195
 
            return True
196
 
        else:
197
 
            # Ok, initial element isn't an exact match, walk
198
 
            # down each child and treat it as the root and try
199
 
            # again
200
 
            for c in elem.elements():
201
 
                if self.matches(c):
202
 
                    return True
203
 
            # No children matched...
204
 
            return False
205
 
 
206
 
    def queryForString(self, elem, resultbuf):
207
 
        raise "UnsupportedOperation"
208
 
 
209
 
    def queryForNodes(self, elem, resultlist):
210
 
        # First check to see if _this_ element is a root
211
 
        if self.isRootMatch(elem):
212
 
            resultlist.append(elem)
213
 
 
214
 
        # Now check each child
215
 
        for c in elem.elements():
216
 
            self.queryForNodes(c, resultlist)            
217
 
        
218
 
 
219
 
    def queryForStringList(self, elem, resultlist):
220
 
        if self.isRootMatch(elem):
221
 
            for c in elem.children:
222
 
                if _isStr(c): resultlist.append(c)
223
 
        for c in elem.elements():
224
 
            self.queryForStringList(c, resultlist)
225
 
        
226
 
 
227
 
 
228
 
class XPathQuery:
229
 
    def __init__(self, queryStr):
230
 
        self.queryStr = queryStr
231
 
        from twisted.words.xish.xpathparser import parse
232
 
        self.baseLocation = parse('XPATH', queryStr)
233
 
 
234
 
    def __hash__(self):
235
 
        return self.queryStr.__hash__()
236
 
 
237
 
    def matches(self, elem):
238
 
        return self.baseLocation.matches(elem)
239
 
 
240
 
    def queryForString(self, elem):
241
 
        result = StringIO.StringIO()
242
 
        self.baseLocation.queryForString(elem, result)
243
 
        return result.getvalue()
244
 
 
245
 
    def queryForNodes(self, elem):
246
 
        result = []
247
 
        self.baseLocation.queryForNodes(elem, result)
248
 
        if len(result) == 0:
249
 
            return None
250
 
        else:
251
 
            return result
252
 
 
253
 
    def queryForStringList(self, elem):
254
 
        result = []
255
 
        self.baseLocation.queryForStringList(elem, result)
256
 
        if len(result) == 0:
257
 
            return None
258
 
        else:
259
 
            return result
260
 
 
261
 
__internedQueries = {}
262
 
 
263
 
def internQuery(queryString):
264
 
    if queryString not in __internedQueries:
265
 
        __internedQueries[queryString] = XPathQuery(queryString)
266
 
    return __internedQueries[queryString]
267
 
 
268
 
def matches(xpathstr, elem):
269
 
    return internQuery(xpathstr).matches(elem)
270
 
 
271
 
def queryForStringList(xpathstr, elem):
272
 
    return internQuery(xpathstr).queryForStringList(elem)
273
 
 
274
 
def queryForString(xpathstr, elem):
275
 
    return internQuery(xpathstr).queryForString(elem)
276
 
 
277
 
def queryForNodes(xpathstr, elem):
278
 
    return internQuery(xpathstr).queryForNodes(elem)
279
 
 
280
 
# Convenience main to generate new xpathparser.py
281
 
if __name__ == "__main__":
282
 
    from twisted.python import yapps2
283
 
    yapps2.generate('xpathparser.g')