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