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

Source Code for Module lxml.tests.test_xslt

   1  # -*- coding: utf-8 -*- 
   2   
   3  """ 
   4  Test cases related to XSLT processing 
   5  """ 
   6   
   7  import unittest, copy, 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  is_python3 = sys.version_info[0] >= 3 
  14   
  15  try: 
  16      unicode 
  17  except NameError: # Python 3 
  18      unicode = str 
  19   
  20  try: 
  21      basestring 
  22  except NameError: # Python 3 
  23      basestring = str 
  24   
  25  from common_imports import etree, BytesIO, HelperTestCase, fileInTestDir 
  26  from common_imports import doctest, _bytes, _str, make_doctest, skipif 
  27   
28 -class ETreeXSLTTestCase(HelperTestCase):
29 """XSLT tests etree""" 30
31 - def test_xslt(self):
32 tree = self.parse('<a><b>B</b><c>C</c></a>') 33 style = self.parse('''\ 34 <xsl:stylesheet version="1.0" 35 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 36 <xsl:template match="*" /> 37 <xsl:template match="/"> 38 <foo><xsl:value-of select="/a/b/text()" /></foo> 39 </xsl:template> 40 </xsl:stylesheet>''') 41 42 st = etree.XSLT(style) 43 res = st(tree) 44 self.assertEqual('''\ 45 <?xml version="1.0"?> 46 <foo>B</foo> 47 ''', 48 str(res))
49
51 self.assertRaises(ValueError, etree.XSLT, etree.ElementTree())
52
53 - def test_xslt_input_none(self):
54 self.assertRaises(TypeError, etree.XSLT, None)
55 56 if False and etree.LIBXSLT_VERSION >= (1,1,15): 57 # earlier versions generate no error 58 if etree.LIBXSLT_VERSION > (1,1,17):
60 style = self.parse('''\ 61 <xsl:stylesheet version="1.0" 62 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 63 <xsl:stylesheet /> 64 </xsl:stylesheet>''') 65 66 self.assertRaises( 67 etree.XSLTParseError, etree.XSLT, style)
68
69 - def test_xslt_copy(self):
70 tree = self.parse('<a><b>B</b><c>C</c></a>') 71 style = self.parse('''\ 72 <xsl:stylesheet version="1.0" 73 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 74 <xsl:template match="*" /> 75 <xsl:template match="/"> 76 <foo><xsl:value-of select="/a/b/text()" /></foo> 77 </xsl:template> 78 </xsl:stylesheet>''') 79 80 transform = etree.XSLT(style) 81 res = transform(tree) 82 self.assertEqual('''\ 83 <?xml version="1.0"?> 84 <foo>B</foo> 85 ''', 86 str(res)) 87 88 transform_copy = copy.deepcopy(transform) 89 res = transform_copy(tree) 90 self.assertEqual('''\ 91 <?xml version="1.0"?> 92 <foo>B</foo> 93 ''', 94 str(res)) 95 96 transform = etree.XSLT(style) 97 res = transform(tree) 98 self.assertEqual('''\ 99 <?xml version="1.0"?> 100 <foo>B</foo> 101 ''', 102 str(res))
103
104 - def test_xslt_utf8(self):
105 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>' 106 ).decode("unicode_escape")) 107 style = self.parse('''\ 108 <xsl:stylesheet version="1.0" 109 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 110 <xsl:output encoding="UTF-8"/> 111 <xsl:template match="/"> 112 <foo><xsl:value-of select="/a/b/text()" /></foo> 113 </xsl:template> 114 </xsl:stylesheet>''') 115 116 st = etree.XSLT(style) 117 res = st(tree) 118 expected = _bytes('''\ 119 <?xml version="1.0" encoding="UTF-8"?> 120 <foo>\\uF8D2</foo> 121 ''').decode("unicode_escape") 122 if is_python3: 123 self.assertEqual(expected, 124 str(bytes(res), 'UTF-8')) 125 else: 126 self.assertEqual(expected, 127 unicode(str(res), 'UTF-8'))
128
129 - def test_xslt_encoding(self):
130 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>' 131 ).decode("unicode_escape")) 132 style = self.parse('''\ 133 <xsl:stylesheet version="1.0" 134 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 135 <xsl:output encoding="UTF-16"/> 136 <xsl:template match="/"> 137 <foo><xsl:value-of select="/a/b/text()" /></foo> 138 </xsl:template> 139 </xsl:stylesheet>''') 140 141 st = etree.XSLT(style) 142 res = st(tree) 143 expected = _bytes('''\ 144 <?xml version="1.0" encoding="UTF-16"?> 145 <foo>\\uF8D2</foo> 146 ''').decode("unicode_escape") 147 if is_python3: 148 self.assertEqual(expected, 149 str(bytes(res), 'UTF-16')) 150 else: 151 self.assertEqual(expected, 152 unicode(str(res), 'UTF-16'))
153
155 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>' 156 ).decode("unicode_escape")) 157 style = self.parse('''\ 158 <xsl:stylesheet version="1.0" 159 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 160 <xsl:output encoding="UTF-8"/> 161 <xsl:template match="/"> 162 <foo><xsl:value-of select="/a/b/text()" /></foo> 163 </xsl:template> 164 </xsl:stylesheet>''') 165 166 st = etree.XSLT(style) 167 res = st(tree) 168 expected = _bytes("""\ 169 <?xml version='1.0' encoding='UTF-16'?>\ 170 <foo>\\uF8D2</foo>""").decode("unicode_escape") 171 172 f = BytesIO() 173 res.write(f, encoding='UTF-16') 174 if is_python3: 175 result = str(f.getvalue(), 'UTF-16').replace('\n', '') 176 else: 177 result = unicode(str(f.getvalue()), 'UTF-16').replace('\n', '') 178 self.assertEqual(expected, result)
179
180 - def test_xslt_unicode(self):
181 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>' 182 ).decode("unicode_escape")) 183 style = self.parse('''\ 184 <xsl:stylesheet version="1.0" 185 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 186 <xsl:output encoding="UTF-16"/> 187 <xsl:template match="/"> 188 <foo><xsl:value-of select="/a/b/text()" /></foo> 189 </xsl:template> 190 </xsl:stylesheet>''') 191 192 st = etree.XSLT(style) 193 res = st(tree) 194 expected = _bytes('''\ 195 <?xml version="1.0"?> 196 <foo>\\uF8D2</foo> 197 ''').decode("unicode_escape") 198 self.assertEqual(expected, 199 unicode(res))
200
202 tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>' 203 ).decode("unicode_escape")) 204 style = self.parse('''\ 205 <xsl:stylesheet version="1.0" 206 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 207 <xsl:output encoding="UTF-16" standalone="no"/> 208 <xsl:template match="/"> 209 <foo><xsl:value-of select="/a/b/text()" /></foo> 210 </xsl:template> 211 </xsl:stylesheet>''') 212 213 st = etree.XSLT(style) 214 res = st(tree) 215 expected = _bytes('''\ 216 <?xml version="1.0" standalone="no"?> 217 <foo>\\uF8D2</foo> 218 ''').decode("unicode_escape") 219 self.assertEqual(expected, 220 unicode(res))
221
222 - def test_xslt_input(self):
223 style = self.parse('''\ 224 <xsl:stylesheet version="1.0" 225 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 226 <xsl:template match="*" /> 227 <xsl:template match="/"> 228 <foo><xsl:value-of select="/a/b/text()" /></foo> 229 </xsl:template> 230 </xsl:stylesheet>''') 231 232 st = etree.XSLT(style) 233 st = etree.XSLT(style.getroot())
234
236 style = self.parse('''\ 237 <otherroot> 238 <xsl:stylesheet version="1.0" 239 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 240 <xsl:template match="*" /> 241 <xsl:template match="/"> 242 <foo><xsl:value-of select="/a/b/text()" /></foo> 243 </xsl:template> 244 </xsl:stylesheet> 245 </otherroot>''') 246 247 self.assertRaises(etree.XSLTParseError, etree.XSLT, style) 248 root_node = style.getroot() 249 self.assertRaises(etree.XSLTParseError, etree.XSLT, root_node) 250 st = etree.XSLT(root_node[0])
251
252 - def test_xslt_broken(self):
253 tree = self.parse('<a/>') 254 style = self.parse('''\ 255 <xsl:stylesheet version="1.0" 256 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 257 <xsl:foo /> 258 </xsl:stylesheet>''') 259 self.assertRaises(etree.XSLTParseError, 260 etree.XSLT, style)
261
262 - def test_xslt_parameters(self):
263 tree = self.parse('<a><b>B</b><c>C</c></a>') 264 style = self.parse('''\ 265 <xsl:stylesheet version="1.0" 266 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 267 <xsl:template match="/"> 268 <foo><xsl:value-of select="$bar" /></foo> 269 </xsl:template> 270 </xsl:stylesheet>''') 271 272 st = etree.XSLT(style) 273 res = st(tree, bar="'Bar'") 274 self.assertEqual('''\ 275 <?xml version="1.0"?> 276 <foo>Bar</foo> 277 ''', 278 str(res))
279
281 tree = self.parse('<a><b>B</b><c>C</c></a>') 282 style = self.parse('''\ 283 <xsl:stylesheet version="1.0" 284 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 285 <xsl:template match="/"> 286 <foo><xsl:value-of select="$bar" /></foo> 287 </xsl:template> 288 </xsl:stylesheet>''') 289 290 st = etree.XSLT(style) 291 res = st(tree, bar=etree.XSLT.strparam('''it's me, "Bar"''')) 292 self.assertEqual('''\ 293 <?xml version="1.0"?> 294 <foo>it's me, "Bar"</foo> 295 ''', 296 str(res))
297
299 tree = self.parse('<a><b>B</b><c>C</c></a>') 300 style = self.parse('''\ 301 <xsl:stylesheet version="1.0" 302 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 303 <xsl:param name="bar"/> 304 <xsl:template match="/"> 305 <foo><xsl:value-of select="$bar" /></foo> 306 </xsl:template> 307 </xsl:stylesheet>''') 308 309 st = etree.XSLT(style) 310 res = self.assertRaises(etree.XSLTApplyError, 311 st, tree, bar="<test/>") 312 res = self.assertRaises(etree.XSLTApplyError, 313 st, tree, bar="....")
314 315 if etree.LIBXSLT_VERSION < (1,1,18): 316 # later versions produce no error
318 # apply() without needed parameter will lead to XSLTApplyError 319 tree = self.parse('<a><b>B</b><c>C</c></a>') 320 style = self.parse('''\ 321 <xsl:stylesheet version="1.0" 322 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 323 <xsl:template match="/"> 324 <foo><xsl:value-of select="$bar" /></foo> 325 </xsl:template> 326 </xsl:stylesheet>''') 327 328 st = etree.XSLT(style) 329 self.assertRaises(etree.XSLTApplyError, 330 st.apply, tree)
331
333 tree = self.parse('<a><b>B</b><c>C</c></a>') 334 style = self.parse('''\ 335 <xsl:stylesheet version="1.0" 336 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 337 <xsl:template match="*" /> 338 <xsl:template match="/"> 339 <foo><xsl:value-of select="$bar" /></foo> 340 <foo><xsl:value-of select="$baz" /></foo> 341 </xsl:template> 342 </xsl:stylesheet>''') 343 344 st = etree.XSLT(style) 345 res = st(tree, bar="'Bar'", baz="'Baz'") 346 self.assertEqual('''\ 347 <?xml version="1.0"?> 348 <foo>Bar</foo><foo>Baz</foo> 349 ''', 350 str(res))
351
352 - def test_xslt_parameter_xpath(self):
353 tree = self.parse('<a><b>B</b><c>C</c></a>') 354 style = self.parse('''\ 355 <xsl:stylesheet version="1.0" 356 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 357 <xsl:template match="*" /> 358 <xsl:template match="/"> 359 <foo><xsl:value-of select="$bar" /></foo> 360 </xsl:template> 361 </xsl:stylesheet>''') 362 363 st = etree.XSLT(style) 364 res = st(tree, bar="/a/b/text()") 365 self.assertEqual('''\ 366 <?xml version="1.0"?> 367 <foo>B</foo> 368 ''', 369 str(res))
370
372 tree = self.parse('<a><b>B</b><c>C</c></a>') 373 style = self.parse('''\ 374 <xsl:stylesheet version="1.0" 375 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 376 <xsl:template match="*" /> 377 <xsl:template match="/"> 378 <foo><xsl:value-of select="$bar" /></foo> 379 </xsl:template> 380 </xsl:stylesheet>''') 381 382 st = etree.XSLT(style) 383 res = st(tree, bar=etree.XPath("/a/b/text()")) 384 self.assertEqual('''\ 385 <?xml version="1.0"?> 386 <foo>B</foo> 387 ''', 388 str(res))
389
391 tree = self.parse('<a><b>B</b><c>C</c></a>') 392 style = self.parse('''\ 393 <xsl:stylesheet version="1.0" 394 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 395 <xsl:param name="bar" select="'Default'" /> 396 <xsl:template match="*" /> 397 <xsl:template match="/"> 398 <foo><xsl:value-of select="$bar" /></foo> 399 </xsl:template> 400 </xsl:stylesheet>''') 401 402 st = etree.XSLT(style) 403 res = st(tree, bar="'Bar'") 404 self.assertEqual('''\ 405 <?xml version="1.0"?> 406 <foo>Bar</foo> 407 ''', 408 str(res)) 409 res = st(tree) 410 self.assertEqual('''\ 411 <?xml version="1.0"?> 412 <foo>Default</foo> 413 ''', 414 str(res))
415
416 - def test_xslt_html_output(self):
417 tree = self.parse('<a><b>B</b><c>C</c></a>') 418 style = self.parse('''\ 419 <xsl:stylesheet version="1.0" 420 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 421 <xsl:output method="html"/> 422 <xsl:strip-space elements="*"/> 423 <xsl:template match="/"> 424 <html><body><xsl:value-of select="/a/b/text()" /></body></html> 425 </xsl:template> 426 </xsl:stylesheet>''') 427 428 st = etree.XSLT(style) 429 res = st(tree) 430 self.assertEqual('<html><body>B</body></html>', 431 str(res).strip())
432
433 - def test_xslt_include(self):
434 tree = etree.parse(fileInTestDir('test1.xslt')) 435 st = etree.XSLT(tree)
436
438 f = open(fileInTestDir('test1.xslt'), 'rb') 439 tree = etree.parse(f) 440 f.close() 441 st = etree.XSLT(tree)
442
444 xml = '<a/>' 445 xslt = '''\ 446 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 447 <xsl:template match="/"> 448 <response>Some text</response> 449 </xsl:template> 450 </xsl:stylesheet> 451 ''' 452 source = self.parse(xml) 453 styledoc = self.parse(xslt) 454 style = etree.XSLT(styledoc) 455 result = style(source) 456 457 etree.tostring(result.getroot()) 458 459 source = self.parse(xml) 460 styledoc = self.parse(xslt) 461 style = etree.XSLT(styledoc) 462 result = style(source) 463 464 etree.tostring(result.getroot())
465
466 - def test_xslt_repeat_transform(self):
467 xml = '<a/>' 468 xslt = '''\ 469 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 470 <xsl:template match="/"> 471 <response>Some text</response> 472 </xsl:template> 473 </xsl:stylesheet> 474 ''' 475 source = self.parse(xml) 476 styledoc = self.parse(xslt) 477 transform = etree.XSLT(styledoc) 478 result = transform(source) 479 result = transform(source) 480 etree.tostring(result.getroot()) 481 result = transform(source) 482 etree.tostring(result.getroot()) 483 str(result) 484 485 result1 = transform(source) 486 result2 = transform(source) 487 self.assertEqual(str(result1), str(result2)) 488 result = transform(source) 489 str(result)
490
491 - def test_xslt_empty(self):
492 # could segfault if result contains "empty document" 493 xml = '<blah/>' 494 xslt = ''' 495 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 496 <xsl:template match="/" /> 497 </xsl:stylesheet> 498 ''' 499 500 source = self.parse(xml) 501 styledoc = self.parse(xslt) 502 style = etree.XSLT(styledoc) 503 result = style(source) 504 self.assertEqual('', str(result))
505
506 - def test_xslt_message(self):
507 xml = '<blah/>' 508 xslt = ''' 509 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 510 <xsl:template match="/"> 511 <xsl:message>TEST TEST TEST</xsl:message> 512 </xsl:template> 513 </xsl:stylesheet> 514 ''' 515 516 source = self.parse(xml) 517 styledoc = self.parse(xslt) 518 style = etree.XSLT(styledoc) 519 result = style(source) 520 self.assertEqual('', str(result)) 521 self.assertTrue("TEST TEST TEST" in [entry.message 522 for entry in style.error_log])
523
525 xml = '<blah/>' 526 xslt = ''' 527 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 528 <xsl:template match="/"> 529 <xsl:message terminate="yes">TEST TEST TEST</xsl:message> 530 </xsl:template> 531 </xsl:stylesheet> 532 ''' 533 534 source = self.parse(xml) 535 styledoc = self.parse(xslt) 536 style = etree.XSLT(styledoc) 537 538 self.assertRaises(etree.XSLTApplyError, style, source) 539 self.assertTrue("TEST TEST TEST" in [entry.message 540 for entry in style.error_log])
541
542 - def test_xslt_shortcut(self):
543 tree = self.parse('<a><b>B</b><c>C</c></a>') 544 style = self.parse('''\ 545 <xsl:stylesheet version="1.0" 546 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 547 <xsl:template match="*" /> 548 <xsl:template match="/"> 549 <doc> 550 <foo><xsl:value-of select="$bar" /></foo> 551 <foo><xsl:value-of select="$baz" /></foo> 552 </doc> 553 </xsl:template> 554 </xsl:stylesheet>''') 555 556 result = tree.xslt(style, bar="'Bar'", baz="'Baz'") 557 self.assertEqual( 558 _bytes('<doc><foo>Bar</foo><foo>Baz</foo></doc>'), 559 etree.tostring(result.getroot()))
560
561 - def test_multiple_elementrees(self):
562 tree = self.parse('<a><b>B</b><c>C</c></a>') 563 style = self.parse('''\ 564 <xsl:stylesheet version="1.0" 565 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 566 <xsl:template match="a"><A><xsl:apply-templates/></A></xsl:template> 567 <xsl:template match="b"><B><xsl:apply-templates/></B></xsl:template> 568 <xsl:template match="c"><C><xsl:apply-templates/></C></xsl:template> 569 </xsl:stylesheet>''') 570 571 self.assertEqual(self._rootstring(tree), 572 _bytes('<a><b>B</b><c>C</c></a>')) 573 result = tree.xslt(style) 574 self.assertEqual(self._rootstring(tree), 575 _bytes('<a><b>B</b><c>C</c></a>')) 576 self.assertEqual(self._rootstring(result), 577 _bytes('<A><B>B</B><C>C</C></A>')) 578 579 b_tree = etree.ElementTree(tree.getroot()[0]) 580 self.assertEqual(self._rootstring(b_tree), 581 _bytes('<b>B</b>')) 582 result = b_tree.xslt(style) 583 self.assertEqual(self._rootstring(tree), 584 _bytes('<a><b>B</b><c>C</c></a>')) 585 self.assertEqual(self._rootstring(result), 586 _bytes('<B>B</B>')) 587 588 c_tree = etree.ElementTree(tree.getroot()[1]) 589 self.assertEqual(self._rootstring(c_tree), 590 _bytes('<c>C</c>')) 591 result = c_tree.xslt(style) 592 self.assertEqual(self._rootstring(tree), 593 _bytes('<a><b>B</b><c>C</c></a>')) 594 self.assertEqual(self._rootstring(result), 595 _bytes('<C>C</C>'))
596
597 - def test_xslt_document_XML(self):
598 # make sure document('') works from parsed strings 599 xslt = etree.XSLT(etree.XML("""\ 600 <xsl:stylesheet version="1.0" 601 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 602 <xsl:template match="/"> 603 <test>TEXT<xsl:copy-of select="document('')//test"/></test> 604 </xsl:template> 605 </xsl:stylesheet> 606 """)) 607 result = xslt(etree.XML('<a/>')) 608 root = result.getroot() 609 self.assertEqual(root.tag, 610 'test') 611 self.assertEqual(root[0].tag, 612 'test') 613 self.assertEqual(root[0].text, 614 'TEXT') 615 self.assertEqual(root[0][0].tag, 616 '{http://www.w3.org/1999/XSL/Transform}copy-of')
617
618 - def test_xslt_document_parse(self):
619 # make sure document('') works from loaded files 620 xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt"))) 621 result = xslt(etree.XML('<a/>')) 622 root = result.getroot() 623 self.assertEqual(root.tag, 624 'test') 625 self.assertEqual(root[0].tag, 626 '{http://www.w3.org/1999/XSL/Transform}stylesheet')
627
629 # make sure document('') works from loaded files 630 xslt = etree.XSLT(etree.ElementTree(file=fileInTestDir("test-document.xslt"))) 631 result = xslt(etree.XML('<a/>')) 632 root = result.getroot() 633 self.assertEqual(root.tag, 634 'test') 635 self.assertEqual(root[0].tag, 636 '{http://www.w3.org/1999/XSL/Transform}stylesheet')
637
638 - def test_xslt_document_error(self):
639 xslt = etree.XSLT(etree.XML("""\ 640 <xsl:stylesheet version="1.0" 641 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 642 <xsl:template match="/"> 643 <test>TEXT<xsl:copy-of select="document('uri:__junkfood__is__evil__')//test"/></test> 644 </xsl:template> 645 </xsl:stylesheet> 646 """)) 647 self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
648
650 # make sure document('') works when custom resolvers are in use 651 assertEqual = self.assertEqual 652 called = {'count' : 0} 653 class TestResolver(etree.Resolver): 654 def resolve(self, url, id, context): 655 assertEqual(url, 'file://ANYTHING') 656 called['count'] += 1 657 return self.resolve_string('<CALLED/>', context)
658 659 parser = etree.XMLParser() 660 parser.resolvers.add(TestResolver()) 661 662 xslt = etree.XSLT(etree.XML(_bytes("""\ 663 <xsl:stylesheet version="1.0" 664 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 665 xmlns:l="local"> 666 <xsl:template match="/"> 667 <test> 668 <xsl:for-each select="document('')//l:data/l:entry"> 669 <xsl:copy-of select="document('file://ANYTHING')"/> 670 <xsl:copy> 671 <xsl:attribute name="value"> 672 <xsl:value-of select="."/> 673 </xsl:attribute> 674 </xsl:copy> 675 </xsl:for-each> 676 </test> 677 </xsl:template> 678 <l:data> 679 <l:entry>A</l:entry> 680 <l:entry>B</l:entry> 681 </l:data> 682 </xsl:stylesheet> 683 """), parser)) 684 685 self.assertEqual(called['count'], 0) 686 result = xslt(etree.XML('<a/>')) 687 self.assertEqual(called['count'], 1) 688 689 root = result.getroot() 690 self.assertEqual(root.tag, 691 'test') 692 self.assertEqual(len(root), 4) 693 694 self.assertEqual(root[0].tag, 695 'CALLED') 696 self.assertEqual(root[1].tag, 697 '{local}entry') 698 self.assertEqual(root[1].text, 699 None) 700 self.assertEqual(root[1].get("value"), 701 'A') 702 self.assertEqual(root[2].tag, 703 'CALLED') 704 self.assertEqual(root[3].tag, 705 '{local}entry') 706 self.assertEqual(root[3].text, 707 None) 708 self.assertEqual(root[3].get("value"), 709 'B') 710
711 - def test_xslt_resolver_url_building(self):
712 assertEqual = self.assertEqual 713 called = {'count' : 0} 714 expected_url = None 715 class TestResolver(etree.Resolver): 716 def resolve(self, url, id, context): 717 assertEqual(url, expected_url) 718 called['count'] += 1 719 return self.resolve_string('<CALLED/>', context)
720 721 stylesheet_xml = _bytes("""\ 722 <xsl:stylesheet version="1.0" 723 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 724 xmlns:l="local"> 725 <xsl:template match="/"> 726 <xsl:copy-of select="document('test.xml')"/> 727 </xsl:template> 728 </xsl:stylesheet> 729 """) 730 731 parser = etree.XMLParser() 732 parser.resolvers.add(TestResolver()) 733 734 # test without base_url => relative path only 735 expected_url = 'test.xml' 736 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser)) 737 738 self.assertEqual(called['count'], 0) 739 result = xslt(etree.XML('<a/>')) 740 self.assertEqual(called['count'], 1) 741 742 # now the same thing with a stylesheet base URL on the filesystem 743 called['count'] = 0 744 expected_url = os.path.join('MY', 'BASE', 'test.xml') 745 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser, 746 base_url=os.path.join('MY', 'BASE', 'FILE'))) 747 748 self.assertEqual(called['count'], 0) 749 result = xslt(etree.XML('<a/>')) 750 self.assertEqual(called['count'], 1) 751 752 # now the same thing with a stylesheet base URL 753 called['count'] = 0 754 expected_url = 'http://server.com/BASE/DIR/test.xml' 755 xslt = etree.XSLT(etree.XML(stylesheet_xml, parser, 756 base_url='http://server.com/BASE/DIR/FILE')) 757 758 self.assertEqual(called['count'], 0) 759 result = xslt(etree.XML('<a/>')) 760 self.assertEqual(called['count'], 1) 761
762 - def test_xslt_document_parse_allow(self):
763 access_control = etree.XSLTAccessControl(read_file=True) 764 xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")), 765 access_control=access_control) 766 result = xslt(etree.XML('<a/>')) 767 root = result.getroot() 768 self.assertEqual(root.tag, 769 'test') 770 self.assertEqual(root[0].tag, 771 '{http://www.w3.org/1999/XSL/Transform}stylesheet')
772
773 - def test_xslt_document_parse_deny(self):
774 access_control = etree.XSLTAccessControl(read_file=False) 775 xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")), 776 access_control=access_control) 777 self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
778
779 - def test_xslt_document_parse_deny_all(self):
780 access_control = etree.XSLTAccessControl.DENY_ALL 781 xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")), 782 access_control=access_control) 783 self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
784
785 - def test_xslt_access_control_repr(self):
786 access_control = etree.XSLTAccessControl.DENY_ALL 787 self.assertTrue(repr(access_control).startswith(type(access_control).__name__)) 788 self.assertEqual(repr(access_control), repr(access_control)) 789 self.assertNotEqual(repr(etree.XSLTAccessControl.DENY_ALL), 790 repr(etree.XSLTAccessControl.DENY_WRITE)) 791 self.assertNotEqual(repr(etree.XSLTAccessControl.DENY_ALL), 792 repr(etree.XSLTAccessControl()))
793
794 - def test_xslt_move_result(self):
795 root = etree.XML(_bytes('''\ 796 <transform> 797 <widget displayType="fieldset"/> 798 </transform>''')) 799 800 xslt = etree.XSLT(etree.XML(_bytes('''\ 801 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 802 <xsl:output method="html" indent="no"/> 803 <xsl:template match="/"> 804 <html> 805 <xsl:apply-templates/> 806 </html> 807 </xsl:template> 808 809 <xsl:template match="widget"> 810 <xsl:element name="{@displayType}"/> 811 </xsl:template> 812 813 </xsl:stylesheet>'''))) 814 815 result = xslt(root[0]) 816 root[:] = result.getroot()[:] 817 del root # segfaulted before
818
819 - def test_xslt_pi(self):
820 tree = self.parse('''\ 821 <?xml version="1.0"?> 822 <?xml-stylesheet type="text/xsl" href="%s"?> 823 <a> 824 <b>B</b> 825 <c>C</c> 826 </a>''' % fileInTestDir("test1.xslt")) 827 828 style_root = tree.getroot().getprevious().parseXSL().getroot() 829 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 830 style_root.tag)
831
832 - def test_xslt_pi_embedded_xmlid(self):
833 # test xml:id dictionary lookup mechanism 834 tree = self.parse('''\ 835 <?xml version="1.0"?> 836 <?xml-stylesheet type="text/xsl" href="#style"?> 837 <a> 838 <b>B</b> 839 <c>C</c> 840 <xsl:stylesheet version="1.0" xml:id="style" 841 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 842 <xsl:template match="*" /> 843 <xsl:template match="/"> 844 <foo><xsl:value-of select="/a/b/text()" /></foo> 845 </xsl:template> 846 </xsl:stylesheet> 847 </a>''') 848 849 style_root = tree.getroot().getprevious().parseXSL().getroot() 850 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 851 style_root.tag) 852 853 st = etree.XSLT(style_root) 854 res = st(tree) 855 self.assertEqual('''\ 856 <?xml version="1.0"?> 857 <foo>B</foo> 858 ''', 859 str(res))
860
861 - def test_xslt_pi_embedded_id(self):
862 # test XPath lookup mechanism 863 tree = self.parse('''\ 864 <?xml version="1.0"?> 865 <?xml-stylesheet type="text/xsl" href="#style"?> 866 <a> 867 <b>B</b> 868 <c>C</c> 869 </a>''') 870 871 style = self.parse('''\ 872 <xsl:stylesheet version="1.0" xml:id="style" 873 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 874 <xsl:template match="*" /> 875 <xsl:template match="/"> 876 <foo><xsl:value-of select="/a/b/text()" /></foo> 877 </xsl:template> 878 </xsl:stylesheet> 879 ''') 880 881 tree.getroot().append(style.getroot()) 882 883 style_root = tree.getroot().getprevious().parseXSL().getroot() 884 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 885 style_root.tag) 886 887 st = etree.XSLT(style_root) 888 res = st(tree) 889 self.assertEqual('''\ 890 <?xml version="1.0"?> 891 <foo>B</foo> 892 ''', 893 str(res))
894
895 - def test_xslt_pi_get(self):
896 tree = self.parse('''\ 897 <?xml version="1.0"?> 898 <?xml-stylesheet type="text/xsl" href="TEST"?> 899 <a> 900 <b>B</b> 901 <c>C</c> 902 </a>''') 903 904 pi = tree.getroot().getprevious() 905 self.assertEqual("TEST", pi.get("href"))
906
907 - def test_xslt_pi_get_all(self):
908 tree = self.parse('''\ 909 <?xml version="1.0"?> 910 <?xml-stylesheet type="text/xsl" href="TEST"?> 911 <a> 912 <b>B</b> 913 <c>C</c> 914 </a>''') 915 916 pi = tree.getroot().getprevious() 917 self.assertEqual("TEST", pi.get("href")) 918 self.assertEqual("text/xsl", pi.get("type")) 919 self.assertEqual(None, pi.get("motz"))
920
921 - def test_xslt_pi_get_all_reversed(self):
922 tree = self.parse('''\ 923 <?xml version="1.0"?> 924 <?xml-stylesheet href="TEST" type="text/xsl"?> 925 <a> 926 <b>B</b> 927 <c>C</c> 928 </a>''') 929 930 pi = tree.getroot().getprevious() 931 self.assertEqual("TEST", pi.get("href")) 932 self.assertEqual("text/xsl", pi.get("type")) 933 self.assertEqual(None, pi.get("motz"))
934
935 - def test_xslt_pi_get_unknown(self):
936 tree = self.parse('''\ 937 <?xml version="1.0"?> 938 <?xml-stylesheet type="text/xsl" href="TEST"?> 939 <a> 940 <b>B</b> 941 <c>C</c> 942 </a>''') 943 944 pi = tree.getroot().getprevious() 945 self.assertEqual(None, pi.get("unknownattribute"))
946
947 - def test_xslt_pi_set_replace(self):
948 tree = self.parse('''\ 949 <?xml version="1.0"?> 950 <?xml-stylesheet type="text/xsl" href="TEST"?> 951 <a> 952 <b>B</b> 953 <c>C</c> 954 </a>''') 955 956 pi = tree.getroot().getprevious() 957 self.assertEqual("TEST", pi.get("href")) 958 959 pi.set("href", "TEST123") 960 self.assertEqual("TEST123", pi.get("href"))
961
962 - def test_xslt_pi_set_new(self):
963 tree = self.parse('''\ 964 <?xml version="1.0"?> 965 <?xml-stylesheet type="text/xsl"?> 966 <a> 967 <b>B</b> 968 <c>C</c> 969 </a>''') 970 971 pi = tree.getroot().getprevious() 972 self.assertEqual(None, pi.get("href")) 973 974 pi.set("href", "TEST") 975 self.assertEqual("TEST", pi.get("href"))
976
977 -class ETreeEXSLTTestCase(HelperTestCase):
978 """EXSLT tests""" 979
980 - def test_exslt_str(self):
981 tree = self.parse('<a><b>B</b><c>C</c></a>') 982 style = self.parse('''\ 983 <xsl:stylesheet version="1.0" 984 xmlns:str="http://exslt.org/strings" 985 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 986 exclude-result-prefixes="str xsl"> 987 <xsl:template match="text()"> 988 <xsl:value-of select="str:align(string(.), '***', 'center')" /> 989 </xsl:template> 990 <xsl:template match="*"> 991 <xsl:copy> 992 <xsl:apply-templates/> 993 </xsl:copy> 994 </xsl:template> 995 </xsl:stylesheet>''') 996 997 st = etree.XSLT(style) 998 res = st(tree) 999 self.assertEqual('''\ 1000 <?xml version="1.0"?> 1001 <a><b>*B*</b><c>*C*</c></a> 1002 ''', 1003 str(res))
1004 1005 if etree.LIBXSLT_VERSION >= (1,1,21):
1007 tree = self.parse('<a><b>B</b><c>C</c></a>') 1008 style = self.parse('''\ 1009 <xsl:stylesheet version = "1.0" 1010 xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 1011 xmlns:str="http://exslt.org/strings" 1012 extension-element-prefixes="str"> 1013 1014 <xsl:template match="/"> 1015 <h1 class="{str:replace('abc', 'b', 'x')}">test</h1> 1016 </xsl:template> 1017 1018 </xsl:stylesheet>''') 1019 1020 st = etree.XSLT(style) 1021 res = st(tree) 1022 self.assertEqual('''\ 1023 <?xml version="1.0"?> 1024 <h1 class="axc">test</h1> 1025 ''', 1026 str(res))
1027
1028 - def test_exslt_math(self):
1029 tree = self.parse('<a><b>B</b><c>C</c></a>') 1030 style = self.parse('''\ 1031 <xsl:stylesheet version="1.0" 1032 xmlns:math="http://exslt.org/math" 1033 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1034 exclude-result-prefixes="math xsl"> 1035 <xsl:template match="*"> 1036 <xsl:copy> 1037 <xsl:attribute name="pi"> 1038 <xsl:value-of select="math:constant('PI', count(*)+2)"/> 1039 </xsl:attribute> 1040 <xsl:apply-templates/> 1041 </xsl:copy> 1042 </xsl:template> 1043 </xsl:stylesheet>''') 1044 1045 st = etree.XSLT(style) 1046 res = st(tree) 1047 self.assertEqual('''\ 1048 <?xml version="1.0"?> 1049 <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a> 1050 ''', 1051 str(res))
1052
1053 - def test_exslt_regexp_test(self):
1054 xslt = etree.XSLT(etree.XML(_bytes("""\ 1055 <xsl:stylesheet version="1.0" 1056 xmlns:regexp="http://exslt.org/regular-expressions" 1057 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1058 <xsl:template match="*"> 1059 <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test> 1060 </xsl:template> 1061 </xsl:stylesheet> 1062 """))) 1063 result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>'))) 1064 root = result.getroot() 1065 self.assertEqual(root.tag, 1066 'test') 1067 self.assertEqual(len(root), 1) 1068 self.assertEqual(root[0].tag, 1069 'b') 1070 self.assertEqual(root[0].text, 1071 '987')
1072
1073 - def test_exslt_regexp_replace(self):
1074 xslt = etree.XSLT(etree.XML("""\ 1075 <xsl:stylesheet version="1.0" 1076 xmlns:regexp="http://exslt.org/regular-expressions" 1077 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1078 <xsl:template match="*"> 1079 <test> 1080 <xsl:copy-of select="regexp:replace(string(.), 'd.', '', 'XX')"/> 1081 <xsl:text>-</xsl:text> 1082 <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/> 1083 </test> 1084 </xsl:template> 1085 </xsl:stylesheet> 1086 """)) 1087 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>'))) 1088 root = result.getroot() 1089 self.assertEqual(root.tag, 1090 'test') 1091 self.assertEqual(len(root), 0) 1092 self.assertEqual(root.text, 'abXXdEeDed-abXXXXeXXd')
1093
1094 - def test_exslt_regexp_match(self):
1095 xslt = etree.XSLT(etree.XML("""\ 1096 <xsl:stylesheet version="1.0" 1097 xmlns:regexp="http://exslt.org/regular-expressions" 1098 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1099 <xsl:template match="*"> 1100 <test> 1101 <test1><xsl:copy-of select="regexp:match(string(.), 'd.')"/></test1> 1102 <test2><xsl:copy-of select="regexp:match(string(.), 'd.', 'g')"/></test2> 1103 <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i> 1104 </test> 1105 </xsl:template> 1106 </xsl:stylesheet> 1107 """)) 1108 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>'))) 1109 root = result.getroot() 1110 self.assertEqual(root.tag, 'test') 1111 self.assertEqual(len(root), 3) 1112 1113 self.assertEqual(len(root[0]), 1) 1114 self.assertEqual(root[0][0].tag, 'match') 1115 self.assertEqual(root[0][0].text, 'dC') 1116 1117 self.assertEqual(len(root[1]), 2) 1118 self.assertEqual(root[1][0].tag, 'match') 1119 self.assertEqual(root[1][0].text, 'dC') 1120 self.assertEqual(root[1][1].tag, 'match') 1121 self.assertEqual(root[1][1].text, 'dE') 1122 1123 self.assertEqual(len(root[2]), 3) 1124 self.assertEqual(root[2][0].tag, 'match') 1125 self.assertEqual(root[2][0].text, 'dC') 1126 self.assertEqual(root[2][1].tag, 'match') 1127 self.assertEqual(root[2][1].text, 'dE') 1128 self.assertEqual(root[2][2].tag, 'match') 1129 self.assertEqual(root[2][2].text, 'De')
1130
1132 xslt = etree.XSLT(etree.XML(_bytes("""\ 1133 <xsl:stylesheet version="1.0" 1134 xmlns:regexp="http://exslt.org/regular-expressions" 1135 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1136 <xsl:template match="/"> 1137 <test> 1138 <xsl:for-each select="regexp:match( 1139 '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )"> 1140 <test1><xsl:value-of select="."/></test1> 1141 </xsl:for-each> 1142 </test> 1143 </xsl:template> 1144 </xsl:stylesheet> 1145 """))) 1146 result = xslt(etree.XML(_bytes('<a/>'))) 1147 root = result.getroot() 1148 self.assertEqual(root.tag, 'test') 1149 self.assertEqual(len(root), 4) 1150 1151 self.assertEqual(root[0].text, "123abc567") 1152 self.assertEqual(root[1].text, "123") 1153 self.assertEqual(root[2].text, "abc") 1154 self.assertEqual(root[3].text, "567")
1155
1156 - def test_exslt_regexp_match1(self):
1157 # taken from http://www.exslt.org/regexp/functions/match/index.html 1158 xslt = etree.XSLT(etree.XML(_bytes("""\ 1159 <xsl:stylesheet version="1.0" 1160 xmlns:regexp="http://exslt.org/regular-expressions" 1161 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1162 <xsl:template match="/"> 1163 <test> 1164 <xsl:for-each select="regexp:match( 1165 'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml', 1166 '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')"> 1167 <test1><xsl:value-of select="."/></test1> 1168 </xsl:for-each> 1169 </test> 1170 </xsl:template> 1171 </xsl:stylesheet> 1172 """))) 1173 result = xslt(etree.XML(_bytes('<a/>'))) 1174 root = result.getroot() 1175 self.assertEqual(root.tag, 'test') 1176 self.assertEqual(len(root), 5) 1177 1178 self.assertEqual( 1179 root[0].text, 1180 "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml") 1181 self.assertEqual( 1182 root[1].text, 1183 "http") 1184 self.assertEqual( 1185 root[2].text, 1186 "www.bayes.co.uk") 1187 self.assertFalse(root[3].text) 1188 self.assertEqual( 1189 root[4].text, 1190 "/xml/index.xml?/xml/utils/rechecker.xml")
1191
1192 - def test_exslt_regexp_match2(self):
1193 # taken from http://www.exslt.org/regexp/functions/match/index.html 1194 xslt = etree.XSLT(self.parse("""\ 1195 <xsl:stylesheet version="1.0" 1196 xmlns:regexp="http://exslt.org/regular-expressions" 1197 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1198 <xsl:template match="/"> 1199 <test> 1200 <xsl:for-each select="regexp:match( 1201 'This is a test string', '(\w+)', 'g')"> 1202 <test1><xsl:value-of select="."/></test1> 1203 </xsl:for-each> 1204 </test> 1205 </xsl:template> 1206 </xsl:stylesheet> 1207 """)) 1208 result = xslt(etree.XML(_bytes('<a/>'))) 1209 root = result.getroot() 1210 self.assertEqual(root.tag, 'test') 1211 self.assertEqual(len(root), 5) 1212 1213 self.assertEqual(root[0].text, "This") 1214 self.assertEqual(root[1].text, "is") 1215 self.assertEqual(root[2].text, "a") 1216 self.assertEqual(root[3].text, "test") 1217 self.assertEqual(root[4].text, "string")
1218
1219 - def _test_exslt_regexp_match3(self):
1220 # taken from http://www.exslt.org/regexp/functions/match/index.html 1221 # THIS IS NOT SUPPORTED! 1222 xslt = etree.XSLT(etree.XML(_bytes("""\ 1223 <xsl:stylesheet version="1.0" 1224 xmlns:regexp="http://exslt.org/regular-expressions" 1225 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1226 <xsl:template match="/"> 1227 <test> 1228 <xsl:for-each select="regexp:match( 1229 'This is a test string', '([a-z])+ ', 'g')"> 1230 <test1><xsl:value-of select="."/></test1> 1231 </xsl:for-each> 1232 </test> 1233 </xsl:template> 1234 </xsl:stylesheet> 1235 """))) 1236 result = xslt(etree.XML(_bytes('<a/>'))) 1237 root = result.getroot() 1238 self.assertEqual(root.tag, 'test') 1239 self.assertEqual(len(root), 4) 1240 1241 self.assertEqual(root[0].text, "his") 1242 self.assertEqual(root[1].text, "is") 1243 self.assertEqual(root[2].text, "a") 1244 self.assertEqual(root[3].text, "test")
1245
1246 - def _test_exslt_regexp_match4(self):
1247 # taken from http://www.exslt.org/regexp/functions/match/index.html 1248 # THIS IS NOT SUPPORTED! 1249 xslt = etree.XSLT(etree.XML(_bytes("""\ 1250 <xsl:stylesheet version="1.0" 1251 xmlns:regexp="http://exslt.org/regular-expressions" 1252 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1253 <xsl:template match="/"> 1254 <test> 1255 <xsl:for-each select="regexp:match( 1256 'This is a test string', '([a-z])+ ', 'gi')"> 1257 <test1><xsl:value-of select="."/></test1> 1258 </xsl:for-each> 1259 </test> 1260 </xsl:template> 1261 </xsl:stylesheet> 1262 """))) 1263 result = xslt(etree.XML(_bytes('<a/>'))) 1264 root = result.getroot() 1265 self.assertEqual(root.tag, 'test') 1266 self.assertEqual(len(root), 4) 1267 1268 self.assertEqual(root[0].text, "This") 1269 self.assertEqual(root[1].text, "is") 1270 self.assertEqual(root[2].text, "a") 1271 self.assertEqual(root[3].text, "test")
1272 1273
1274 -class ETreeXSLTExtFuncTestCase(HelperTestCase):
1275 """Tests for XPath extension functions in XSLT.""" 1276
1277 - def test_extensions1(self):
1278 tree = self.parse('<a><b>B</b></a>') 1279 style = self.parse('''\ 1280 <xsl:stylesheet version="1.0" 1281 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1282 xmlns:myns="testns" 1283 exclude-result-prefixes="myns"> 1284 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template> 1285 </xsl:stylesheet>''') 1286 1287 def mytext(ctxt, values): 1288 return 'X' * len(values)
1289 1290 result = tree.xslt(style, {('testns', 'mytext') : mytext}) 1291 self.assertEqual(self._rootstring(result), 1292 _bytes('<A>X</A>'))
1293
1294 - def test_extensions2(self):
1295 tree = self.parse('<a><b>B</b></a>') 1296 style = self.parse('''\ 1297 <xsl:stylesheet version="1.0" 1298 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1299 xmlns:myns="testns" 1300 exclude-result-prefixes="myns"> 1301 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template> 1302 </xsl:stylesheet>''') 1303 1304 def mytext(ctxt, values): 1305 return 'X' * len(values)
1306 1307 namespace = etree.FunctionNamespace('testns') 1308 namespace['mytext'] = mytext 1309 1310 result = tree.xslt(style) 1311 self.assertEqual(self._rootstring(result), 1312 _bytes('<A>X</A>')) 1313
1314 - def test_variable_result_tree_fragment(self):
1315 tree = self.parse('<a><b>B</b><b/></a>') 1316 style = self.parse('''\ 1317 <xsl:stylesheet version="1.0" 1318 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1319 xmlns:myns="testns" 1320 exclude-result-prefixes="myns"> 1321 <xsl:template match="a"> 1322 <xsl:variable name="content"> 1323 <xsl:apply-templates/> 1324 </xsl:variable> 1325 <A><xsl:value-of select="myns:mytext($content)"/></A> 1326 </xsl:template> 1327 <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template> 1328 </xsl:stylesheet>''') 1329 1330 def mytext(ctxt, values): 1331 for value in values: 1332 self.assertTrue(hasattr(value, 'tag'), 1333 "%s is not an Element" % type(value)) 1334 self.assertEqual(value.tag, 'b') 1335 self.assertEqual(value.text, 'BBB') 1336 return 'X'.join([el.tag for el in values])
1337 1338 namespace = etree.FunctionNamespace('testns') 1339 namespace['mytext'] = mytext 1340 1341 result = tree.xslt(style) 1342 self.assertEqual(self._rootstring(result), 1343 _bytes('<A>bXb</A>')) 1344 1345
1346 -class ETreeXSLTExtElementTestCase(HelperTestCase):
1347 """Tests for extension elements in XSLT.""" 1348
1349 - def test_extension_element(self):
1350 tree = self.parse('<a><b>B</b></a>') 1351 style = self.parse('''\ 1352 <xsl:stylesheet version="1.0" 1353 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1354 xmlns:myns="testns" 1355 extension-element-prefixes="myns" 1356 exclude-result-prefixes="myns"> 1357 <xsl:template match="a"> 1358 <A><myns:myext>b</myns:myext></A> 1359 </xsl:template> 1360 </xsl:stylesheet>''') 1361 1362 class MyExt(etree.XSLTExtension): 1363 def execute(self, context, self_node, input_node, output_parent): 1364 child = etree.Element(self_node.text) 1365 child.text = 'X' 1366 output_parent.append(child)
1367 1368 extensions = { ('testns', 'myext') : MyExt() } 1369 1370 result = tree.xslt(style, extensions=extensions) 1371 self.assertEqual(self._rootstring(result), 1372 _bytes('<A><b>X</b></A>')) 1373
1374 - def test_extension_element_doc_context(self):
1375 tree = self.parse('<a><b>B</b></a>') 1376 style = self.parse('''\ 1377 <xsl:stylesheet version="1.0" 1378 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1379 xmlns:myns="testns" 1380 extension-element-prefixes="myns" 1381 exclude-result-prefixes="myns"> 1382 <xsl:template match="/"> 1383 <A><myns:myext>b</myns:myext></A> 1384 </xsl:template> 1385 </xsl:stylesheet>''') 1386 1387 tags = [] 1388 1389 class MyExt(etree.XSLTExtension): 1390 def execute(self, context, self_node, input_node, output_parent): 1391 tags.append(input_node.tag)
1392 1393 extensions = { ('testns', 'myext') : MyExt() } 1394 1395 result = tree.xslt(style, extensions=extensions) 1396 self.assertEqual(tags, ['a']) 1397
1398 - def test_extension_element_comment_pi_context(self):
1399 tree = self.parse('<?test toast?><a><!--a comment--><?another pi?></a>') 1400 style = self.parse('''\ 1401 <xsl:stylesheet version="1.0" 1402 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1403 xmlns:myns="testns" 1404 extension-element-prefixes="myns" 1405 exclude-result-prefixes="myns"> 1406 <xsl:template match="/"> 1407 <ROOT><xsl:apply-templates /></ROOT> 1408 </xsl:template> 1409 <xsl:template match="comment()"> 1410 <A><myns:myext>b</myns:myext></A> 1411 </xsl:template> 1412 <xsl:template match="processing-instruction()"> 1413 <A><myns:myext>b</myns:myext></A> 1414 </xsl:template> 1415 </xsl:stylesheet>''') 1416 1417 text = [] 1418 1419 class MyExt(etree.XSLTExtension): 1420 def execute(self, context, self_node, input_node, output_parent): 1421 text.append(input_node.text)
1422 1423 extensions = { ('testns', 'myext') : MyExt() } 1424 1425 result = tree.xslt(style, extensions=extensions) 1426 self.assertEqual(text, ['toast', 'a comment', 'pi']) 1427
1428 - def _test_extension_element_attribute_context(self):
1429 # currently not supported 1430 tree = self.parse('<a test="A"><b attr="B"/></a>') 1431 style = self.parse('''\ 1432 <xsl:stylesheet version="1.0" 1433 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1434 xmlns:myns="testns" 1435 extension-element-prefixes="myns" 1436 exclude-result-prefixes="myns"> 1437 <xsl:template match="@test"> 1438 <A><myns:myext>b</myns:myext></A> 1439 </xsl:template> 1440 <xsl:template match="@attr"> 1441 <A><myns:myext>b</myns:myext></A> 1442 </xsl:template> 1443 </xsl:stylesheet>''') 1444 1445 text = [] 1446 1447 class MyExt(etree.XSLTExtension): 1448 def execute(self, context, self_node, attr_value, output_parent): 1449 text.append(attr_value)
1450 1451 extensions = { ('testns', 'myext') : MyExt() } 1452 1453 result = tree.xslt(style, extensions=extensions) 1454 self.assertEqual(text, ['A', 'B']) 1455
1456 - def test_extension_element_content(self):
1457 tree = self.parse('<a><b>B</b></a>') 1458 style = self.parse('''\ 1459 <xsl:stylesheet version="1.0" 1460 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1461 xmlns:myns="testns" 1462 extension-element-prefixes="myns"> 1463 <xsl:template match="a"> 1464 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 1465 </xsl:template> 1466 </xsl:stylesheet>''') 1467 1468 class MyExt(etree.XSLTExtension): 1469 def execute(self, context, self_node, input_node, output_parent): 1470 output_parent.extend(list(self_node)[1:])
1471 1472 extensions = { ('testns', 'myext') : MyExt() } 1473 1474 result = tree.xslt(style, extensions=extensions) 1475 self.assertEqual(self._rootstring(result), 1476 _bytes('<A><y>Y</y><z/></A>')) 1477
1478 - def test_extension_element_apply_templates(self):
1479 tree = self.parse('<a><b>B</b></a>') 1480 style = self.parse('''\ 1481 <xsl:stylesheet version="1.0" 1482 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1483 xmlns:myns="testns" 1484 extension-element-prefixes="myns"> 1485 <xsl:template match="a"> 1486 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 1487 </xsl:template> 1488 <xsl:template match="x" /> 1489 <xsl:template match="z">XYZ</xsl:template> 1490 </xsl:stylesheet>''') 1491 1492 class MyExt(etree.XSLTExtension): 1493 def execute(self, context, self_node, input_node, output_parent): 1494 for child in self_node: 1495 for result in self.apply_templates(context, child): 1496 if isinstance(result, basestring): 1497 el = etree.Element("T") 1498 el.text = result 1499 else: 1500 el = result 1501 output_parent.append(el)
1502 1503 extensions = { ('testns', 'myext') : MyExt() } 1504 1505 result = tree.xslt(style, extensions=extensions) 1506 self.assertEqual(self._rootstring(result), 1507 _bytes('<A><T>Y</T><T>XYZ</T></A>')) 1508
1509 - def test_extension_element_apply_templates_elements_only(self):
1510 tree = self.parse('<a><b>B</b></a>') 1511 style = self.parse('''\ 1512 <xsl:stylesheet version="1.0" 1513 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1514 xmlns:myns="testns" 1515 extension-element-prefixes="myns"> 1516 <xsl:template match="a"> 1517 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 1518 </xsl:template> 1519 <xsl:template match="x"><X/></xsl:template> 1520 <xsl:template match="z">XYZ</xsl:template> 1521 </xsl:stylesheet>''') 1522 1523 class MyExt(etree.XSLTExtension): 1524 def execute(self, context, self_node, input_node, output_parent): 1525 for child in self_node: 1526 for result in self.apply_templates(context, child, 1527 elements_only=True): 1528 assert not isinstance(result, basestring) 1529 output_parent.append(result)
1530 1531 extensions = { ('testns', 'myext') : MyExt() } 1532 1533 result = tree.xslt(style, extensions=extensions) 1534 self.assertEqual(self._rootstring(result), 1535 _bytes('<A><X/></A>')) 1536
1537 - def test_extension_element_apply_templates_remove_blank_text(self):
1538 tree = self.parse('<a><b>B</b></a>') 1539 style = self.parse('''\ 1540 <xsl:stylesheet version="1.0" 1541 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1542 xmlns:myns="testns" 1543 extension-element-prefixes="myns"> 1544 <xsl:template match="a"> 1545 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 1546 </xsl:template> 1547 <xsl:template match="x"><X/></xsl:template> 1548 <xsl:template match="y"><xsl:text> </xsl:text></xsl:template> 1549 <xsl:template match="z">XYZ</xsl:template> 1550 </xsl:stylesheet>''') 1551 1552 class MyExt(etree.XSLTExtension): 1553 def execute(self, context, self_node, input_node, output_parent): 1554 for child in self_node: 1555 for result in self.apply_templates(context, child, 1556 remove_blank_text=True): 1557 if isinstance(result, basestring): 1558 assert result.strip() 1559 el = etree.Element("T") 1560 el.text = result 1561 else: 1562 el = result 1563 output_parent.append(el)
1564 1565 extensions = { ('testns', 'myext') : MyExt() } 1566 1567 result = tree.xslt(style, extensions=extensions) 1568 self.assertEqual(self._rootstring(result), 1569 _bytes('<A><X/><T>XYZ</T></A>')) 1570
1571 - def test_extension_element_apply_templates_target_node(self):
1572 tree = self.parse('<a><b>B</b></a>') 1573 style = self.parse('''\ 1574 <xsl:stylesheet version="1.0" 1575 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1576 xmlns:myns="testns" 1577 extension-element-prefixes="myns"> 1578 <xsl:template match="a"> 1579 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 1580 </xsl:template> 1581 <xsl:template match="x" /> 1582 <xsl:template match="z">XYZ</xsl:template> 1583 </xsl:stylesheet>''') 1584 1585 class MyExt(etree.XSLTExtension): 1586 def execute(self, context, self_node, input_node, output_parent): 1587 for child in self_node: 1588 self.apply_templates(context, child, output_parent)
1589 1590 extensions = { ('testns', 'myext') : MyExt() } 1591 1592 result = tree.xslt(style, extensions=extensions) 1593 self.assertEqual(self._rootstring(result), 1594 _bytes('<A>YXYZ</A>')) 1595
1596 - def test_extension_element_apply_templates_target_node_doc(self):
1597 tree = self.parse('<a><b>B</b></a>') 1598 style = self.parse('''\ 1599 <xsl:stylesheet version="1.0" 1600 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1601 xmlns:myns="testns" 1602 extension-element-prefixes="myns"> 1603 <xsl:template match="a"> 1604 <myns:myext><x>X</x><y>Y</y><z/></myns:myext> 1605 </xsl:template> 1606 <xsl:template match="x"><xsl:processing-instruction name="test">TEST</xsl:processing-instruction></xsl:template> 1607 <xsl:template match="y"><Y>XYZ</Y></xsl:template> 1608 <xsl:template match="z"><xsl:comment>TEST</xsl:comment></xsl:template> 1609 </xsl:stylesheet>''') 1610 1611 class MyExt(etree.XSLTExtension): 1612 def execute(self, context, self_node, input_node, output_parent): 1613 for child in self_node: 1614 self.apply_templates(context, child, output_parent)
1615 1616 extensions = { ('testns', 'myext') : MyExt() } 1617 1618 result = tree.xslt(style, extensions=extensions) 1619 self.assertEqual(etree.tostring(result), 1620 _bytes('<?test TEST?><Y>XYZ</Y><!--TEST-->')) 1621
1622 - def test_extension_element_process_children(self):
1623 tree = self.parse('<a><b>E</b></a>') 1624 style = self.parse('''\ 1625 <xsl:stylesheet version="1.0" 1626 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1627 xmlns:myns="testns" 1628 extension-element-prefixes="myns"> 1629 <xsl:template match="a"> 1630 <xsl:variable name="testvar">yo</xsl:variable> 1631 <A> 1632 <myns:myext> 1633 <xsl:attribute name="attr"> 1634 <xsl:value-of select="$testvar" /> 1635 </xsl:attribute> 1636 <B> 1637 <xsl:choose> 1638 <xsl:when test="1 = 2"><C/></xsl:when> 1639 <xsl:otherwise><D><xsl:value-of select="b/text()" /></D></xsl:otherwise> 1640 </xsl:choose> 1641 </B> 1642 </myns:myext> 1643 </A> 1644 </xsl:template> 1645 </xsl:stylesheet>''') 1646 1647 class MyExt(etree.XSLTExtension): 1648 def execute(self, context, self_node, input_node, output_parent): 1649 el = etree.Element('MY') 1650 self.process_children(context, el) 1651 output_parent.append(el)
1652 1653 extensions = { ('testns', 'myext') : MyExt() } 1654 1655 result = tree.xslt(style, extensions=extensions) 1656 self.assertEqual(self._rootstring(result), 1657 _bytes('<A><MYattr="yo"><B><D>E</D></B></MY></A>')) 1658
1659 - def test_extension_element_process_children_to_append_only(self):
1660 tree = self.parse('<a/>') 1661 style = self.parse('''\ 1662 <xsl:stylesheet version="1.0" 1663 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1664 xmlns:myns="testns" 1665 extension-element-prefixes="myns"> 1666 <xsl:template match="a"> 1667 <myns:myext> 1668 <A/> 1669 </myns:myext> 1670 </xsl:template> 1671 </xsl:stylesheet>''') 1672 1673 class MyExt(etree.XSLTExtension): 1674 def execute(self, context, self_node, input_node, output_parent): 1675 self.process_children(context, output_parent)
1676 1677 extensions = { ('testns', 'myext') : MyExt() } 1678 1679 result = tree.xslt(style, extensions=extensions) 1680 self.assertEqual(self._rootstring(result), 1681 _bytes('<A/>')) 1682
1683 - def test_extension_element_process_children_to_read_only_raise(self):
1684 tree = self.parse('<a/>') 1685 style = self.parse('''\ 1686 <xsl:stylesheet version="1.0" 1687 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1688 xmlns:myns="testns" 1689 extension-element-prefixes="myns"> 1690 <xsl:template match="a"> 1691 <myns:myext> 1692 <A/> 1693 </myns:myext> 1694 </xsl:template> 1695 </xsl:stylesheet>''') 1696 1697 class MyExt(etree.XSLTExtension): 1698 def execute(self, context, self_node, input_node, output_parent): 1699 self.process_children(context, self_node)
1700 1701 extensions = { ('testns', 'myext') : MyExt() } 1702 1703 self.assertRaises(TypeError, tree.xslt, style, extensions=extensions) 1704
1705 - def test_extension_element_process_children_with_subextension_element(self):
1706 tree = self.parse('<a/>') 1707 style = self.parse('''\ 1708 <xsl:stylesheet version="1.0" 1709 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1710 xmlns:myns="testns" 1711 extension-element-prefixes="myns"> 1712 <xsl:template match="a"> 1713 <myns:myext> 1714 <A><myns:myext><B/></myns:myext></A> 1715 </myns:myext> 1716 </xsl:template> 1717 </xsl:stylesheet>''') 1718 1719 class MyExt(etree.XSLTExtension): 1720 callback_call_counter = 0 1721 def execute(self, context, self_node, input_node, output_parent): 1722 self.callback_call_counter += 1 1723 el = etree.Element('MY', n=str(self.callback_call_counter)) 1724 self.process_children(context, el) 1725 output_parent.append(el)
1726 1727 extensions = { ('testns', 'myext') : MyExt() } 1728 1729 result = tree.xslt(style, extensions=extensions) 1730 self.assertEqual(self._rootstring(result), 1731 _bytes('<MYn="1"><A><MYn="2"><B/></MY></A></MY>')) 1732
1733 - def test_extension_element_raise(self):
1734 tree = self.parse('<a><b>B</b></a>') 1735 style = self.parse('''\ 1736 <xsl:stylesheet version="1.0" 1737 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1738 xmlns:myns="testns" 1739 extension-element-prefixes="myns" 1740 exclude-result-prefixes="myns"> 1741 <xsl:template match="a"> 1742 <A><myns:myext>b</myns:myext></A> 1743 </xsl:template> 1744 </xsl:stylesheet>''') 1745 1746 class MyError(Exception): 1747 pass
1748 1749 class MyExt(etree.XSLTExtension): 1750 def execute(self, context, self_node, input_node, output_parent): 1751 raise MyError("expected!") 1752 1753 extensions = { ('testns', 'myext') : MyExt() } 1754 self.assertRaises(MyError, tree.xslt, style, extensions=extensions) 1755 1756
1757 -class Py3XSLTTestCase(HelperTestCase):
1758 """XSLT tests for etree under Python 3""" 1759 1760 pytestmark = skipif('sys.version_info < (3,0)') 1761
1762 - def test_xslt_result_bytes(self):
1763 tree = self.parse('<a><b>B</b><c>C</c></a>') 1764 style = self.parse('''\ 1765 <xsl:stylesheet version="1.0" 1766 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1767 <xsl:template match="*" /> 1768 <xsl:template match="/"> 1769 <foo><xsl:value-of select="/a/b/text()" /></foo> 1770 </xsl:template> 1771 </xsl:stylesheet>''') 1772 1773 st = etree.XSLT(style) 1774 res = st(tree) 1775 self.assertEqual(_bytes('''\ 1776 <?xml version="1.0"?> 1777 <foo>B</foo> 1778 '''), 1779 bytes(res))
1780
1781 - def test_xslt_result_bytearray(self):
1782 tree = self.parse('<a><b>B</b><c>C</c></a>') 1783 style = self.parse('''\ 1784 <xsl:stylesheet version="1.0" 1785 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1786 <xsl:template match="*" /> 1787 <xsl:template match="/"> 1788 <foo><xsl:value-of select="/a/b/text()" /></foo> 1789 </xsl:template> 1790 </xsl:stylesheet>''') 1791 1792 st = etree.XSLT(style) 1793 res = st(tree) 1794 self.assertEqual(_bytes('''\ 1795 <?xml version="1.0"?> 1796 <foo>B</foo> 1797 '''), 1798 bytearray(res))
1799
1801 tree = self.parse('<a><b>B</b><c>C</c></a>') 1802 style = self.parse('''\ 1803 <xsl:stylesheet version="1.0" 1804 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1805 <xsl:template match="*" /> 1806 <xsl:template match="/"> 1807 <foo><xsl:value-of select="/a/b/text()" /></foo> 1808 </xsl:template> 1809 </xsl:stylesheet>''') 1810 1811 st = etree.XSLT(style) 1812 res = st(tree) 1813 self.assertEqual(_bytes('''\ 1814 <?xml version="1.0"?> 1815 <foo>B</foo> 1816 '''), 1817 bytes(memoryview(res)))
1818 1819
1820 -def test_suite():
1821 suite = unittest.TestSuite() 1822 suite.addTests([unittest.makeSuite(ETreeXSLTTestCase)]) 1823 suite.addTests([unittest.makeSuite(ETreeEXSLTTestCase)]) 1824 suite.addTests([unittest.makeSuite(ETreeXSLTExtFuncTestCase)]) 1825 suite.addTests([unittest.makeSuite(ETreeXSLTExtElementTestCase)]) 1826 if is_python3: 1827 suite.addTests([unittest.makeSuite(Py3XSLTTestCase)]) 1828 suite.addTests( 1829 [make_doctest('../../../doc/extensions.txt')]) 1830 suite.addTests( 1831 [make_doctest('../../../doc/xpathxslt.txt')]) 1832 return suite
1833 1834 if __name__ == '__main__': 1835 print('to test use test.py %s' % __file__) 1836