Package lxml :: Package tests :: Module test_xpathevaluator
[hide private]
[frames] | no frames]

Source Code for Module lxml.tests.test_xpathevaluator

  1  # -*- coding: utf-8 -*- 
  2   
  3  """ 
  4  Test cases related to XPath evaluation and the XPath class 
  5  """ 
  6   
  7  from __future__ import absolute_import 
  8   
  9  import unittest, sys 
 10   
 11  from .common_imports import etree, HelperTestCase, _bytes, BytesIO, doctest, make_doctest 
 12   
 13   
14 -class ETreeXPathTestCase(HelperTestCase):
15 """XPath tests etree""" 16
17 - def test_xpath_boolean(self):
18 tree = self.parse('<a><b></b><b></b></a>') 19 self.assertTrue(tree.xpath('boolean(/a/b)')) 20 self.assertTrue(not tree.xpath('boolean(/a/c)'))
21
22 - def test_xpath_number(self):
23 tree = self.parse('<a>1</a>') 24 self.assertEqual(1., 25 tree.xpath('number(/a)')) 26 tree = self.parse('<a>A</a>') 27 actual = str(tree.xpath('number(/a)')) 28 expected = ['nan', '1.#qnan', 'nanq'] 29 if not actual.lower() in expected: 30 self.fail('Expected a NAN value, got %s' % actual)
31
32 - def test_xpath_string(self):
33 tree = self.parse('<a>Foo</a>') 34 self.assertEqual('Foo', 35 tree.xpath('string(/a/text())'))
36
37 - def test_xpath_document_root(self):
38 tree = self.parse('<a><b/></a>') 39 self.assertEqual([], 40 tree.xpath('/'))
41
42 - def test_xpath_namespace(self):
43 tree = self.parse('<a xmlns="test" xmlns:p="myURI"/>') 44 self.assertTrue((None, "test") in tree.xpath('namespace::*')) 45 self.assertTrue(('p', 'myURI') in tree.xpath('namespace::*'))
46
48 tree = self.parse('<a/>') 49 self.assertEqual([('xml', 'http://www.w3.org/XML/1998/namespace')], 50 tree.xpath('namespace::*'))
51
52 - def test_xpath_list_elements(self):
53 tree = self.parse('<a><b>Foo</b><b>Bar</b></a>') 54 root = tree.getroot() 55 self.assertEqual([root[0], root[1]], 56 tree.xpath('/a/b'))
57
58 - def test_xpath_list_nothing(self):
59 tree = self.parse('<a><b/></a>') 60 self.assertEqual([], 61 tree.xpath('/a/c')) 62 # this seems to pass a different code path, also should return nothing 63 self.assertEqual([], 64 tree.xpath('/a/c/text()'))
65
66 - def test_xpath_list_text(self):
67 tree = self.parse('<a><b>Foo</b><b>Bar</b></a>') 68 root = tree.getroot() 69 self.assertEqual(['Foo', 'Bar'], 70 tree.xpath('/a/b/text()'))
71
73 tree = self.parse('<a><b>FooBar</b><b>BarFoo</b></a>') 74 root = tree.getroot() 75 self.assertEqual(['FooBar', 'BarFoo'], 76 tree.xpath('/a/b/text()')) 77 self.assertEqual([root[0], root[1]], 78 [r.getparent() for r in tree.xpath('/a/b/text()')])
79
81 tree = self.parse('<a><b>FooBar</b><b>BarFoo</b></a>') 82 root = tree.getroot() 83 self.assertEqual(['FooBar', 'BarFoo'], 84 tree.xpath('/a/b/text()', smart_strings=True)) 85 self.assertEqual([root[0], root[1]], 86 [r.getparent() for r in 87 tree.xpath('/a/b/text()', smart_strings=True)]) 88 self.assertEqual([None, None], 89 [r.attrname for r in 90 tree.xpath('/a/b/text()', smart_strings=True)]) 91 92 self.assertEqual(['FooBar', 'BarFoo'], 93 tree.xpath('/a/b/text()', smart_strings=False)) 94 self.assertEqual([False, False], 95 [hasattr(r, 'getparent') for r in 96 tree.xpath('/a/b/text()', smart_strings=False)]) 97 self.assertEqual([None, None], 98 [r.attrname for r in 99 tree.xpath('/a/b/text()', smart_strings=True)])
100
102 xml = _bytes('<a><b>FooBar\\u0680\\u3120</b><b>BarFoo\\u0680\\u3120</b></a>').decode("unicode_escape") 103 tree = self.parse(xml.encode('utf-8')) 104 root = tree.getroot() 105 self.assertEqual([_bytes('FooBar\\u0680\\u3120').decode("unicode_escape"), 106 _bytes('BarFoo\\u0680\\u3120').decode("unicode_escape")], 107 tree.xpath('/a/b/text()')) 108 self.assertEqual([root[0], root[1]], 109 [r.getparent() for r in tree.xpath('/a/b/text()')])
110
112 tree = self.parse('<a b="B" c="C"/>') 113 self.assertEqual(['B'], 114 tree.xpath('/a/@b'))
115
117 tree = self.parse('<a b="BaSdFgHjKl" c="CqWeRtZuI"/>') 118 results = tree.xpath('/a/@c') 119 self.assertEqual(1, len(results)) 120 self.assertEqual('CqWeRtZuI', results[0]) 121 self.assertEqual(tree.getroot().tag, results[0].getparent().tag)
122
124 tree = self.parse('<a b="BaSdFgHjKl" c="CqWeRtZuI"/>') 125 126 results = tree.xpath('/a/@c', smart_strings=True) 127 self.assertEqual(1, len(results)) 128 self.assertEqual('CqWeRtZuI', results[0]) 129 self.assertEqual('c', results[0].attrname) 130 self.assertEqual(tree.getroot().tag, results[0].getparent().tag) 131 132 results = tree.xpath('/a/@c', smart_strings=False) 133 self.assertEqual(1, len(results)) 134 self.assertEqual('CqWeRtZuI', results[0]) 135 self.assertEqual(False, hasattr(results[0], 'getparent')) 136 self.assertEqual(False, hasattr(results[0], 'attrname'))
137
139 xml_data = ''' 140 <table> 141 <item xml:id="k1"><value>v1</value></item> 142 <item xml:id="k2"><value>v2</value></item> 143 </table> 144 ''' 145 146 def lookup(dummy, id): 147 return etree.XML(xml_data).xpath('id(%r)' % id)
148 functions = {(None, 'lookup') : lookup} 149 150 root = etree.XML('<dummy/>') 151 values = root.xpath("lookup('k1')/value/text()", 152 extensions=functions) 153 self.assertEqual(['v1'], values) 154 self.assertEqual('value', values[0].getparent().tag)
155
156 - def test_xpath_list_comment(self):
157 tree = self.parse('<a><!-- Foo --></a>') 158 self.assertEqual(['<!-- Foo -->'], 159 list(map(repr, tree.xpath('/a/node()'))))
160
161 - def test_rel_xpath_boolean(self):
162 root = etree.XML('<a><b><c/></b></a>') 163 el = root[0] 164 self.assertTrue(el.xpath('boolean(c)')) 165 self.assertTrue(not el.xpath('boolean(d)'))
166
167 - def test_rel_xpath_list_elements(self):
168 tree = self.parse('<a><c><b>Foo</b><b>Bar</b></c><c><b>Hey</b></c></a>') 169 root = tree.getroot() 170 c = root[0] 171 self.assertEqual([c[0], c[1]], 172 c.xpath('b')) 173 self.assertEqual([c[0], c[1], root[1][0]], 174 c.xpath('//b'))
175
176 - def test_xpath_ns(self):
177 tree = self.parse('<a xmlns="uri:a"><b></b></a>') 178 root = tree.getroot() 179 self.assertEqual( 180 [root[0]], 181 tree.xpath('//foo:b', namespaces={'foo': 'uri:a'})) 182 self.assertEqual( 183 [], 184 tree.xpath('//foo:b', namespaces={'foo': 'uri:c'})) 185 self.assertEqual( 186 [root[0]], 187 root.xpath('//baz:b', namespaces={'baz': 'uri:a'}))
188
189 - def test_xpath_ns_none(self):
190 tree = self.parse('<a xmlns="uri:a"><b></b></a>') 191 root = tree.getroot() 192 self.assertRaises( 193 TypeError, 194 root.xpath, '//b', namespaces={None: 'uri:a'})
195
196 - def test_xpath_ns_empty(self):
197 tree = self.parse('<a xmlns="uri:a"><b></b></a>') 198 root = tree.getroot() 199 self.assertRaises( 200 TypeError, 201 root.xpath, '//b', namespaces={'': 'uri:a'})
202
203 - def test_xpath_error(self):
204 tree = self.parse('<a/>') 205 self.assertRaises(etree.XPathEvalError, tree.xpath, '\\fad')
206
207 - def test_xpath_class_error(self):
208 self.assertRaises(SyntaxError, etree.XPath, '\\fad') 209 self.assertRaises(etree.XPathSyntaxError, etree.XPath, '\\fad')
210
211 - def test_xpath_prefix_error(self):
212 tree = self.parse('<a/>') 213 self.assertRaises(etree.XPathEvalError, tree.xpath, '/fa:d')
214
215 - def test_xpath_class_prefix_error(self):
216 tree = self.parse('<a/>') 217 xpath = etree.XPath("/fa:d") 218 self.assertRaises(etree.XPathEvalError, xpath, tree)
219
220 - def test_elementtree_getpath(self):
221 a = etree.Element("a") 222 b = etree.SubElement(a, "b") 223 c = etree.SubElement(a, "c") 224 d1 = etree.SubElement(c, "d") 225 d2 = etree.SubElement(c, "d") 226 227 tree = etree.ElementTree(a) 228 self.assertEqual('/a/c/d', 229 tree.getpath(d2)[:6]) 230 self.assertEqual([d2], 231 tree.xpath(tree.getpath(d2)))
232
233 - def test_elementtree_getpath_partial(self):
234 a = etree.Element("a") 235 b = etree.SubElement(a, "b") 236 c = etree.SubElement(a, "c") 237 d1 = etree.SubElement(c, "d") 238 d2 = etree.SubElement(c, "d") 239 240 tree = etree.ElementTree(c) 241 self.assertEqual('/c/d', 242 tree.getpath(d2)[:4]) 243 self.assertEqual([d2], 244 tree.xpath(tree.getpath(d2)))
245
246 - def test_xpath_evaluator(self):
247 tree = self.parse('<a><b><c></c></b></a>') 248 e = etree.XPathEvaluator(tree) 249 root = tree.getroot() 250 self.assertEqual( 251 [root], 252 e('//a'))
253
254 - def test_xpath_evaluator_tree(self):
255 tree = self.parse('<a><b><c></c></b></a>') 256 child_tree = etree.ElementTree(tree.getroot()[0]) 257 e = etree.XPathEvaluator(child_tree) 258 self.assertEqual( 259 [], 260 e('a')) 261 root = child_tree.getroot() 262 self.assertEqual( 263 [root[0]], 264 e('c'))
265
266 - def test_xpath_evaluator_tree_absolute(self):
267 tree = self.parse('<a><b><c></c></b></a>') 268 child_tree = etree.ElementTree(tree.getroot()[0]) 269 e = etree.XPathEvaluator(child_tree) 270 self.assertEqual( 271 [], 272 e('/a')) 273 root = child_tree.getroot() 274 self.assertEqual( 275 [root], 276 e('/b')) 277 self.assertEqual( 278 [], 279 e('/c'))
280
281 - def test_xpath_evaluator_element(self):
282 tree = self.parse('<a><b><c></c></b></a>') 283 root = tree.getroot() 284 e = etree.XPathEvaluator(root[0]) 285 self.assertEqual( 286 [root[0][0]], 287 e('c'))
288
289 - def test_xpath_extensions(self):
290 def foo(evaluator, a): 291 return 'hello %s' % a
292 extension = {(None, 'foo'): foo} 293 tree = self.parse('<a><b></b></a>') 294 e = etree.XPathEvaluator(tree, extensions=[extension]) 295 self.assertEqual( 296 "hello you", e("foo('you')")) 297
298 - def test_xpath_extensions_wrong_args(self):
299 def foo(evaluator, a, b): 300 return "hello %s and %s" % (a, b)
301 extension = {(None, 'foo'): foo} 302 tree = self.parse('<a><b></b></a>') 303 e = etree.XPathEvaluator(tree, extensions=[extension]) 304 self.assertRaises(TypeError, e, "foo('you')") 305
306 - def test_xpath_extensions_error(self):
307 def foo(evaluator, a): 308 return 1/0
309 extension = {(None, 'foo'): foo} 310 tree = self.parse('<a/>') 311 e = etree.XPathEvaluator(tree, extensions=[extension]) 312 self.assertRaises(ZeroDivisionError, e, "foo('test')") 313
314 - def test_xpath_extensions_nodes(self):
315 def f(evaluator, arg): 316 r = etree.Element('results') 317 b = etree.SubElement(r, 'result') 318 b.text = 'Hoi' 319 b = etree.SubElement(r, 'result') 320 b.text = 'Dag' 321 return r
322 323 x = self.parse('<a/>') 324 e = etree.XPathEvaluator(x, extensions=[{(None, 'foo'): f}]) 325 r = e("foo('World')/result") 326 self.assertEqual(2, len(r)) 327 self.assertEqual('Hoi', r[0].text) 328 self.assertEqual('Dag', r[1].text) 329
330 - def test_xpath_extensions_nodes_append(self):
331 def f(evaluator, nodes): 332 r = etree.SubElement(nodes[0], 'results') 333 b = etree.SubElement(r, 'result') 334 b.text = 'Hoi' 335 b = etree.SubElement(r, 'result') 336 b.text = 'Dag' 337 return r
338 339 x = self.parse('<a/>') 340 e = etree.XPathEvaluator(x, extensions=[{(None, 'foo'): f}]) 341 r = e("foo(/*)/result") 342 self.assertEqual(2, len(r)) 343 self.assertEqual('Hoi', r[0].text) 344 self.assertEqual('Dag', r[1].text) 345
346 - def test_xpath_extensions_nodes_append2(self):
347 def f(evaluator, nodes): 348 r = etree.Element('results') 349 b = etree.SubElement(r, 'result') 350 b.text = 'Hoi' 351 b = etree.SubElement(r, 'result') 352 b.text = 'Dag' 353 r.append(nodes[0]) 354 return r
355 356 x = self.parse('<result>Honk</result>') 357 e = etree.XPathEvaluator(x, extensions=[{(None, 'foo'): f}]) 358 r = e("foo(/*)/result") 359 self.assertEqual(3, len(r)) 360 self.assertEqual('Hoi', r[0].text) 361 self.assertEqual('Dag', r[1].text) 362 self.assertEqual('Honk', r[2].text) 363
364 - def test_xpath_context_node(self):
365 tree = self.parse('<root><a/><b><c/></b></root>') 366 367 check_call = [] 368 def check_context(ctxt, nodes): 369 self.assertEqual(len(nodes), 1) 370 check_call.append(nodes[0].tag) 371 self.assertEqual(ctxt.context_node, nodes[0]) 372 return True
373 374 find = etree.XPath("//*[p:foo(.)]", 375 namespaces={'p' : 'ns'}, 376 extensions=[{('ns', 'foo') : check_context}]) 377 find(tree) 378 379 check_call.sort() 380 self.assertEqual(check_call, ["a", "b", "c", "root"]) 381
382 - def test_xpath_eval_context_propagation(self):
383 tree = self.parse('<root><a/><b><c/></b></root>') 384 385 check_call = {} 386 def check_context(ctxt, nodes): 387 self.assertEqual(len(nodes), 1) 388 tag = nodes[0].tag 389 # empty during the "b" call, a "b" during the "c" call 390 check_call[tag] = ctxt.eval_context.get("b") 391 ctxt.eval_context[tag] = tag 392 return True
393 394 find = etree.XPath("//b[p:foo(.)]/c[p:foo(.)]", 395 namespaces={'p' : 'ns'}, 396 extensions=[{('ns', 'foo') : check_context}]) 397 result = find(tree) 398 399 self.assertEqual(result, [tree.getroot()[1][0]]) 400 self.assertEqual(check_call, {'b':None, 'c':'b'}) 401
402 - def test_xpath_eval_context_clear(self):
403 tree = self.parse('<root><a/><b><c/></b></root>') 404 405 check_call = {} 406 def check_context(ctxt): 407 check_call["done"] = True 408 # context must be empty for each new evaluation 409 self.assertEqual(len(ctxt.eval_context), 0) 410 ctxt.eval_context["test"] = True 411 return True
412 413 find = etree.XPath("//b[p:foo()]", 414 namespaces={'p' : 'ns'}, 415 extensions=[{('ns', 'foo') : check_context}]) 416 result = find(tree) 417 418 self.assertEqual(result, [tree.getroot()[1]]) 419 self.assertEqual(check_call["done"], True) 420 421 check_call.clear() 422 find = etree.XPath("//b[p:foo()]", 423 namespaces={'p' : 'ns'}, 424 extensions=[{('ns', 'foo') : check_context}]) 425 result = find(tree) 426 427 self.assertEqual(result, [tree.getroot()[1]]) 428 self.assertEqual(check_call["done"], True) 429
430 - def test_xpath_variables(self):
431 x = self.parse('<a attr="true"/>') 432 e = etree.XPathEvaluator(x) 433 434 expr = "/a[@attr=$aval]" 435 r = e(expr, aval=1) 436 self.assertEqual(0, len(r)) 437 438 r = e(expr, aval="true") 439 self.assertEqual(1, len(r)) 440 self.assertEqual("true", r[0].get('attr')) 441 442 r = e(expr, aval=True) 443 self.assertEqual(1, len(r)) 444 self.assertEqual("true", r[0].get('attr'))
445
446 - def test_xpath_variables_nodeset(self):
447 x = self.parse('<a attr="true"/>') 448 e = etree.XPathEvaluator(x) 449 450 element = etree.Element("test-el") 451 etree.SubElement(element, "test-sub") 452 expr = "$value" 453 r = e(expr, value=element) 454 self.assertEqual(1, len(r)) 455 self.assertEqual(element.tag, r[0].tag) 456 self.assertEqual(element[0].tag, r[0][0].tag)
457
458 - def test_xpath_extensions_mix(self):
459 x = self.parse('<a attr="true"><test/></a>') 460 461 class LocalException(Exception): 462 pass
463 464 def foo(evaluator, a, varval): 465 etree.Element("DUMMY") 466 if varval == 0: 467 raise LocalException 468 elif varval == 1: 469 return () 470 elif varval == 2: 471 return None 472 elif varval == 3: 473 return a[0][0] 474 a = a[0] 475 if a.get("attr") == str(varval): 476 return a 477 else: 478 return etree.Element("NODE") 479 480 extension = {(None, 'foo'): foo} 481 e = etree.XPathEvaluator(x, extensions=[extension]) 482 del x 483 484 self.assertRaises(LocalException, e, "foo(., 0)") 485 self.assertRaises(LocalException, e, "foo(., $value)", value=0) 486 487 r = e("foo(., $value)", value=1) 488 self.assertEqual(len(r), 0) 489 490 r = e("foo(., 1)") 491 self.assertEqual(len(r), 0) 492 493 r = e("foo(., $value)", value=2) 494 self.assertEqual(len(r), 0) 495 496 r = e("foo(., $value)", value=3) 497 self.assertEqual(len(r), 1) 498 self.assertEqual(r[0].tag, "test") 499 500 r = e("foo(., $value)", value="false") 501 self.assertEqual(len(r), 1) 502 self.assertEqual(r[0].tag, "NODE") 503 504 r = e("foo(., 'false')") 505 self.assertEqual(len(r), 1) 506 self.assertEqual(r[0].tag, "NODE") 507 508 r = e("foo(., 'true')") 509 self.assertEqual(len(r), 1) 510 self.assertEqual(r[0].tag, "a") 511 self.assertEqual(r[0][0].tag, "test") 512 513 r = e("foo(., $value)", value="true") 514 self.assertEqual(len(r), 1) 515 self.assertEqual(r[0].tag, "a") 516 517 self.assertRaises(LocalException, e, "foo(., 0)") 518 self.assertRaises(LocalException, e, "foo(., $value)", value=0) 519 520
521 -class ETreeXPathClassTestCase(HelperTestCase):
522 "Tests for the XPath class"
523 - def test_xpath_compile_doc(self):
524 x = self.parse('<a attr="true"/>') 525 526 expr = etree.XPath("/a[@attr != 'true']") 527 r = expr(x) 528 self.assertEqual(0, len(r)) 529 530 expr = etree.XPath("/a[@attr = 'true']") 531 r = expr(x) 532 self.assertEqual(1, len(r)) 533 534 expr = etree.XPath( expr.path ) 535 r = expr(x) 536 self.assertEqual(1, len(r))
537
539 x = self.parse('<a><b/><c/></a>') 540 root = x.getroot() 541 542 expr = etree.XPath("./b") 543 r = expr(root) 544 self.assertEqual(1, len(r)) 545 self.assertEqual('b', r[0].tag) 546 547 expr = etree.XPath("./*") 548 r = expr(root) 549 self.assertEqual(2, len(r))
550
551 - def test_xpath_compile_vars(self):
552 x = self.parse('<a attr="true"/>') 553 554 expr = etree.XPath("/a[@attr=$aval]") 555 r = expr(x, aval=False) 556 self.assertEqual(0, len(r)) 557 558 r = expr(x, aval=True) 559 self.assertEqual(1, len(r))
560
561 - def test_xpath_compile_error(self):
562 self.assertRaises(SyntaxError, etree.XPath, '\\fad')
563
565 self.assertRaises(ValueError, etree.XPath('*'), etree.ElementTree())
566 567
568 -class ETreeXPathExsltTestCase(HelperTestCase):
569 "Tests for the EXSLT support in XPath (requires libxslt 1.1.25+)" 570 571 NSMAP = dict( 572 date = "http://exslt.org/dates-and-times", 573 math = "http://exslt.org/math", 574 set = "http://exslt.org/sets", 575 str = "http://exslt.org/strings", 576 ) 577
579 tree = self.parse('<a><b>2009-11-12</b><b>2008-12-11</b></a>') 580 581 match_dates = tree.xpath('//b[date:year(string()) = 2009]', 582 namespaces=self.NSMAP) 583 self.assertTrue(match_dates, str(match_dates)) 584 self.assertEqual(len(match_dates), 1, str(match_dates)) 585 self.assertEqual(match_dates[0].text, '2009-11-12')
586
588 tree = self.parse('<a><b>2009-11-12</b><b>2008-12-11</b></a>') 589 590 aligned_date = tree.xpath( 591 'str:align(string(//b[1]), "%s", "center")' % ('-'*20), 592 namespaces=self.NSMAP) 593 self.assertTrue(aligned_date, str(aligned_date)) 594 self.assertEqual(aligned_date, '-----2009-11-12-----')
595 596
597 -class ETreeETXPathClassTestCase(HelperTestCase):
598 "Tests for the ETXPath class"
599 - def test_xpath_compile_ns(self):
600 x = self.parse('<a><b xmlns="nsa"/><b xmlns="nsb"/></a>') 601 602 expr = etree.ETXPath("/a/{nsa}b") 603 r = expr(x) 604 self.assertEqual(1, len(r)) 605 self.assertEqual('{nsa}b', r[0].tag) 606 607 expr = etree.ETXPath("/a/{nsb}b") 608 r = expr(x) 609 self.assertEqual(1, len(r)) 610 self.assertEqual('{nsb}b', r[0].tag)
611 612 # disabled this test as non-ASCII characters in namespace URIs are 613 # not acceptable
615 x = self.parse(_bytes('<a><b xmlns="http://nsa/\\uf8d2"/><b xmlns="http://nsb/\\uf8d1"/></a>' 616 ).decode("unicode_escape")) 617 618 expr = etree.ETXPath(_bytes("/a/{http://nsa/\\uf8d2}b").decode("unicode_escape")) 619 r = expr(x) 620 self.assertEqual(1, len(r)) 621 self.assertEqual(_bytes('{http://nsa/\\uf8d2}b').decode("unicode_escape"), r[0].tag) 622 623 expr = etree.ETXPath(_bytes("/a/{http://nsb/\\uf8d1}b").decode("unicode_escape")) 624 r = expr(x) 625 self.assertEqual(1, len(r)) 626 self.assertEqual(_bytes('{http://nsb/\\uf8d1}b').decode("unicode_escape"), r[0].tag)
627 628 SAMPLE_XML = etree.parse(BytesIO(""" 629 <body> 630 <tag>text</tag> 631 <section> 632 <tag>subtext</tag> 633 </section> 634 <tag /> 635 <tag /> 636 </body> 637 """)) 638
639 -def tag(elem):
640 return elem.tag
641
642 -def tag_or_value(elem):
643 return getattr(elem, 'tag', elem)
644
645 -def stringTest(ctxt, s1):
646 return "Hello "+s1
647
648 -def stringListTest(ctxt, s1):
649 return ["Hello "] + list(s1) + ["!"]
650
651 -def floatTest(ctxt, f1):
652 return f1+4
653
654 -def booleanTest(ctxt, b1):
655 return not b1
656
657 -def setTest(ctxt, st1):
658 return st1[0]
659
660 -def setTest2(ctxt, st1):
661 return st1[0:2]
662
663 -def argsTest1(ctxt, s, f, b, st):
664 return ", ".join(map(str, (s, f, b, list(map(tag, st)))))
665
666 -def argsTest2(ctxt, st1, st2):
667 st1.extend(st2) 668 return st1
669
670 -def resultTypesTest(ctxt):
671 return [None,None]
672
673 -def resultTypesTest2(ctxt):
674 return resultTypesTest
675 676 uri = "http://www.example.com/" 677 678 extension = {(None, 'stringTest'): stringTest, 679 (None, 'stringListTest'): stringListTest, 680 (None, 'floatTest'): floatTest, 681 (None, 'booleanTest'): booleanTest, 682 (None, 'setTest'): setTest, 683 (None, 'setTest2'): setTest2, 684 (None, 'argsTest1'): argsTest1, 685 (None, 'argsTest2'): argsTest2, 686 (None, 'resultTypesTest'): resultTypesTest, 687 (None, 'resultTypesTest2'): resultTypesTest2,} 688
689 -def xpath():
690 """ 691 Test xpath extension functions. 692 693 >>> root = SAMPLE_XML 694 >>> e = etree.XPathEvaluator(root, extensions=[extension]) 695 >>> e("stringTest('you')") 696 'Hello you' 697 >>> e(_bytes("stringTest('\\\\xe9lan')").decode("unicode_escape")) 698 u'Hello \\xe9lan' 699 >>> e("stringTest('you','there')") #doctest: +ELLIPSIS 700 Traceback (most recent call last): 701 ... 702 TypeError: stringTest() takes... 2 ...arguments ... 703 >>> e("floatTest(2)") 704 6.0 705 >>> e("booleanTest(true())") 706 False 707 >>> list(map(tag, e("setTest(/body/tag)"))) 708 ['tag'] 709 >>> list(map(tag, e("setTest2(/body/*)"))) 710 ['tag', 'section'] 711 >>> list(map(tag_or_value, e("stringListTest(/body/tag)"))) 712 ['Hello ', 'tag', 'tag', 'tag', '!'] 713 >>> e("argsTest1('a',1.5,true(),/body/tag)") 714 "a, 1.5, True, ['tag', 'tag', 'tag']" 715 >>> list(map(tag, e("argsTest2(/body/tag, /body/section)"))) 716 ['tag', 'section', 'tag', 'tag'] 717 >>> e("resultTypesTest()") 718 Traceback (most recent call last): 719 ... 720 XPathResultError: This is not a supported node-set result: None 721 >>> try: 722 ... e("resultTypesTest2()") 723 ... except etree.XPathResultError: 724 ... print("Got error") 725 Got error 726 """
727 728 if sys.version_info[0] >= 3: 729 xpath.__doc__ = xpath.__doc__.replace(" u'", " '") 730 xpath.__doc__ = xpath.__doc__.replace(" XPathResultError", 731 " lxml.etree.XPathResultError") 732 xpath.__doc__ = xpath.__doc__.replace(" exactly 2 arguments", 733 " exactly 2 positional arguments") 734
735 -def test_suite():
736 suite = unittest.TestSuite() 737 suite.addTests([unittest.makeSuite(ETreeXPathTestCase)]) 738 suite.addTests([unittest.makeSuite(ETreeXPathClassTestCase)]) 739 if etree.LIBXSLT_COMPILED_VERSION >= (1,1,25): 740 suite.addTests([unittest.makeSuite(ETreeXPathExsltTestCase)]) 741 suite.addTests([unittest.makeSuite(ETreeETXPathClassTestCase)]) 742 suite.addTests([doctest.DocTestSuite()]) 743 suite.addTests( 744 [make_doctest('../../../doc/xpathxslt.txt')]) 745 return suite
746 747 if __name__ == '__main__': 748 print('to test use test.py %s' % __file__) 749