1
2
3 """
4 Tests for the ElementPath implementation.
5 """
6
7 from __future__ import absolute_import
8
9 import unittest
10 from copy import deepcopy
11 from .common_imports import etree, HelperTestCase
12
13
16
19
24
25
27 etree = etree
28 from lxml import _elementpath
29
31 self._elementpath._cache.clear()
32 el = self.etree.XML(b'<a><b><c/><c/></b></a>')
33 self.assertFalse(self._elementpath._cache)
34
35 self.assertTrue(el.findall('b/c'))
36 self.assertEqual(1, len(self._elementpath._cache))
37 self.assertTrue(el.findall('b/c'))
38 self.assertEqual(1, len(self._elementpath._cache))
39 self.assertFalse(el.findall('xxx'))
40 self.assertEqual(2, len(self._elementpath._cache))
41 self.assertFalse(el.findall('xxx'))
42 self.assertEqual(2, len(self._elementpath._cache))
43 self.assertTrue(el.findall('b/c'))
44 self.assertEqual(2, len(self._elementpath._cache))
45
48
50 assert_tokens = self._assert_tokens
51 assert_tokens(
52 [('/', '')],
53 '/',
54 )
55 assert_tokens(
56 [('.', ''), ('/', ''), ('', 'a'), ('/', ''), ('', 'b'), ('/', ''), ('', 'c')],
57 './a/b/c',
58 )
59 assert_tokens(
60 [('/', ''), ('', 'a'), ('/', ''), ('', 'b'), ('/', ''), ('', 'c')],
61 '/a/b/c',
62 )
63 assert_tokens(
64 [('/', ''), ('', '{nsx}a'), ('/', ''), ('', '{nsy}b'), ('/', ''), ('', 'c')],
65 '/x:a/y:b/c',
66 {'x': 'nsx', 'y': 'nsy'},
67 )
68 assert_tokens(
69 [('/', ''), ('', '{nsx}a'), ('/', ''), ('', '{nsy}b'), ('/', ''), ('', '{nsnone}c')],
70 '/x:a/y:b/c',
71 {'x': 'nsx', 'y': 'nsy', None: 'nsnone'},
72 )
73
75 assert_tokens = self._assert_tokens
76 assert_tokens(
77 [('', 'a'), ('[', ''), ('', 'b'), (']', '')],
78 'a[b]',
79 )
80 assert_tokens(
81 [('', 'a'), ('[', ''), ('', 'b'), ('=', ''), ('"abc"', ''), (']', '')],
82 'a[b="abc"]',
83 )
84 assert_tokens(
85 [('', 'a'), ('[', ''), ('.', ''), ('', ''), ('=', ''), ('', ''), ('"abc"', ''), (']', '')],
86 'a[. = "abc"]',
87 )
88
90
91 ElementPath = self._elementpath
92
93 def check(p, expected, namespaces=None):
94 self.assertEqual([op or tag
95 for op, tag in ElementPath.xpath_tokenizer(p, namespaces)],
96 expected)
97
98
99 check("*", ['*'])
100 check("text()", ['text', '()'])
101 check("@name", ['@', 'name'])
102 check("@*", ['@', '*'])
103 check("para[1]", ['para', '[', '1', ']'])
104 check("para[last()]", ['para', '[', 'last', '()', ']'])
105 check("*/para", ['*', '/', 'para'])
106 check("/doc/chapter[5]/section[2]",
107 ['/', 'doc', '/', 'chapter', '[', '5', ']',
108 '/', 'section', '[', '2', ']'])
109 check("chapter//para", ['chapter', '//', 'para'])
110 check("//para", ['//', 'para'])
111 check("//olist/item", ['//', 'olist', '/', 'item'])
112 check(".", ['.'])
113 check(".//para", ['.', '//', 'para'])
114 check("..", ['..'])
115 check("../@lang", ['..', '/', '@', 'lang'])
116 check("chapter[title]", ['chapter', '[', 'title', ']'])
117 check("employee[@secretary and @assistant]", ['employee',
118 '[', '@', 'secretary', '', 'and', '', '@', 'assistant', ']'])
119
120
121 check("@{ns}attr", ['@', '{ns}attr'])
122 check("{http://spam}egg", ['{http://spam}egg'])
123 check("./spam.egg", ['.', '/', 'spam.egg'])
124 check(".//{http://spam}egg", ['.', '//', '{http://spam}egg'])
125
126
127 check("{ns}*", ['{ns}*'])
128 check("{}*", ['{}*'])
129 check("{*}tag", ['{*}tag'])
130 check("{*}*", ['{*}*'])
131 check(".//{*}tag", ['.', '//', '{*}tag'])
132
133
134 check("./xsd:type", ['.', '/', '{http://www.w3.org/2001/XMLSchema}type'],
135 {'xsd': 'http://www.w3.org/2001/XMLSchema'})
136 check("type", ['{http://www.w3.org/2001/XMLSchema}type'],
137 {'': 'http://www.w3.org/2001/XMLSchema'})
138 check("@xsd:type", ['@', '{http://www.w3.org/2001/XMLSchema}type'],
139 {'xsd': 'http://www.w3.org/2001/XMLSchema'})
140 check("@type", ['@', 'type'],
141 {'': 'http://www.w3.org/2001/XMLSchema'})
142 check("@{*}type", ['@', '{*}type'],
143 {'': 'http://www.w3.org/2001/XMLSchema'})
144 check("@{ns}attr", ['@', '{ns}attr'],
145 {'': 'http://www.w3.org/2001/XMLSchema',
146 'ns': 'http://www.w3.org/2001/XMLSchema'})
147
149 """
150 Test find methods (including xpath syntax).
151 Originally copied from 'selftest.py'.
152 """
153 elem = etree.XML("""
154 <body>
155 <tag class='a'>text</tag>
156 <tag class='b' />
157 <section>
158 <tag class='b' id='inner'>subtext</tag>
159 </section>
160 </body>
161 """)
162
163 self.assertEqual(elem.find("tag").tag,
164 'tag')
165 self.assertEqual(etree.ElementTree(elem).find("tag").tag,
166 'tag')
167 self.assertEqual(elem.find("section/tag").tag,
168 'tag')
169 self.assertEqual(etree.ElementTree(elem).find("section/tag").tag,
170 'tag')
171
172 self.assertEqual(elem.findtext("tag"),
173 'text')
174 self.assertEqual(elem.findtext("tog"),
175 None)
176 self.assertEqual(elem.findtext("tog", "default"),
177 'default')
178 self.assertEqual(etree.ElementTree(elem).findtext("tag"),
179 'text')
180 self.assertEqual(elem.findtext("section/tag"),
181 'subtext')
182 self.assertEqual(etree.ElementTree(elem).findtext("section/tag"),
183 'subtext')
184
185 self.assertEqual(summarize_list(elem.findall("tag")),
186 ['tag', 'tag'])
187 self.assertEqual(summarize_list(elem.findall("*")),
188 ['tag', 'tag', 'section'])
189 self.assertEqual(summarize_list(elem.findall(".//tag")),
190 ['tag', 'tag', 'tag'])
191 self.assertEqual(summarize_list(elem.findall("section/tag")),
192 ['tag'])
193 self.assertEqual(summarize_list(elem.findall("section//tag")),
194 ['tag'])
195
196 self.assertEqual(summarize_list(elem.findall("section/*")),
197 ['tag'])
198 self.assertEqual(summarize_list(elem.findall("section//*")),
199 ['tag'])
200 self.assertEqual(summarize_list(elem.findall("section/.//*")),
201 ['tag'])
202 self.assertEqual(summarize_list(elem.findall("*/*")),
203 ['tag'])
204 self.assertEqual(summarize_list(elem.findall("*//*")),
205 ['tag'])
206 self.assertEqual(summarize_list(elem.findall("*/tag")),
207 ['tag'])
208 self.assertEqual(summarize_list(elem.findall("*/./tag")),
209 ['tag'])
210 self.assertEqual(summarize_list(elem.findall("./tag")),
211 ['tag', 'tag'])
212 self.assertEqual(summarize_list(elem.findall(".//tag")),
213 ['tag', 'tag', 'tag'])
214 self.assertEqual(summarize_list(elem.findall("././tag")),
215 ['tag', 'tag'])
216
217 self.assertEqual(summarize_list(elem.findall(".//tag[@class]")),
218 ['tag', 'tag', 'tag'])
219 self.assertEqual(summarize_list(elem.findall(".//tag[ @class]")),
220 ['tag', 'tag', 'tag'])
221 self.assertEqual(summarize_list(elem.findall(".//tag[@class ]")),
222 ['tag', 'tag', 'tag'])
223 self.assertEqual(summarize_list(elem.findall(".//tag[ @class ]")),
224 ['tag', 'tag', 'tag'])
225 self.assertEqual(summarize_list(elem.findall(".//tag[@class='a']")),
226 ['tag'])
227 self.assertEqual(summarize_list(elem.findall('.//tag[@class="a"]')),
228 ['tag'])
229 self.assertEqual(summarize_list(elem.findall(".//tag[@class='b']")),
230 ['tag', 'tag'])
231 self.assertEqual(summarize_list(elem.findall('.//tag[@class="b"]')),
232 ['tag', 'tag'])
233 self.assertEqual(summarize_list(elem.findall('.//tag[@class = "b"]')),
234 ['tag', 'tag'])
235 self.assertEqual(summarize_list(elem.findall(".//tag[@id]")),
236 ['tag'])
237 self.assertEqual(summarize_list(elem.findall(".//tag[@class][@id]")),
238 ['tag'])
239 self.assertEqual(summarize_list(elem.findall(".//section[tag]")),
240 ['section'])
241 self.assertEqual(summarize_list(elem.findall(".//section[element]")),
242 [])
243
244 self.assertEqual(summarize_list(elem.findall(".//section[tag='subtext']")),
245 ['section'])
246 self.assertEqual(summarize_list(elem.findall(".//section[tag ='subtext']")),
247 ['section'])
248 self.assertEqual(summarize_list(elem.findall(".//section[tag= 'subtext']")),
249 ['section'])
250 self.assertEqual(summarize_list(elem.findall(".//section[tag = 'subtext']")),
251 ['section'])
252 self.assertEqual(summarize_list(elem.findall(".//section[ tag = 'subtext' ]")),
253 ['section'])
254 self.assertEqual(summarize_list(elem.findall(".//tag[.='subtext']")),
255 ['tag'])
256 self.assertEqual(summarize_list(elem.findall(".//tag[. ='subtext']")),
257 ['tag'])
258 self.assertEqual(summarize_list(elem.findall('.//tag[.= "subtext"]')),
259 ['tag'])
260 self.assertEqual(summarize_list(elem.findall(".//tag[. = 'subtext']")),
261 ['tag'])
262 self.assertEqual(summarize_list(elem.findall(".//tag[. = 'subtext ']")),
263 [])
264 self.assertEqual(summarize_list(elem.findall(".//tag[.= ' subtext']")),
265 [])
266
267 self.assertEqual(summarize_list(elem.findall("../tag")),
268 [])
269 self.assertEqual(summarize_list(elem.findall("section/../tag")),
270 ['tag', 'tag'])
271 self.assertEqual(summarize_list(etree.ElementTree(elem).findall("./tag")),
272 ['tag', 'tag'])
273
274
275
276 self.assertEqual(summarize_list(etree.ElementTree(elem).findall("/tag")),
277 ['tag', 'tag'])
278
279
280 elem[1] = deepcopy(elem[2])
281 self.assertEqual(summarize_list(elem.findall(".//section[tag = 'subtext']")),
282 ['section', 'section'])
283 self.assertEqual(summarize_list(elem.findall(".//tag[. = 'subtext']")),
284 ['tag', 'tag'])
285 self.assertEqual(summarize_list(elem.findall(".//tag[@class][@id]")),
286 ['tag', 'tag'])
287
288
289
290
291
292
293
295 suite = unittest.TestSuite()
296 suite.addTests([unittest.makeSuite(EtreeElementPathTestCase)])
297
298 return suite
299
300
301 if __name__ == '__main__':
302 print('to test use test.py %s' % __file__)
303