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_move_result(self):
786 root = etree.XML(_bytes('''\ 787 <transform> 788 <widget displayType="fieldset"/> 789 </transform>''')) 790 791 xslt = etree.XSLT(etree.XML(_bytes('''\ 792 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 793 <xsl:output method="html" indent="no"/> 794 <xsl:template match="/"> 795 <html> 796 <xsl:apply-templates/> 797 </html> 798 </xsl:template> 799 800 <xsl:template match="widget"> 801 <xsl:element name="{@displayType}"/> 802 </xsl:template> 803 804 </xsl:stylesheet>'''))) 805 806 result = xslt(root[0]) 807 root[:] = result.getroot()[:] 808 del root # segfaulted before
809
810 - def test_xslt_pi(self):
811 tree = self.parse('''\ 812 <?xml version="1.0"?> 813 <?xml-stylesheet type="text/xsl" href="%s"?> 814 <a> 815 <b>B</b> 816 <c>C</c> 817 </a>''' % fileInTestDir("test1.xslt")) 818 819 style_root = tree.getroot().getprevious().parseXSL().getroot() 820 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 821 style_root.tag)
822
823 - def test_xslt_pi_embedded_xmlid(self):
824 # test xml:id dictionary lookup mechanism 825 tree = self.parse('''\ 826 <?xml version="1.0"?> 827 <?xml-stylesheet type="text/xsl" href="#style"?> 828 <a> 829 <b>B</b> 830 <c>C</c> 831 <xsl:stylesheet version="1.0" xml:id="style" 832 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 833 <xsl:template match="*" /> 834 <xsl:template match="/"> 835 <foo><xsl:value-of select="/a/b/text()" /></foo> 836 </xsl:template> 837 </xsl:stylesheet> 838 </a>''') 839 840 style_root = tree.getroot().getprevious().parseXSL().getroot() 841 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 842 style_root.tag) 843 844 st = etree.XSLT(style_root) 845 res = st(tree) 846 self.assertEqual('''\ 847 <?xml version="1.0"?> 848 <foo>B</foo> 849 ''', 850 str(res))
851
852 - def test_xslt_pi_embedded_id(self):
853 # test XPath lookup mechanism 854 tree = self.parse('''\ 855 <?xml version="1.0"?> 856 <?xml-stylesheet type="text/xsl" href="#style"?> 857 <a> 858 <b>B</b> 859 <c>C</c> 860 </a>''') 861 862 style = self.parse('''\ 863 <xsl:stylesheet version="1.0" xml:id="style" 864 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 865 <xsl:template match="*" /> 866 <xsl:template match="/"> 867 <foo><xsl:value-of select="/a/b/text()" /></foo> 868 </xsl:template> 869 </xsl:stylesheet> 870 ''') 871 872 tree.getroot().append(style.getroot()) 873 874 style_root = tree.getroot().getprevious().parseXSL().getroot() 875 self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 876 style_root.tag) 877 878 st = etree.XSLT(style_root) 879 res = st(tree) 880 self.assertEqual('''\ 881 <?xml version="1.0"?> 882 <foo>B</foo> 883 ''', 884 str(res))
885
886 - def test_xslt_pi_get(self):
887 tree = self.parse('''\ 888 <?xml version="1.0"?> 889 <?xml-stylesheet type="text/xsl" href="TEST"?> 890 <a> 891 <b>B</b> 892 <c>C</c> 893 </a>''') 894 895 pi = tree.getroot().getprevious() 896 self.assertEqual("TEST", pi.get("href"))
897
898 - def test_xslt_pi_get_all(self):
899 tree = self.parse('''\ 900 <?xml version="1.0"?> 901 <?xml-stylesheet type="text/xsl" href="TEST"?> 902 <a> 903 <b>B</b> 904 <c>C</c> 905 </a>''') 906 907 pi = tree.getroot().getprevious() 908 self.assertEqual("TEST", pi.get("href")) 909 self.assertEqual("text/xsl", pi.get("type")) 910 self.assertEqual(None, pi.get("motz"))
911
912 - def test_xslt_pi_get_all_reversed(self):
913 tree = self.parse('''\ 914 <?xml version="1.0"?> 915 <?xml-stylesheet href="TEST" type="text/xsl"?> 916 <a> 917 <b>B</b> 918 <c>C</c> 919 </a>''') 920 921 pi = tree.getroot().getprevious() 922 self.assertEqual("TEST", pi.get("href")) 923 self.assertEqual("text/xsl", pi.get("type")) 924 self.assertEqual(None, pi.get("motz"))
925
926 - def test_xslt_pi_get_unknown(self):
927 tree = self.parse('''\ 928 <?xml version="1.0"?> 929 <?xml-stylesheet type="text/xsl" href="TEST"?> 930 <a> 931 <b>B</b> 932 <c>C</c> 933 </a>''') 934 935 pi = tree.getroot().getprevious() 936 self.assertEqual(None, pi.get("unknownattribute"))
937
938 - def test_xslt_pi_set_replace(self):
939 tree = self.parse('''\ 940 <?xml version="1.0"?> 941 <?xml-stylesheet type="text/xsl" href="TEST"?> 942 <a> 943 <b>B</b> 944 <c>C</c> 945 </a>''') 946 947 pi = tree.getroot().getprevious() 948 self.assertEqual("TEST", pi.get("href")) 949 950 pi.set("href", "TEST123") 951 self.assertEqual("TEST123", pi.get("href"))
952
953 - def test_xslt_pi_set_new(self):
954 tree = self.parse('''\ 955 <?xml version="1.0"?> 956 <?xml-stylesheet type="text/xsl"?> 957 <a> 958 <b>B</b> 959 <c>C</c> 960 </a>''') 961 962 pi = tree.getroot().getprevious() 963 self.assertEqual(None, pi.get("href")) 964 965 pi.set("href", "TEST") 966 self.assertEqual("TEST", pi.get("href"))
967
968 -class ETreeEXSLTTestCase(HelperTestCase):
969 """EXSLT tests""" 970
971 - def test_exslt_str(self):
972 tree = self.parse('<a><b>B</b><c>C</c></a>') 973 style = self.parse('''\ 974 <xsl:stylesheet version="1.0" 975 xmlns:str="http://exslt.org/strings" 976 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 977 exclude-result-prefixes="str xsl"> 978 <xsl:template match="text()"> 979 <xsl:value-of select="str:align(string(.), '***', 'center')" /> 980 </xsl:template> 981 <xsl:template match="*"> 982 <xsl:copy> 983 <xsl:apply-templates/> 984 </xsl:copy> 985 </xsl:template> 986 </xsl:stylesheet>''') 987 988 st = etree.XSLT(style) 989 res = st(tree) 990 self.assertEqual('''\ 991 <?xml version="1.0"?> 992 <a><b>*B*</b><c>*C*</c></a> 993 ''', 994 str(res))
995 996 if etree.LIBXSLT_VERSION >= (1,1,21):
998 tree = self.parse('<a><b>B</b><c>C</c></a>') 999 style = self.parse('''\ 1000 <xsl:stylesheet version = "1.0" 1001 xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 1002 xmlns:str="http://exslt.org/strings" 1003 extension-element-prefixes="str"> 1004 1005 <xsl:template match="/"> 1006 <h1 class="{str:replace('abc', 'b', 'x')}">test</h1> 1007 </xsl:template> 1008 1009 </xsl:stylesheet>''') 1010 1011 st = etree.XSLT(style) 1012 res = st(tree) 1013 self.assertEqual('''\ 1014 <?xml version="1.0"?> 1015 <h1 class="axc">test</h1> 1016 ''', 1017 str(res))
1018
1019 - def test_exslt_math(self):
1020 tree = self.parse('<a><b>B</b><c>C</c></a>') 1021 style = self.parse('''\ 1022 <xsl:stylesheet version="1.0" 1023 xmlns:math="http://exslt.org/math" 1024 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1025 exclude-result-prefixes="math xsl"> 1026 <xsl:template match="*"> 1027 <xsl:copy> 1028 <xsl:attribute name="pi"> 1029 <xsl:value-of select="math:constant('PI', count(*)+2)"/> 1030 </xsl:attribute> 1031 <xsl:apply-templates/> 1032 </xsl:copy> 1033 </xsl:template> 1034 </xsl:stylesheet>''') 1035 1036 st = etree.XSLT(style) 1037 res = st(tree) 1038 self.assertEqual('''\ 1039 <?xml version="1.0"?> 1040 <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a> 1041 ''', 1042 str(res))
1043
1044 - def test_exslt_regexp_test(self):
1045 xslt = etree.XSLT(etree.XML(_bytes("""\ 1046 <xsl:stylesheet version="1.0" 1047 xmlns:regexp="http://exslt.org/regular-expressions" 1048 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1049 <xsl:template match="*"> 1050 <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test> 1051 </xsl:template> 1052 </xsl:stylesheet> 1053 """))) 1054 result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>'))) 1055 root = result.getroot() 1056 self.assertEqual(root.tag, 1057 'test') 1058 self.assertEqual(len(root), 1) 1059 self.assertEqual(root[0].tag, 1060 'b') 1061 self.assertEqual(root[0].text, 1062 '987')
1063
1064 - def test_exslt_regexp_replace(self):
1065 xslt = etree.XSLT(etree.XML("""\ 1066 <xsl:stylesheet version="1.0" 1067 xmlns:regexp="http://exslt.org/regular-expressions" 1068 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1069 <xsl:template match="*"> 1070 <test> 1071 <xsl:copy-of select="regexp:replace(string(.), 'd.', '', 'XX')"/> 1072 <xsl:text>-</xsl:text> 1073 <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/> 1074 </test> 1075 </xsl:template> 1076 </xsl:stylesheet> 1077 """)) 1078 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>'))) 1079 root = result.getroot() 1080 self.assertEqual(root.tag, 1081 'test') 1082 self.assertEqual(len(root), 0) 1083 self.assertEqual(root.text, 'abXXdEeDed-abXXXXeXXd')
1084
1085 - def test_exslt_regexp_match(self):
1086 xslt = etree.XSLT(etree.XML("""\ 1087 <xsl:stylesheet version="1.0" 1088 xmlns:regexp="http://exslt.org/regular-expressions" 1089 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1090 <xsl:template match="*"> 1091 <test> 1092 <test1><xsl:copy-of select="regexp:match(string(.), 'd.')"/></test1> 1093 <test2><xsl:copy-of select="regexp:match(string(.), 'd.', 'g')"/></test2> 1094 <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i> 1095 </test> 1096 </xsl:template> 1097 </xsl:stylesheet> 1098 """)) 1099 result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>'))) 1100 root = result.getroot() 1101 self.assertEqual(root.tag, 'test') 1102 self.assertEqual(len(root), 3) 1103 1104 self.assertEqual(len(root[0]), 1) 1105 self.assertEqual(root[0][0].tag, 'match') 1106 self.assertEqual(root[0][0].text, 'dC') 1107 1108 self.assertEqual(len(root[1]), 2) 1109 self.assertEqual(root[1][0].tag, 'match') 1110 self.assertEqual(root[1][0].text, 'dC') 1111 self.assertEqual(root[1][1].tag, 'match') 1112 self.assertEqual(root[1][1].text, 'dE') 1113 1114 self.assertEqual(len(root[2]), 3) 1115 self.assertEqual(root[2][0].tag, 'match') 1116 self.assertEqual(root[2][0].text, 'dC') 1117 self.assertEqual(root[2][1].tag, 'match') 1118 self.assertEqual(root[2][1].text, 'dE') 1119 self.assertEqual(root[2][2].tag, 'match') 1120 self.assertEqual(root[2][2].text, 'De')
1121
1123 xslt = etree.XSLT(etree.XML(_bytes("""\ 1124 <xsl:stylesheet version="1.0" 1125 xmlns:regexp="http://exslt.org/regular-expressions" 1126 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1127 <xsl:template match="/"> 1128 <test> 1129 <xsl:for-each select="regexp:match( 1130 '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )"> 1131 <test1><xsl:value-of select="."/></test1> 1132 </xsl:for-each> 1133 </test> 1134 </xsl:template> 1135 </xsl:stylesheet> 1136 """))) 1137 result = xslt(etree.XML(_bytes('<a/>'))) 1138 root = result.getroot() 1139 self.assertEqual(root.tag, 'test') 1140 self.assertEqual(len(root), 4) 1141 1142 self.assertEqual(root[0].text, "123abc567") 1143 self.assertEqual(root[1].text, "123") 1144 self.assertEqual(root[2].text, "abc") 1145 self.assertEqual(root[3].text, "567")
1146
1147 - def test_exslt_regexp_match1(self):
1148 # taken from http://www.exslt.org/regexp/functions/match/index.html 1149 xslt = etree.XSLT(etree.XML(_bytes("""\ 1150 <xsl:stylesheet version="1.0" 1151 xmlns:regexp="http://exslt.org/regular-expressions" 1152 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1153 <xsl:template match="/"> 1154 <test> 1155 <xsl:for-each select="regexp:match( 1156 'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml', 1157 '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')"> 1158 <test1><xsl:value-of select="."/></test1> 1159 </xsl:for-each> 1160 </test> 1161 </xsl:template> 1162 </xsl:stylesheet> 1163 """))) 1164 result = xslt(etree.XML(_bytes('<a/>'))) 1165 root = result.getroot() 1166 self.assertEqual(root.tag, 'test') 1167 self.assertEqual(len(root), 5) 1168 1169 self.assertEqual( 1170 root[0].text, 1171 "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml") 1172 self.assertEqual( 1173 root[1].text, 1174 "http") 1175 self.assertEqual( 1176 root[2].text, 1177 "www.bayes.co.uk") 1178 self.assertFalse(root[3].text) 1179 self.assertEqual( 1180 root[4].text, 1181 "/xml/index.xml?/xml/utils/rechecker.xml")
1182
1183 - def test_exslt_regexp_match2(self):
1184 # taken from http://www.exslt.org/regexp/functions/match/index.html 1185 xslt = etree.XSLT(self.parse("""\ 1186 <xsl:stylesheet version="1.0" 1187 xmlns:regexp="http://exslt.org/regular-expressions" 1188 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1189 <xsl:template match="/"> 1190 <test> 1191 <xsl:for-each select="regexp:match( 1192 'This is a test string', '(\w+)', 'g')"> 1193 <test1><xsl:value-of select="."/></test1> 1194 </xsl:for-each> 1195 </test> 1196 </xsl:template> 1197 </xsl:stylesheet> 1198 """)) 1199 result = xslt(etree.XML(_bytes('<a/>'))) 1200 root = result.getroot() 1201 self.assertEqual(root.tag, 'test') 1202 self.assertEqual(len(root), 5) 1203 1204 self.assertEqual(root[0].text, "This") 1205 self.assertEqual(root[1].text, "is") 1206 self.assertEqual(root[2].text, "a") 1207 self.assertEqual(root[3].text, "test") 1208 self.assertEqual(root[4].text, "string")
1209
1210 - def _test_exslt_regexp_match3(self):
1211 # taken from http://www.exslt.org/regexp/functions/match/index.html 1212 # THIS IS NOT SUPPORTED! 1213 xslt = etree.XSLT(etree.XML(_bytes("""\ 1214 <xsl:stylesheet version="1.0" 1215 xmlns:regexp="http://exslt.org/regular-expressions" 1216 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1217 <xsl:template match="/"> 1218 <test> 1219 <xsl:for-each select="regexp:match( 1220 'This is a test string', '([a-z])+ ', 'g')"> 1221 <test1><xsl:value-of select="."/></test1> 1222 </xsl:for-each> 1223 </test> 1224 </xsl:template> 1225 </xsl:stylesheet> 1226 """))) 1227 result = xslt(etree.XML(_bytes('<a/>'))) 1228 root = result.getroot() 1229 self.assertEqual(root.tag, 'test') 1230 self.assertEqual(len(root), 4) 1231 1232 self.assertEqual(root[0].text, "his") 1233 self.assertEqual(root[1].text, "is") 1234 self.assertEqual(root[2].text, "a") 1235 self.assertEqual(root[3].text, "test")
1236
1237 - def _test_exslt_regexp_match4(self):
1238 # taken from http://www.exslt.org/regexp/functions/match/index.html 1239 # THIS IS NOT SUPPORTED! 1240 xslt = etree.XSLT(etree.XML(_bytes("""\ 1241 <xsl:stylesheet version="1.0" 1242 xmlns:regexp="http://exslt.org/regular-expressions" 1243 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1244 <xsl:template match="/"> 1245 <test> 1246 <xsl:for-each select="regexp:match( 1247 'This is a test string', '([a-z])+ ', 'gi')"> 1248 <test1><xsl:value-of select="."/></test1> 1249 </xsl:for-each> 1250 </test> 1251 </xsl:template> 1252 </xsl:stylesheet> 1253 """))) 1254 result = xslt(etree.XML(_bytes('<a/>'))) 1255 root = result.getroot() 1256 self.assertEqual(root.tag, 'test') 1257 self.assertEqual(len(root), 4) 1258 1259 self.assertEqual(root[0].text, "This") 1260 self.assertEqual(root[1].text, "is") 1261 self.assertEqual(root[2].text, "a") 1262 self.assertEqual(root[3].text, "test")
1263 1264
1265 -class ETreeXSLTExtFuncTestCase(HelperTestCase):
1266 """Tests for XPath extension functions in XSLT.""" 1267
1268 - def test_extensions1(self):
1269 tree = self.parse('<a><b>B</b></a>') 1270 style = self.parse('''\ 1271 <xsl:stylesheet version="1.0" 1272 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1273 xmlns:myns="testns" 1274 exclude-result-prefixes="myns"> 1275 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template> 1276 </xsl:stylesheet>''') 1277 1278 def mytext(ctxt, values): 1279 return 'X' * len(values)
1280 1281 result = tree.xslt(style, {('testns', 'mytext') : mytext}) 1282 self.assertEqual(self._rootstring(result), 1283 _bytes('<A>X</A>'))
1284
1285 - def test_extensions2(self):
1286 tree = self.parse('<a><b>B</b></a>') 1287 style = self.parse('''\ 1288 <xsl:stylesheet version="1.0" 1289 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1290 xmlns:myns="testns" 1291 exclude-result-prefixes="myns"> 1292 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template> 1293 </xsl:stylesheet>''') 1294 1295 def mytext(ctxt, values): 1296 return 'X' * len(values)
1297 1298 namespace = etree.FunctionNamespace('testns') 1299 namespace['mytext'] = mytext 1300 1301 result = tree.xslt(style) 1302 self.assertEqual(self._rootstring(result), 1303 _bytes('<A>X</A>')) 1304
1305 - def test_variable_result_tree_fragment(self):
1306 tree = self.parse('<a><b>B</b><b/></a>') 1307 style = self.parse('''\ 1308 <xsl:stylesheet version="1.0" 1309 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1310 xmlns:myns="testns" 1311 exclude-result-prefixes="myns"> 1312 <xsl:template match="a"> 1313 <xsl:variable name="content"> 1314 <xsl:apply-templates/> 1315 </xsl:variable> 1316 <A><xsl:value-of select="myns:mytext($content)"/></A> 1317 </xsl:template> 1318 <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template> 1319 </xsl:stylesheet>''') 1320 1321 def mytext(ctxt, values): 1322 for value in values: 1323 self.assertTrue(hasattr(value, 'tag'), 1324 "%s is not an Element" % type(value)) 1325 self.assertEqual(value.tag, 'b') 1326 self.assertEqual(value.text, 'BBB') 1327 return 'X'.join([el.tag for el in values])
1328 1329 namespace = etree.FunctionNamespace('testns') 1330 namespace['mytext'] = mytext 1331 1332 result = tree.xslt(style) 1333 self.assertEqual(self._rootstring(result), 1334 _bytes('<A>bXb</A>')) 1335 1336
1337 -class ETreeXSLTExtElementTestCase(HelperTestCase):
1338 """Tests for extension elements in XSLT.""" 1339
1340 - def test_extension_element(self):
1341 tree = self.parse('<a><b>B</b></a>') 1342 style = self.parse('''\ 1343 <xsl:stylesheet version="1.0" 1344 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1345 xmlns:myns="testns" 1346 extension-element-prefixes="myns" 1347 exclude-result-prefixes="myns"> 1348 <xsl:template match="a"> 1349 <A><myns:myext>b</myns:myext></A> 1350 </xsl:template> 1351 </xsl:stylesheet>''') 1352 1353 class MyExt(etree.XSLTExtension): 1354 def execute(self, context, self_node, input_node, output_parent): 1355 child = etree.Element(self_node.text) 1356 child.text = 'X' 1357 output_parent.append(child)
1358 1359 extensions = { ('testns', 'myext') : MyExt() } 1360 1361 result = tree.xslt(style, extensions=extensions) 1362 self.assertEqual(self._rootstring(result), 1363 _bytes('<A><b>X</b></A>')) 1364
1365 - def test_extension_element_doc_context(self):
1366 tree = self.parse('<a><b>B</b></a>') 1367 style = self.parse('''\ 1368 <xsl:stylesheet version="1.0" 1369 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1370 xmlns:myns="testns" 1371 extension-element-prefixes="myns" 1372 exclude-result-prefixes="myns"> 1373 <xsl:template match="/"> 1374 <A><myns:myext>b</myns:myext></A> 1375 </xsl:template> 1376 </xsl:stylesheet>''') 1377 1378 tags = [] 1379 1380 class MyExt(etree.XSLTExtension): 1381 def execute(self, context, self_node, input_node, output_parent): 1382 tags.append(input_node.tag)
1383 1384 extensions = { ('testns', 'myext') : MyExt() } 1385 1386 result = tree.xslt(style, extensions=extensions) 1387 self.assertEqual(tags, ['a']) 1388
1389 - def test_extension_element_comment_pi_context(self):
1390 tree = self.parse('<?test toast?><a><!--a comment--><?another pi?></a>') 1391 style = self.parse('''\ 1392 <xsl:stylesheet version="1.0" 1393 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1394 xmlns:myns="testns" 1395 extension-element-prefixes="myns" 1396 exclude-result-prefixes="myns"> 1397 <xsl:template match="/"> 1398 <ROOT><xsl:apply-templates /></ROOT> 1399 </xsl:template> 1400 <xsl:template match="comment()"> 1401 <A><myns:myext>b</myns:myext></A> 1402 </xsl:template> 1403 <xsl:template match="processing-instruction()"> 1404 <A><myns:myext>b</myns:myext></A> 1405 </xsl:template> 1406 </xsl:stylesheet>''') 1407 1408 text = [] 1409 1410 class MyExt(etree.XSLTExtension): 1411 def execute(self, context, self_node, input_node, output_parent): 1412 text.append(input_node.text)
1413 1414 extensions = { ('testns', 'myext') : MyExt() } 1415 1416 result = tree.xslt(style, extensions=extensions) 1417 self.assertEqual(text, ['toast', 'a comment', 'pi']) 1418
1419 - def _test_extension_element_attribute_context(self):
1420 # currently not supported 1421 tree = self.parse('<a test="A"><b attr="B"/></a>') 1422 style = self.parse('''\ 1423 <xsl:stylesheet version="1.0" 1424 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1425 xmlns:myns="testns" 1426 extension-element-prefixes="myns" 1427 exclude-result-prefixes="myns"> 1428 <xsl:template match="@test"> 1429 <A><myns:myext>b</myns:myext></A> 1430 </xsl:template> 1431 <xsl:template match="@attr"> 1432 <A><myns:myext>b</myns:myext></A> 1433 </xsl:template> 1434 </xsl:stylesheet>''') 1435 1436 text = [] 1437 1438 class MyExt(etree.XSLTExtension): 1439 def execute(self, context, self_node, attr_value, output_parent): 1440 text.append(attr_value)
1441 1442 extensions = { ('testns', 'myext') : MyExt() } 1443 1444 result = tree.xslt(style, extensions=extensions) 1445 self.assertEqual(text, ['A', 'B']) 1446
1447 - def test_extension_element_content(self):
1448 tree = self.parse('<a><b>B</b></a>') 1449 style = self.parse('''\ 1450 <xsl:stylesheet version="1.0" 1451 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1452 xmlns:myns="testns" 1453 extension-element-prefixes="myns"> 1454 <xsl:template match="a"> 1455 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 1456 </xsl:template> 1457 </xsl:stylesheet>''') 1458 1459 class MyExt(etree.XSLTExtension): 1460 def execute(self, context, self_node, input_node, output_parent): 1461 output_parent.extend(list(self_node)[1:])
1462 1463 extensions = { ('testns', 'myext') : MyExt() } 1464 1465 result = tree.xslt(style, extensions=extensions) 1466 self.assertEqual(self._rootstring(result), 1467 _bytes('<A><y>Y</y><z/></A>')) 1468
1469 - def test_extension_element_apply_templates(self):
1470 tree = self.parse('<a><b>B</b></a>') 1471 style = self.parse('''\ 1472 <xsl:stylesheet version="1.0" 1473 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1474 xmlns:myns="testns" 1475 extension-element-prefixes="myns"> 1476 <xsl:template match="a"> 1477 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 1478 </xsl:template> 1479 <xsl:template match="x" /> 1480 <xsl:template match="z">XYZ</xsl:template> 1481 </xsl:stylesheet>''') 1482 1483 class MyExt(etree.XSLTExtension): 1484 def execute(self, context, self_node, input_node, output_parent): 1485 for child in self_node: 1486 for result in self.apply_templates(context, child): 1487 if isinstance(result, basestring): 1488 el = etree.Element("T") 1489 el.text = result 1490 else: 1491 el = result 1492 output_parent.append(el)
1493 1494 extensions = { ('testns', 'myext') : MyExt() } 1495 1496 result = tree.xslt(style, extensions=extensions) 1497 self.assertEqual(self._rootstring(result), 1498 _bytes('<A><T>Y</T><T>XYZ</T></A>')) 1499
1500 - def test_extension_element_apply_templates_target_node(self):
1501 tree = self.parse('<a><b>B</b></a>') 1502 style = self.parse('''\ 1503 <xsl:stylesheet version="1.0" 1504 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1505 xmlns:myns="testns" 1506 extension-element-prefixes="myns"> 1507 <xsl:template match="a"> 1508 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 1509 </xsl:template> 1510 <xsl:template match="x" /> 1511 <xsl:template match="z">XYZ</xsl:template> 1512 </xsl:stylesheet>''') 1513 1514 class MyExt(etree.XSLTExtension): 1515 def execute(self, context, self_node, input_node, output_parent): 1516 for child in self_node: 1517 self.apply_templates(context, child, output_parent)
1518 1519 extensions = { ('testns', 'myext') : MyExt() } 1520 1521 result = tree.xslt(style, extensions=extensions) 1522 self.assertEqual(self._rootstring(result), 1523 _bytes('<A>YXYZ</A>')) 1524
1525 - def test_extension_element_apply_templates_target_node_doc(self):
1526 tree = self.parse('<a><b>B</b></a>') 1527 style = self.parse('''\ 1528 <xsl:stylesheet version="1.0" 1529 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1530 xmlns:myns="testns" 1531 extension-element-prefixes="myns"> 1532 <xsl:template match="a"> 1533 <myns:myext><x>X</x><y>Y</y><z/></myns:myext> 1534 </xsl:template> 1535 <xsl:template match="x"><xsl:processing-instruction name="test">TEST</xsl:processing-instruction></xsl:template> 1536 <xsl:template match="y"><Y>XYZ</Y></xsl:template> 1537 <xsl:template match="z"><xsl:comment>TEST</xsl:comment></xsl:template> 1538 </xsl:stylesheet>''') 1539 1540 class MyExt(etree.XSLTExtension): 1541 def execute(self, context, self_node, input_node, output_parent): 1542 for child in self_node: 1543 self.apply_templates(context, child, output_parent)
1544 1545 extensions = { ('testns', 'myext') : MyExt() } 1546 1547 result = tree.xslt(style, extensions=extensions) 1548 self.assertEqual(etree.tostring(result), 1549 _bytes('<?test TEST?><Y>XYZ</Y><!--TEST-->')) 1550
1551 - def test_extension_element_process_children(self):
1552 tree = self.parse('<a><b>E</b></a>') 1553 style = self.parse('''\ 1554 <xsl:stylesheet version="1.0" 1555 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1556 xmlns:myns="testns" 1557 extension-element-prefixes="myns"> 1558 <xsl:template match="a"> 1559 <xsl:variable name="testvar">yo</xsl:variable> 1560 <A> 1561 <myns:myext> 1562 <xsl:attribute name="attr"> 1563 <xsl:value-of select="$testvar" /> 1564 </xsl:attribute> 1565 <B> 1566 <xsl:choose> 1567 <xsl:when test="1 = 2"><C/></xsl:when> 1568 <xsl:otherwise><D><xsl:value-of select="b/text()" /></D></xsl:otherwise> 1569 </xsl:choose> 1570 </B> 1571 </myns:myext> 1572 </A> 1573 </xsl:template> 1574 </xsl:stylesheet>''') 1575 1576 class MyExt(etree.XSLTExtension): 1577 def execute(self, context, self_node, input_node, output_parent): 1578 el = etree.Element('MY') 1579 self.process_children(context, el) 1580 output_parent.append(el)
1581 1582 extensions = { ('testns', 'myext') : MyExt() } 1583 1584 result = tree.xslt(style, extensions=extensions) 1585 self.assertEqual(self._rootstring(result), 1586 _bytes('<A><MYattr="yo"><B><D>E</D></B></MY></A>')) 1587
1588 - def test_extension_element_process_children_to_append_only(self):
1589 tree = self.parse('<a/>') 1590 style = self.parse('''\ 1591 <xsl:stylesheet version="1.0" 1592 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1593 xmlns:myns="testns" 1594 extension-element-prefixes="myns"> 1595 <xsl:template match="a"> 1596 <myns:myext> 1597 <A/> 1598 </myns:myext> 1599 </xsl:template> 1600 </xsl:stylesheet>''') 1601 1602 class MyExt(etree.XSLTExtension): 1603 def execute(self, context, self_node, input_node, output_parent): 1604 self.process_children(context, output_parent)
1605 1606 extensions = { ('testns', 'myext') : MyExt() } 1607 1608 result = tree.xslt(style, extensions=extensions) 1609 self.assertEqual(self._rootstring(result), 1610 _bytes('<A/>')) 1611
1612 - def test_extension_element_process_children_to_read_only_raise(self):
1613 tree = self.parse('<a/>') 1614 style = self.parse('''\ 1615 <xsl:stylesheet version="1.0" 1616 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1617 xmlns:myns="testns" 1618 extension-element-prefixes="myns"> 1619 <xsl:template match="a"> 1620 <myns:myext> 1621 <A/> 1622 </myns:myext> 1623 </xsl:template> 1624 </xsl:stylesheet>''') 1625 1626 class MyExt(etree.XSLTExtension): 1627 def execute(self, context, self_node, input_node, output_parent): 1628 self.process_children(context, self_node)
1629 1630 extensions = { ('testns', 'myext') : MyExt() } 1631 1632 self.assertRaises(TypeError, tree.xslt, style, extensions=extensions) 1633
1634 - def test_extension_element_process_children_with_subextension_element(self):
1635 tree = self.parse('<a/>') 1636 style = self.parse('''\ 1637 <xsl:stylesheet version="1.0" 1638 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1639 xmlns:myns="testns" 1640 extension-element-prefixes="myns"> 1641 <xsl:template match="a"> 1642 <myns:myext> 1643 <A><myns:myext><B/></myns:myext></A> 1644 </myns:myext> 1645 </xsl:template> 1646 </xsl:stylesheet>''') 1647 1648 class MyExt(etree.XSLTExtension): 1649 callback_call_counter = 0 1650 def execute(self, context, self_node, input_node, output_parent): 1651 self.callback_call_counter += 1 1652 el = etree.Element('MY', n=str(self.callback_call_counter)) 1653 self.process_children(context, el) 1654 output_parent.append(el)
1655 1656 extensions = { ('testns', 'myext') : MyExt() } 1657 1658 result = tree.xslt(style, extensions=extensions) 1659 self.assertEqual(self._rootstring(result), 1660 _bytes('<MYn="1"><A><MYn="2"><B/></MY></A></MY>')) 1661
1662 - def test_extension_element_raise(self):
1663 tree = self.parse('<a><b>B</b></a>') 1664 style = self.parse('''\ 1665 <xsl:stylesheet version="1.0" 1666 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 1667 xmlns:myns="testns" 1668 extension-element-prefixes="myns" 1669 exclude-result-prefixes="myns"> 1670 <xsl:template match="a"> 1671 <A><myns:myext>b</myns:myext></A> 1672 </xsl:template> 1673 </xsl:stylesheet>''') 1674 1675 class MyError(Exception): 1676 pass
1677 1678 class MyExt(etree.XSLTExtension): 1679 def execute(self, context, self_node, input_node, output_parent): 1680 raise MyError("expected!") 1681 1682 extensions = { ('testns', 'myext') : MyExt() } 1683 self.assertRaises(MyError, tree.xslt, style, extensions=extensions) 1684 1685
1686 -class Py3XSLTTestCase(HelperTestCase):
1687 """XSLT tests for etree under Python 3""" 1688 1689 pytestmark = skipif('sys.version_info < (3,0)') 1690
1691 - def test_xslt_result_bytes(self):
1692 tree = self.parse('<a><b>B</b><c>C</c></a>') 1693 style = self.parse('''\ 1694 <xsl:stylesheet version="1.0" 1695 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1696 <xsl:template match="*" /> 1697 <xsl:template match="/"> 1698 <foo><xsl:value-of select="/a/b/text()" /></foo> 1699 </xsl:template> 1700 </xsl:stylesheet>''') 1701 1702 st = etree.XSLT(style) 1703 res = st(tree) 1704 self.assertEqual(_bytes('''\ 1705 <?xml version="1.0"?> 1706 <foo>B</foo> 1707 '''), 1708 bytes(res))
1709
1710 - def test_xslt_result_bytearray(self):
1711 tree = self.parse('<a><b>B</b><c>C</c></a>') 1712 style = self.parse('''\ 1713 <xsl:stylesheet version="1.0" 1714 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1715 <xsl:template match="*" /> 1716 <xsl:template match="/"> 1717 <foo><xsl:value-of select="/a/b/text()" /></foo> 1718 </xsl:template> 1719 </xsl:stylesheet>''') 1720 1721 st = etree.XSLT(style) 1722 res = st(tree) 1723 self.assertEqual(_bytes('''\ 1724 <?xml version="1.0"?> 1725 <foo>B</foo> 1726 '''), 1727 bytearray(res))
1728
1730 tree = self.parse('<a><b>B</b><c>C</c></a>') 1731 style = self.parse('''\ 1732 <xsl:stylesheet version="1.0" 1733 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1734 <xsl:template match="*" /> 1735 <xsl:template match="/"> 1736 <foo><xsl:value-of select="/a/b/text()" /></foo> 1737 </xsl:template> 1738 </xsl:stylesheet>''') 1739 1740 st = etree.XSLT(style) 1741 res = st(tree) 1742 self.assertEqual(_bytes('''\ 1743 <?xml version="1.0"?> 1744 <foo>B</foo> 1745 '''), 1746 bytes(memoryview(res)))
1747 1748
1749 -def test_suite():
1750 suite = unittest.TestSuite() 1751 suite.addTests([unittest.makeSuite(ETreeXSLTTestCase)]) 1752 suite.addTests([unittest.makeSuite(ETreeEXSLTTestCase)]) 1753 suite.addTests([unittest.makeSuite(ETreeXSLTExtFuncTestCase)]) 1754 suite.addTests([unittest.makeSuite(ETreeXSLTExtElementTestCase)]) 1755 if is_python3: 1756 suite.addTests([unittest.makeSuite(Py3XSLTTestCase)]) 1757 suite.addTests( 1758 [make_doctest('../../../doc/extensions.txt')]) 1759 suite.addTests( 1760 [make_doctest('../../../doc/xpathxslt.txt')]) 1761 return suite
1762 1763 if __name__ == '__main__': 1764 print('to test use test.py %s' % __file__) 1765