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