Package lxml :: Package tests :: Module test_xslt
[hide private]
[frames] | no frames]

Source Code for Module lxml.tests.test_xslt

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