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