| Home | Trees | Indices | Help |
|
|---|
|
|
1 #
2 # ElementTree
3 # $Id: ElementPath.py 3276 2007-09-12 06:52:30Z fredrik $
4 #
5 # limited xpath support for element trees
6 #
7 # history:
8 # 2003-05-23 fl created
9 # 2003-05-28 fl added support for // etc
10 # 2003-08-27 fl fixed parsing of periods in element names
11 # 2007-09-10 fl new selection engine
12 #
13 # Copyright (c) 2003-2007 by Fredrik Lundh. All rights reserved.
14 #
15 # fredrik@pythonware.com
16 # http://www.pythonware.com
17 #
18 # --------------------------------------------------------------------
19 # The ElementTree toolkit is
20 #
21 # Copyright (c) 1999-2007 by Fredrik Lundh
22 #
23 # By obtaining, using, and/or copying this software and/or its
24 # associated documentation, you agree that you have read, understood,
25 # and will comply with the following terms and conditions:
26 #
27 # Permission to use, copy, modify, and distribute this software and
28 # its associated documentation for any purpose and without fee is
29 # hereby granted, provided that the above copyright notice appears in
30 # all copies, and that both that copyright notice and this permission
31 # notice appear in supporting documentation, and that the name of
32 # Secret Labs AB or the author not be used in advertising or publicity
33 # pertaining to distribution of the software without specific, written
34 # prior permission.
35 #
36 # SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
37 # TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
38 # ABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
39 # BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
40 # DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 # WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
42 # ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
43 # OF THIS SOFTWARE.
44 # --------------------------------------------------------------------
45
46 ##
47 # Implementation module for XPath support. There's usually no reason
48 # to import this module directly; the <b>ElementTree</b> does this for
49 # you, if needed.
50 ##
51
52 import re
53
54 xpath_tokenizer = re.compile(
55 "("
56 "'[^']*'|\"[^\"]*\"|"
57 "::|"
58 "//?|"
59 "\.\.|"
60 "\(\)|"
61 "[/.*:\[\]\(\)@=])|"
62 "((?:\{[^}]+\})?[^/:\[\]\(\)@=\s]+)|"
63 "\s+"
64 ).findall
65
67 tag = token[1]
68 def select(result):
69 for elem in result:
70 for e in elem.iterchildren(tag=tag):
71 yield e
72 return select
73
79 return select
80
84 return select
85
87 token = next()
88 if token[0] == "*":
89 tag = "*"
90 elif not token[0]:
91 tag = token[1]
92 else:
93 raise SyntaxError
94 def select(result):
95 for elem in result:
96 for e in elem.iterdescendants(tag=tag):
97 yield e
98 return select
99
101 def select(result):
102 for elem in result:
103 parent = elem.getparent()
104 if parent is not None:
105 yield parent
106 return select
107
109 # this one should probably be refactored...
110 token = next()
111 if token[0] == "@":
112 # attribute
113 token = next()
114 if token[0]:
115 raise SyntaxError("invalid attribute predicate")
116 key = token[1]
117 token = next()
118 if token[0] == "]":
119 def select(result):
120 for elem in result:
121 if elem.get(key) is not None:
122 yield elem
123 elif token[0] == "=":
124 value = next()[0]
125 if value[:1] == "'" or value[:1] == '"':
126 value = value[1:-1]
127 else:
128 raise SyntaxError("invalid comparison target")
129 token = next()
130 def select(result):
131 for elem in result:
132 if elem.get(key) == value:
133 yield elem
134 if token[0] != "]":
135 raise SyntaxError("invalid attribute predicate")
136 elif not token[0]:
137 tag = token[1]
138 token = next()
139 if token[0] != "]":
140 raise SyntaxError("invalid node predicate")
141 def select(result):
142 for elem in result:
143 try:
144 elem.iterdescendants(tag).next()
145 yield elem
146 except StopIteration:
147 pass
148 else:
149 raise SyntaxError("invalid predicate")
150 return select
151
152 ops = {
153 "": prepare_tag,
154 "*": prepare_star,
155 ".": prepare_dot,
156 "..": prepare_dot_dot,
157 "//": prepare_iter,
158 "[": prepare_predicate,
159 }
160
161 _cache = {}
162
163 # --------------------------------------------------------------------
164
166 # compile selector pattern
167 try:
168 return _cache[path]
169 except KeyError:
170 pass
171 if len(_cache) > 100:
172 _cache.clear()
173
174 if path[:1] == "/":
175 raise SyntaxError("cannot use absolute path on element")
176 stream = iter(xpath_tokenizer(path))
177 next = stream.next; token = next()
178 selector = []
179 while 1:
180 try:
181 selector.append(ops[token[0]](next, token))
182 except StopIteration:
183 raise SyntaxError("invalid path")
184 try:
185 token = next()
186 if token[0] == "/":
187 token = next()
188 except StopIteration:
189 break
190 return selector
191
192 ##
193 # Iterate over the matching nodes
194
196 # execute selector pattern
197 selector = _build_path_iterator(path)
198 result = iter((elem,))
199 for select in selector:
200 result = select(result)
201 return result
202
203 ##
204 # Find first matching object.
205
211
212 ##
213 # Find all matching objects.
214
217
218 ##
219 # Find text for first matching object.
220
227
| Home | Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0 on Fri Feb 1 19:02:32 2008 | http://epydoc.sourceforge.net |