1
2
3 """
4 Test cases related to XPath evaluation and the XPath class
5 """
6
7 import unittest, doctest
8 from StringIO import StringIO
9
10 from common_imports import etree, HelperTestCase
11
13 """XPath tests etree"""
14
16 tree = self.parse('<a><b></b><b></b></a>')
17 self.assert_(tree.xpath('boolean(/a/b)'))
18 self.assert_(not tree.xpath('boolean(/a/c)'))
19
21 tree = self.parse('<a>1</a>')
22 self.assertEquals(1.,
23 tree.xpath('number(/a)'))
24 tree = self.parse('<a>A</a>')
25 actual = str(tree.xpath('number(/a)'))
26 expected = ['nan', '1.#qnan', 'nanq']
27 if not actual.lower() in expected:
28 self.fail('Expected a NAN value, got %s' % actual)
29
31 tree = self.parse('<a>Foo</a>')
32 self.assertEquals('Foo',
33 tree.xpath('string(/a/text())'))
34
36 tree = self.parse('<a><b/></a>')
37 self.assertEquals([],
38 tree.xpath('/'))
39
41 tree = self.parse('<a xmlns="test" xmlns:p="myURI"/>')
42 self.assert_((None, "test") in tree.xpath('namespace::*'))
43 self.assert_(('p', 'myURI') in tree.xpath('namespace::*'))
44
46 tree = self.parse('<a/>')
47 self.assertEquals([('xml', 'http://www.w3.org/XML/1998/namespace')],
48 tree.xpath('namespace::*'))
49
51 tree = self.parse('<a><b>Foo</b><b>Bar</b></a>')
52 root = tree.getroot()
53 self.assertEquals([root[0], root[1]],
54 tree.xpath('/a/b'))
55
57 tree = self.parse('<a><b/></a>')
58 self.assertEquals([],
59 tree.xpath('/a/c'))
60
61 self.assertEquals([],
62 tree.xpath('/a/c/text()'))
63
65 tree = self.parse('<a><b>Foo</b><b>Bar</b></a>')
66 root = tree.getroot()
67 self.assertEquals(['Foo', 'Bar'],
68 tree.xpath('/a/b/text()'))
69
71 tree = self.parse('<a b="B" c="C"/>')
72 self.assertEquals(['B'],
73 tree.xpath('/a/@b'))
74
79
81 root = etree.XML('<a><b><c/></b></a>')
82 el = root[0]
83 self.assert_(el.xpath('boolean(c)'))
84 self.assert_(not el.xpath('boolean(d)'))
85
87 tree = self.parse('<a><c><b>Foo</b><b>Bar</b></c><c><b>Hey</b></c></a>')
88 root = tree.getroot()
89 c = root[0]
90 self.assertEquals([c[0], c[1]],
91 c.xpath('b'))
92 self.assertEquals([c[0], c[1], root[1][0]],
93 c.xpath('//b'))
94
96 tree = self.parse('<a xmlns="uri:a"><b></b></a>')
97 root = tree.getroot()
98 self.assertEquals(
99 [root[0]],
100 tree.xpath('//foo:b', {'foo': 'uri:a'}))
101 self.assertEquals(
102 [],
103 tree.xpath('//foo:b', {'foo': 'uri:c'}))
104 self.assertEquals(
105 [root[0]],
106 root.xpath('//baz:b', {'baz': 'uri:a'}))
107
109 tree = self.parse('<a xmlns="uri:a"><b></b></a>')
110 root = tree.getroot()
111 self.assertRaises(
112 TypeError,
113 root.xpath, '//b', {None: 'uri:a'})
114
116 tree = self.parse('<a/>')
117 self.assertRaises(SyntaxError, tree.xpath, '\\fad')
118
131
144
146 tree = self.parse('<a><b><c></c></b></a>')
147 e = etree.XPathEvaluator(tree)
148 root = tree.getroot()
149 self.assertEquals(
150 [root],
151 e.evaluate('//a'))
152
154 tree = self.parse('<a><b><c></c></b></a>')
155 child_tree = etree.ElementTree(tree.getroot()[0])
156 e = etree.XPathEvaluator(child_tree)
157 self.assertEquals(
158 [],
159 e.evaluate('a'))
160 root = child_tree.getroot()
161 self.assertEquals(
162 [root[0]],
163 e.evaluate('c'))
164
166 tree = self.parse('<a><b><c></c></b></a>')
167 root = tree.getroot()
168 e = etree.XPathEvaluator(root[0])
169 self.assertEquals(
170 [root[0][0]],
171 e.evaluate('c'))
172
174 def foo(evaluator, a):
175 return 'hello %s' % a
176 extension = {(None, 'foo'): foo}
177 tree = self.parse('<a><b></b></a>')
178 e = etree.XPathEvaluator(tree, None, [extension])
179 self.assertEquals(
180 "hello you", e.evaluate("foo('you')"))
181
183 def foo(evaluator, a, b):
184 return "hello %s and %s" % (a, b)
185 extension = {(None, 'foo'): foo}
186 tree = self.parse('<a><b></b></a>')
187 e = etree.XPathEvaluator(tree, extensions=[extension])
188 self.assertRaises(TypeError, e.evaluate, "foo('you')")
189
191 def foo(evaluator, a):
192 return 1/0
193 extension = {(None, 'foo'): foo}
194 tree = self.parse('<a/>')
195 e = etree.XPathEvaluator(tree, None, [extension])
196 self.assertRaises(ZeroDivisionError, e.evaluate, "foo('test')")
197
206
207 x = self.parse('<a/>')
208 e = etree.XPathEvaluator(x, None, [{(None, 'foo'): f}])
209 r = e.evaluate("foo('World')/result")
210 self.assertEquals(2, len(r))
211 self.assertEquals('Hoi', r[0].text)
212 self.assertEquals('Dag', r[1].text)
213
222
223 x = self.parse('<a/>')
224 e = etree.XPathEvaluator(x, None, [{(None, 'foo'): f}])
225 r = e.evaluate("foo(/*)/result")
226 self.assertEquals(2, len(r))
227 self.assertEquals('Hoi', r[0].text)
228 self.assertEquals('Dag', r[1].text)
229
239
240 x = self.parse('<result>Honk</result>')
241 e = etree.XPathEvaluator(x, None, [{(None, 'foo'): f}])
242 r = e.evaluate("foo(/*)/result")
243 self.assertEquals(3, len(r))
244 self.assertEquals('Hoi', r[0].text)
245 self.assertEquals('Dag', r[1].text)
246 self.assertEquals('Honk', r[2].text)
247
249 x = self.parse('<a attr="true"/>')
250 e = etree.XPathEvaluator(x)
251
252 expr = "/a[@attr=$aval]"
253 r = e.evaluate(expr, aval=1)
254 self.assertEquals(0, len(r))
255
256 r = e.evaluate(expr, aval="true")
257 self.assertEquals(1, len(r))
258 self.assertEquals("true", r[0].get('attr'))
259
260 r = e.evaluate(expr, aval=True)
261 self.assertEquals(1, len(r))
262 self.assertEquals("true", r[0].get('attr'))
263
265 x = self.parse('<a attr="true"/>')
266 e = etree.XPathEvaluator(x)
267
268 element = etree.Element("test-el")
269 etree.SubElement(element, "test-sub")
270 expr = "$value"
271 r = e.evaluate(expr, value=element)
272 self.assertEquals(1, len(r))
273 self.assertEquals(element.tag, r[0].tag)
274 self.assertEquals(element[0].tag, r[0][0].tag)
275
277 x = self.parse('<a attr="true"><test/></a>')
278
279 class LocalException(Exception):
280 pass
281
282 def foo(evaluator, a, varval):
283 etree.Element("DUMMY")
284 if varval == 0:
285 raise LocalException
286 elif varval == 1:
287 return ()
288 elif varval == 2:
289 return None
290 elif varval == 3:
291 return a[0][0]
292 a = a[0]
293 if a.get("attr") == str(varval):
294 return a
295 else:
296 return etree.Element("NODE")
297
298 extension = {(None, 'foo'): foo}
299 e = etree.XPathEvaluator(x, extensions=[extension])
300 del x
301
302 self.assertRaises(LocalException, e.evaluate, "foo(., 0)")
303 self.assertRaises(LocalException, e.evaluate, "foo(., $value)", value=0)
304
305 r = e.evaluate("foo(., $value)", value=1)
306 self.assertEqual(len(r), 0)
307
308 r = e.evaluate("foo(., 1)")
309 self.assertEqual(len(r), 0)
310
311 r = e.evaluate("foo(., $value)", value=2)
312 self.assertEqual(len(r), 0)
313
314 r = e.evaluate("foo(., $value)", value=3)
315 self.assertEqual(len(r), 1)
316 self.assertEqual(r[0].tag, "test")
317
318 r = e.evaluate("foo(., $value)", value="false")
319 self.assertEqual(len(r), 1)
320 self.assertEqual(r[0].tag, "NODE")
321
322 r = e.evaluate("foo(., 'false')")
323 self.assertEqual(len(r), 1)
324 self.assertEqual(r[0].tag, "NODE")
325
326 r = e.evaluate("foo(., 'true')")
327 self.assertEqual(len(r), 1)
328 self.assertEqual(r[0].tag, "a")
329 self.assertEqual(r[0][0].tag, "test")
330
331 r = e.evaluate("foo(., $value)", value="true")
332 self.assertEqual(len(r), 1)
333 self.assertEqual(r[0].tag, "a")
334
335 self.assertRaises(LocalException, e.evaluate, "foo(., 0)")
336 self.assertRaises(LocalException, e.evaluate, "foo(., $value)", value=0)
337
338
340 "Tests for the XPath class"
342 x = self.parse('<a attr="true"/>')
343
344 expr = etree.XPath("/a[@attr != 'true']")
345 r = expr.evaluate(x)
346 self.assertEquals(0, len(r))
347
348 expr = etree.XPath("/a[@attr = 'true']")
349 r = expr.evaluate(x)
350 self.assertEquals(1, len(r))
351
352 expr = etree.XPath( expr.path )
353 r = expr.evaluate(x)
354 self.assertEquals(1, len(r))
355
357 x = self.parse('<a><b/><c/></a>')
358 root = x.getroot()
359
360 expr = etree.XPath("./b")
361 r = expr.evaluate(root)
362 self.assertEquals(1, len(r))
363 self.assertEquals('b', r[0].tag)
364
365 expr = etree.XPath("./*")
366 r = expr.evaluate(root)
367 self.assertEquals(2, len(r))
368
370 x = self.parse('<a attr="true"/>')
371
372 expr = etree.XPath("/a[@attr=$aval]")
373 r = expr.evaluate(x, aval=False)
374 self.assertEquals(0, len(r))
375
376 r = expr.evaluate(x, aval=True)
377 self.assertEquals(1, len(r))
378
380 self.assertRaises(SyntaxError, etree.XPath, '\\fad')
381
384
386 "Tests for the ETXPath class"
388 x = self.parse('<a><b xmlns="nsa"/><b xmlns="nsb"/></a>')
389
390 expr = etree.ETXPath("/a/{nsa}b")
391 r = expr.evaluate(x)
392 self.assertEquals(1, len(r))
393 self.assertEquals('{nsa}b', r[0].tag)
394
395 expr = etree.ETXPath("/a/{nsb}b")
396 r = expr.evaluate(x)
397 self.assertEquals(1, len(r))
398 self.assertEquals('{nsb}b', r[0].tag)
399
401 x = self.parse(u'<a><b xmlns="nsa\uf8d2"/><b xmlns="nsb\uf8d1"/></a>')
402
403 expr = etree.ETXPath(u"/a/{nsa\uf8d2}b")
404 r = expr.evaluate(x)
405 self.assertEquals(1, len(r))
406 self.assertEquals(u'{nsa\uf8d2}b', r[0].tag)
407
408 expr = etree.ETXPath(u"/a/{nsb\uf8d1}b")
409 r = expr.evaluate(x)
410 self.assertEquals(1, len(r))
411 self.assertEquals(u'{nsb\uf8d1}b', r[0].tag)
412
413 SAMPLE_XML = etree.parse(StringIO("""
414 <body>
415 <tag>text</tag>
416 <section>
417 <tag>subtext</tag>
418 </section>
419 <tag />
420 <tag />
421 </body>
422 """))
423
426
429
432
435
438
441
443 return ", ".join(map(str, (s, f, b, map(tag, st))))
444
446 st1.extend(st2)
447 return st1
448
451
454
455 uri = "http://www.example.com/"
456
457 extension = {(None, 'stringTest'): stringTest,
458 (None, 'floatTest'): floatTest,
459 (None, 'booleanTest'): booleanTest,
460 (None, 'setTest'): setTest,
461 (None, 'setTest2'): setTest2,
462 (None, 'argsTest1'): argsTest1,
463 (None, 'argsTest2'): argsTest2,
464 (None, 'resultTypesTest'): resultTypesTest,
465 (None, 'resultTypesTest2'): resultTypesTest2,}
466
468 """
469 Test xpath extension functions.
470
471 >>> root = SAMPLE_XML
472 >>> e = etree.XPathEvaluator(root, None, [extension])
473 >>> e.evaluate("stringTest('you')")
474 'Hello you'
475 >>> e.evaluate(u"stringTest('\xe9lan')")
476 u'Hello \\xe9lan'
477 >>> e.evaluate("stringTest('you','there')")
478 Traceback (most recent call last):
479 ...
480 TypeError: stringTest() takes exactly 2 arguments (3 given)
481 >>> e.evaluate("floatTest(2)")
482 6.0
483 >>> e.evaluate("booleanTest(true())")
484 False
485 >>> map(tag, e.evaluate("setTest(/body/tag)"))
486 ['tag']
487 >>> map(tag, e.evaluate("setTest2(/body/*)"))
488 ['tag', 'section']
489 >>> e.evaluate("argsTest1('a',1.5,true(),/body/tag)")
490 "a, 1.5, True, ['tag', 'tag', 'tag']"
491 >>> map(tag, e.evaluate("argsTest2(/body/tag, /body/section)"))
492 ['tag', 'section', 'tag', 'tag']
493 >>> e.evaluate("resultTypesTest()")
494 Traceback (most recent call last):
495 ...
496 XPathResultError: This is not a node: x
497 >>> try:
498 ... e.evaluate("resultTypesTest2()")
499 ... except etree.XPathResultError:
500 ... print "Got error"
501 Got error
502 """
503
505 suite = unittest.TestSuite()
506 suite.addTests([unittest.makeSuite(ETreeXPathTestCase)])
507 suite.addTests([unittest.makeSuite(ETreeXPathClassTestCase)])
508 suite.addTests([unittest.makeSuite(ETreeETXPathClassTestCase)])
509 suite.addTests([doctest.DocTestSuite()])
510 suite.addTests(
511 [doctest.DocFileSuite('../../../doc/xpathxslt.txt')])
512 return suite
513
514 if __name__ == '__main__':
515 unittest.main()
516