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