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