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