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