annotate markup/path.py @ 24:5a4d45703319 trunk

Cosmetic (mostly whitespace) changes.
author cmlenz
date Mon, 26 Jun 2006 17:54:00 +0000
parents d88358f719fa
children e3be27f5bcf5
rev   line source
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
2 #
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
3 # Copyright (C) 2006 Edgewall Software
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
4 # All rights reserved.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
5 #
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
8 # are also available at http://trac.edgewall.com/license.html.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
9 #
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://projects.edgewall.com/trac/.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
13
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
14 """Basic support for evaluating XPath expressions against streams."""
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
15
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
16 import re
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
17
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
18 from markup.core import QName, Stream
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
19
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
20 __all__ = ['Path']
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
21
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
22 _QUOTES = (("'", "'"), ('"', '"'))
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
23
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
24 class Path(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
25 """Basic XPath support on markup event streams.
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
26
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
27 >>> from markup.input import XML
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
28
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
29 Selecting specific tags:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
30
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
31 >>> Path('root').select(XML('<root/>')).render()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
32 '<root/>'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
33 >>> Path('//root').select(XML('<root/>')).render()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
34 '<root/>'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
35
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
36 Using wildcards for tag names:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
37
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
38 >>> Path('*').select(XML('<root/>')).render()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
39 '<root/>'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
40 >>> Path('//*').select(XML('<root/>')).render()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
41 '<root/>'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
42
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
43 Selecting attribute values:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
44
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
45 >>> Path('@foo').select(XML('<root/>')).render()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
46 ''
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
47 >>> Path('@foo').select(XML('<root foo="bar"/>')).render()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
48 'bar'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
49
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
50 Selecting descendants:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
51
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
52 >>> Path("root/*").select(XML('<root><foo/><bar/></root>')).render()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
53 '<foo/><bar/>'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
54 >>> Path("root/bar").select(XML('<root><foo/><bar/></root>')).render()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
55 '<bar/>'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
56 >>> Path("root/baz").select(XML('<root><foo/><bar/></root>')).render()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
57 ''
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
58 >>> Path("root/foo/*").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
59 ... XML('<root><foo><bar/></foo></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
60 '<bar/>'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
61
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
62 Selecting text nodes:
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
63 >>> Path("item/text()").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
64 ... XML('<root><item>Foo</item></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
65 'Foo'
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
66 >>> Path("item/text()").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
67 ... XML('<root><item>Foo</item><item>Bar</item></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
68 'FooBar'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
69
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
70 Skipping ancestors:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
71
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
72 >>> Path("foo/bar").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
73 ... XML('<root><foo><bar/></foo></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
74 '<bar/>'
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
75 >>> Path("foo/*").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
76 ... XML('<root><foo><bar/></foo></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
77 '<bar/>'
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
78 >>> Path("root/bar").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
79 ... XML('<root><foo><bar/></foo></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
80 ''
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
81 >>> Path("root/bar").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
82 ... XML('<root><foo><bar id="1"/></foo><bar id="2"/></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
83 '<bar id="2"/>'
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
84 >>> Path("root/*/bar").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
85 ... XML('<root><foo><bar/></foo></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
86 '<bar/>'
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
87 >>> Path("root//bar").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
88 ... XML('<root><foo><bar id="1"/></foo><bar id="2"/></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
89 '<bar id="1"/><bar id="2"/>'
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
90 >>> Path("root//bar").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
91 ... XML('<root><foo><bar id="1"/></foo><bar id="2"/></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
92 '<bar id="1"/><bar id="2"/>'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
93
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
94 Using simple attribute predicates:
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
95 >>> Path("root/item[@important]").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
96 ... XML('<root><item/><item important="very"/></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
97 '<item important="very"/>'
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
98 >>> Path('root/item[@important="very"]').select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
99 ... XML('<root><item/><item important="very"/></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
100 '<item important="very"/>'
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
101 >>> Path("root/item[@important='very']").select(
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
102 ... XML('<root><item/><item important="notso"/></root>')).render()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
103 ''
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
104 >>> Path("root/item[@important!='very']").select(
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
105 ... XML('<root><item/><item important="notso"/></root>')).render()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
106 '<item/><item important="notso"/>'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
107 """
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
108
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
109 _TOKEN_RE = re.compile('(::|\.\.|\(\)|[/.:\[\]\(\)@=!])|'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
110 '([^/:\[\]\(\)@=!\s]+)|'
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
111 '\s+')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
112
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
113 def __init__(self, text):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
114 self.source = text
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
115
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
116 steps = []
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
117 cur_op = ''
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
118 cur_tag = ''
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
119 in_predicate = False
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
120 for op, tag in self._TOKEN_RE.findall(text):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
121 if op:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
122 if op == '[':
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
123 in_predicate = True
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
124 elif op == ']':
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
125 in_predicate = False
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
126 elif op.startswith('('):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
127 if cur_tag == 'text':
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
128 steps[-1] = (False, self.fn_text(), [])
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
129 else:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
130 raise NotImplementedError('XPath function "%s" not '
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
131 'supported' % cur_tag)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
132 else:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
133 cur_op += op
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
134 cur_tag = ''
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
135 else:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
136 closure = cur_op in ('', '//')
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
137 if cur_op == '@':
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
138 if tag == '*':
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
139 node_test = self.any_attribute()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
140 else:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
141 node_test = self.attribute_by_name(tag)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
142 else:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
143 if tag == '*':
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
144 node_test = self.any_element()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
145 elif in_predicate:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
146 if len(tag) > 1 and (tag[0], tag[-1]) in _QUOTES:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
147 node_test = self.literal_string(tag[1:-1])
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
148 if cur_op == '=':
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
149 node_test = self.op_eq(steps[-1][2][-1], node_test)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
150 steps[-1][2].pop()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
151 elif cur_op == '!=':
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
152 node_test = self.op_neq(steps[-1][2][-1], node_test)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
153 steps[-1][2].pop()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
154 else:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
155 node_test = self.element_by_name(tag)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
156 if in_predicate:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
157 steps[-1][2].append(node_test)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
158 else:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
159 steps.append([closure, node_test, []])
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
160 cur_op = ''
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
161 cur_tag = tag
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
162 self.steps = steps
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
163
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
164 def __repr__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
165 return '<%s "%s">' % (self.__class__.__name__, self.source)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
166
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
167 def select(self, stream):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
168 stream = iter(stream)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
169 def _generate(tests):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
170 test = self.test()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
171 for kind, data, pos in stream:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
172 result = test(kind, data, pos)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
173 if result is True:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
174 yield kind, data, pos
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
175 depth = 1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
176 while depth > 0:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
177 ev = stream.next()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
178 if ev[0] is Stream.START:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
179 depth += 1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
180 elif ev[0] is Stream.END:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
181 depth -= 1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
182 yield ev
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
183 test(*ev)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
184 elif result:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
185 yield result
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
186 return Stream(_generate(self.steps))
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
187
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
188 def test(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
189 stack = [0] # stack of cursors into the location path
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
190
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
191 def _test(kind, data, pos):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
192 if not stack:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
193 return False
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
194
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
195 if kind is Stream.END:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
196 stack.pop()
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
197 return None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
198
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
199 if kind is Stream.START:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
200 stack.append(stack[-1])
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
201
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
202 matched = False
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
203 closure, node_test, predicates = self.steps[stack[-1]]
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
204
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
205 matched = node_test(kind, data, pos)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
206 if matched and predicates:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
207 for predicate in predicates:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
208 if not predicate(kind, data, pos):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
209 matched = None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
210 break
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
211
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
212 if matched:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
213 if stack[-1] == len(self.steps) - 1:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
214 return matched
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
215
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
216 stack[-1] += 1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
217
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
218 elif kind is Stream.START and not closure:
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
219 # If this step is not a closure, it cannot be matched until the
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
220 # current element is closed... so we need to move the cursor
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
221 # back to the last closure and retest that against the current
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
222 # element
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
223 closures = [step for step in self.steps[:stack[-1]] if step[0]]
24
5a4d45703319 Cosmetic (mostly whitespace) changes.
cmlenz
parents: 23
diff changeset
224 closures.reverse()
1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
225 for closure, node_test, predicates in closures:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
226 stack[-1] -= 1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
227 if closure:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
228 matched = node_test(kind, data, pos)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
229 if matched:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
230 stack[-1] += 1
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
231 break
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
232
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
233 return None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
234
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
235 return _test
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
236
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
237 class any_element(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
238 def __call__(self, kind, data, pos):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
239 if kind is Stream.START:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
240 return True
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
241 return None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
242 def __repr__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
243 return '<%s>' % self.__class__.__name__
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
244
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
245 class element_by_name(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
246 def __init__(self, name):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
247 self.name = QName(name)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
248 def __call__(self, kind, data, pos):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
249 if kind is Stream.START:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
250 return data[0].localname == self.name
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
251 return None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
252 def __repr__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
253 return '<%s "%s">' % (self.__class__.__name__, self.name)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
254
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
255 class any_attribute(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
256 def __call__(self, kind, data, pos):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
257 if kind is Stream.START:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
258 text = ''.join([val for name, val in data[1]])
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
259 if text:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
260 return Stream.TEXT, text, pos
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
261 return None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
262 return None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
263 def __repr__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
264 return '<%s>' % (self.__class__.__name__)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
265
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
266 class attribute_by_name(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
267 def __init__(self, name):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
268 self.name = QName(name)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
269 def __call__(self, kind, data, pos):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
270 if kind is Stream.START:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
271 if self.name in data[1]:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
272 return Stream.TEXT, data[1].get(self.name), pos
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
273 return None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
274 return None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
275 def __repr__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
276 return '<%s "%s">' % (self.__class__.__name__, self.name)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
277
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
278 class fn_text(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
279 def __call__(self, kind, data, pos):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
280 if kind is Stream.TEXT:
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
281 return kind, data, pos
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
282 return None
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
283 def __repr__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
284 return '<%s>' % (self.__class__.__name__)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
285
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
286 class literal_string(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
287 def __init__(self, value):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
288 self.value = value
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
289 def __call__(self, kind, data, pos):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
290 return Stream.TEXT, self.value, (-1, -1)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
291 def __repr__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
292 return '<%s>' % (self.__class__.__name__)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
293
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
294 class op_eq(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
295 def __init__(self, lval, rval):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
296 self.lval = lval
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
297 self.rval = rval
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
298 def __call__(self, kind, data, pos):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
299 lval = self.lval(kind, data, pos)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
300 rval = self.rval(kind, data, pos)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
301 return (lval and lval[1]) == (rval and rval[1])
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
302 def __repr__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
303 return '<%s %r = %r>' % (self.__class__.__name__, self.lval,
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
304 self.rval)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
305
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
306 class op_neq(object):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
307 def __init__(self, lval, rval):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
308 self.lval = lval
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
309 self.rval = rval
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
310 def __call__(self, kind, data, pos):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
311 lval = self.lval(kind, data, pos)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
312 rval = self.rval(kind, data, pos)
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
313 return (lval and lval[1]) != (rval and rval[1])
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
314 def __repr__(self):
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
315 return '<%s %r != %r>' % (self.__class__.__name__, self.lval,
5479aae32f5a Initial import.
cmlenz
parents:
diff changeset
316 self.rval)
Copyright (C) 2012-2017 Edgewall Software