Package lxml :: Package tests :: Module test_xslt
[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 
   8   
   9  from common_imports import etree, StringIO, HelperTestCase, fileInTestDir 
  10  from common_imports import doctest 
  11   
12 -class ETreeXSLTTestCase(HelperTestCase):
13 """XPath tests etree""" 14
15 - def test_xslt(self):
16 tree = self.parse('<a><b>B</b><c>C</c></a>') 17 style = self.parse('''\ 18 <xsl:stylesheet version="1.0" 19 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 20 <xsl:template match="*" /> 21 <xsl:template match="/"> 22 <foo><xsl:value-of select="/a/b/text()" /></foo> 23 </xsl:template> 24 </xsl:stylesheet>''') 25 26 st = etree.XSLT(style) 27 res = st(tree) 28 self.assertEquals('''\ 29 <?xml version="1.0"?> 30 <foo>B</foo> 31 ''', 32 str(res))
33
35 self.assertRaises(ValueError, etree.XSLT, etree.ElementTree())
36
37 - def test_xslt_input_none(self):
38 self.assertRaises(TypeError, etree.XSLT, None)
39 40 if False and etree.LIBXSLT_VERSION >= (1,1,15): 41 # earlier versions generate no error 42 if etree.LIBXSLT_VERSION > (1,1,17):
44 style = self.parse('''\ 45 <xsl:stylesheet version="1.0" 46 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 47 <xsl:stylesheet /> 48 </xsl:stylesheet>''') 49 50 self.assertRaises( 51 etree.XSLTParseError, etree.XSLT, style)
52
53 - def test_xslt_copy(self):
54 tree = self.parse('<a><b>B</b><c>C</c></a>') 55 style = self.parse('''\ 56 <xsl:stylesheet version="1.0" 57 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 58 <xsl:template match="*" /> 59 <xsl:template match="/"> 60 <foo><xsl:value-of select="/a/b/text()" /></foo> 61 </xsl:template> 62 </xsl:stylesheet>''') 63 64 transform = etree.XSLT(style) 65 res = transform(tree) 66 self.assertEquals('''\ 67 <?xml version="1.0"?> 68 <foo>B</foo> 69 ''', 70 str(res)) 71 72 transform_copy = copy.deepcopy(transform) 73 res = transform_copy(tree) 74 self.assertEquals('''\ 75 <?xml version="1.0"?> 76 <foo>B</foo> 77 ''', 78 str(res)) 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 - def test_xslt_utf8(self):
89 tree = self.parse(u'<a><b>\uF8D2</b><c>\uF8D2</c></a>') 90 style = self.parse('''\ 91 <xsl:stylesheet version="1.0" 92 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 93 <xsl:output encoding="UTF-8"/> 94 <xsl:template match="/"> 95 <foo><xsl:value-of select="/a/b/text()" /></foo> 96 </xsl:template> 97 </xsl:stylesheet>''') 98 99 st = etree.XSLT(style) 100 res = st(tree) 101 expected = u'''\ 102 <?xml version="1.0" encoding="UTF-8"?> 103 <foo>\uF8D2</foo> 104 ''' 105 self.assertEquals(expected, 106 unicode(str(res), 'UTF-8'))
107
108 - def test_xslt_encoding(self):
109 tree = self.parse(u'<a><b>\uF8D2</b><c>\uF8D2</c></a>') 110 style = self.parse('''\ 111 <xsl:stylesheet version="1.0" 112 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 113 <xsl:output encoding="UTF-16"/> 114 <xsl:template match="/"> 115 <foo><xsl:value-of select="/a/b/text()" /></foo> 116 </xsl:template> 117 </xsl:stylesheet>''') 118 119 st = etree.XSLT(style) 120 res = st(tree) 121 expected = u'''\ 122 <?xml version="1.0" encoding="UTF-16"?> 123 <foo>\uF8D2</foo> 124 ''' 125 self.assertEquals(expected, 126 unicode(str(res), 'UTF-16'))
127
129 tree = self.parse(u'<a><b>\uF8D2</b><c>\uF8D2</c></a>') 130 style = self.parse('''\ 131 <xsl:stylesheet version="1.0" 132 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 133 <xsl:output encoding="UTF-8"/> 134 <xsl:template match="/"> 135 <foo><xsl:value-of select="/a/b/text()" /></foo> 136 </xsl:template> 137 </xsl:stylesheet>''') 138 139 st = etree.XSLT(style) 140 res = st(tree) 141 expected = u"""\ 142 <?xml version='1.0' encoding='UTF-16'?>\ 143 <foo>\uF8D2</foo>""" 144 145 f = StringIO() 146 res.write(f, encoding='UTF-16') 147 result = unicode(f.getvalue(), 'UTF-16').replace('\n', '') 148 self.assertEquals(expected, 149 result)
150
151 - def test_xslt_unicode(self):
152 tree = self.parse(u'<a><b>\uF8D2</b><c>\uF8D2</c></a>') 153 style = self.parse('''\ 154 <xsl:stylesheet version="1.0" 155 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 156 <xsl:output encoding="UTF-16"/> 157 <xsl:template match="/"> 158 <foo><xsl:value-of select="/a/b/text()" /></foo> 159 </xsl:template> 160 </xsl:stylesheet>''') 161 162 st = etree.XSLT(style) 163 res = st(tree) 164 expected = u'''\ 165 <?xml version="1.0"?> 166 <foo>\uF8D2</foo> 167 ''' 168 self.assertEquals(expected, 169 unicode(res))
170
171 - def test_exslt_str(self):
172 tree = self.parse('<a><b>B</b><c>C</c></a>') 173 style = self.parse('''\ 174 <xsl:stylesheet version="1.0" 175 xmlns:str="http://exslt.org/strings" 176 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 177 exclude-result-prefixes="str xsl"> 178 <xsl:template match="text()"> 179 <xsl:value-of select="str:align(string(.), '***', 'center')" /> 180 </xsl:template> 181 <xsl:template match="*"> 182 <xsl:copy> 183 <xsl:apply-templates/> 184 </xsl:copy> 185 </xsl:template> 186 </xsl:stylesheet>''') 187 188 st = etree.XSLT(style) 189 res = st(tree) 190 self.assertEquals('''\ 191 <?xml version="1.0"?> 192 <a><b>*B*</b><c>*C*</c></a> 193 ''', 194 str(res))
195 196 if etree.LIBXSLT_VERSION >= (1,1,21):
198 tree = self.parse('<a><b>B</b><c>C</c></a>') 199 style = self.parse('''\ 200 <xsl:stylesheet version = "1.0" 201 xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 202 xmlns:str="http://exslt.org/strings" 203 extension-element-prefixes="str"> 204 205 <xsl:template match="/"> 206 <h1 class="{str:replace('abc', 'b', 'x')}">test</h1> 207 </xsl:template> 208 209 </xsl:stylesheet>''') 210 211 st = etree.XSLT(style) 212 res = st(tree) 213 self.assertEquals('''\ 214 <?xml version="1.0"?> 215 <h1 class="axc">test</h1> 216 ''', 217 str(res))
218
219 - def test_exslt_math(self):
220 tree = self.parse('<a><b>B</b><c>C</c></a>') 221 style = self.parse('''\ 222 <xsl:stylesheet version="1.0" 223 xmlns:math="http://exslt.org/math" 224 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 225 exclude-result-prefixes="math xsl"> 226 <xsl:template match="*"> 227 <xsl:copy> 228 <xsl:attribute name="pi"> 229 <xsl:value-of select="math:constant('PI', count(*)+2)"/> 230 </xsl:attribute> 231 <xsl:apply-templates/> 232 </xsl:copy> 233 </xsl:template> 234 </xsl:stylesheet>''') 235 236 st = etree.XSLT(style) 237 res = st(tree) 238 self.assertEquals('''\ 239 <?xml version="1.0"?> 240 <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a> 241 ''', 242 str(res))
243
244 - def test_xslt_input(self):
245 style = self.parse('''\ 246 <xsl:stylesheet version="1.0" 247 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 248 <xsl:template match="*" /> 249 <xsl:template match="/"> 250 <foo><xsl:value-of select="/a/b/text()" /></foo> 251 </xsl:template> 252 </xsl:stylesheet>''') 253 254 st = etree.XSLT(style) 255 st = etree.XSLT(style.getroot())
256
258 style = self.parse('''\ 259 <otherroot> 260 <xsl:stylesheet version="1.0" 261 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 262 <xsl:template match="*" /> 263 <xsl:template match="/"> 264 <foo><xsl:value-of select="/a/b/text()" /></foo> 265 </xsl:template> 266 </xsl:stylesheet> 267 </otherroot>''') 268 269 self.assertRaises(etree.XSLTParseError, etree.XSLT, style) 270 root_node = style.getroot() 271 self.assertRaises(etree.XSLTParseError, etree.XSLT, root_node) 272 st = etree.XSLT(root_node[0])
273
274 - def test_xslt_broken(self):
275 tree = self.parse('<a/>') 276 style = self.parse('''\ 277 <xsl:stylesheet version="1.0" 278 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 279 <xsl:foo /> 280 </xsl:stylesheet>''') 281 self.assertRaises(etree.XSLTParseError, 282 etree.XSLT, style)
283
284 - def test_xslt_parameters(self):
285 tree = self.parse('<a><b>B</b><c>C</c></a>') 286 style = self.parse('''\ 287 <xsl:stylesheet version="1.0" 288 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 289 <xsl:template match="/"> 290 <foo><xsl:value-of select="$bar" /></foo> 291 </xsl:template> 292 </xsl:stylesheet>''') 293 294 st = etree.XSLT(style) 295 res = st(tree, bar="'Bar'") 296 self.assertEquals('''\ 297 <?xml version="1.0"?> 298 <foo>Bar</foo> 299 ''', 300 str(res))
301 302 if etree.LIBXSLT_VERSION < (1,1,18): 303 # later versions produce no error
305 # apply() without needed parameter will lead to XSLTApplyError 306 tree = self.parse('<a><b>B</b><c>C</c></a>') 307 style = self.parse('''\ 308 <xsl:stylesheet version="1.0" 309 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 310 <xsl:template match="/"> 311 <foo><xsl:value-of select="$bar" /></foo> 312 </xsl:template> 313 </xsl:stylesheet>''') 314 315 st = etree.XSLT(style) 316 self.assertRaises(etree.XSLTApplyError, 317 st.apply, tree)
318
320 tree = self.parse('<a><b>B</b><c>C</c></a>') 321 style = self.parse('''\ 322 <xsl:stylesheet version="1.0" 323 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 324 <xsl:template match="*" /> 325 <xsl:template match="/"> 326 <foo><xsl:value-of select="$bar" /></foo> 327 <foo><xsl:value-of select="$baz" /></foo> 328 </xsl:template> 329 </xsl:stylesheet>''') 330 331 st = etree.XSLT(style) 332 res = st(tree, bar="'Bar'", baz="'Baz'") 333 self.assertEquals('''\ 334 <?xml version="1.0"?> 335 <foo>Bar</foo><foo>Baz</foo> 336 ''', 337 str(res))
338
339 - def test_xslt_parameter_xpath(self):
340 tree = self.parse('<a><b>B</b><c>C</c></a>') 341 style = self.parse('''\ 342 <xsl:stylesheet version="1.0" 343 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 344 <xsl:template match="*" /> 345 <xsl:template match="/"> 346 <foo><xsl:value-of select="$bar" /></foo> 347 </xsl:template> 348 </xsl:stylesheet>''') 349 350 st = etree.XSLT(style) 351 res = st(tree, bar="/a/b/text()") 352 self.assertEquals('''\ 353 <?xml version="1.0"?> 354 <foo>B</foo> 355 ''', 356 str(res))
357 358
360 tree = self.parse('<a><b>B</b><c>C</c></a>') 361 style = self.parse('''\ 362 <xsl:stylesheet version="1.0" 363 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 364 <xsl:param name="bar" select="'Default'" /> 365 <xsl:template match="*" /> 366 <xsl:template match="/"> 367 <foo><xsl:value-of select="$bar" /></foo> 368 </xsl:template> 369 </xsl:stylesheet>''') 370 371 st = etree.XSLT(style) 372 res = st(tree, bar="'Bar'") 373 self.assertEquals('''\ 374 <?xml version="1.0"?> 375 <foo>Bar</foo> 376 ''', 377 str(res)) 378 res = st(tree) 379 self.assertEquals('''\ 380 <?xml version="1.0"?> 381 <foo>Default</foo> 382 ''', 383 str(res))
384
385 - def test_xslt_html_output(self):
386 tree = self.parse('<a><b>B</b><c>C</c></a>') 387 style = self.parse('''\ 388 <xsl:stylesheet version="1.0" 389 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 390 <xsl:output method="html"/> 391 <xsl:strip-space elements="*"/> 392 <xsl:template match="/"> 393 <html><body><xsl:value-of select="/a/b/text()" /></body></html> 394 </xsl:template> 395 </xsl:stylesheet>''') 396 397 st = etree.XSLT(style) 398 res = st(tree) 399 self.assertEquals('''<html><body>B</body></html>''', 400 str(res).strip())
401
402 - def test_xslt_include(self):
403 tree = etree.parse(fileInTestDir('test1.xslt')) 404 st = etree.XSLT(tree)
405
407 f = open(fileInTestDir('test1.xslt'), 'r') 408 tree = etree.parse(f) 409 f.close() 410 st = etree.XSLT(tree)
411
413 xml = '<a/>' 414 xslt = '''\ 415 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 416 <xsl:template match="/"> 417 <response>Some text</response> 418 </xsl:template> 419 </xsl:stylesheet> 420 ''' 421 source = self.parse(xml) 422 styledoc = self.parse(xslt) 423 style = etree.XSLT(styledoc) 424 result = style(source) 425 426 etree.tostring(result.getroot()) 427 428 source = self.parse(xml) 429 styledoc = self.parse(xslt) 430 style = etree.XSLT(styledoc) 431 result = style(source) 432 433 etree.tostring(result.getroot())
434
435 - def test_xslt_repeat_transform(self):
436 xml = '<a/>' 437 xslt = '''\ 438 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 439 <xsl:template match="/"> 440 <response>Some text</response> 441 </xsl:template> 442 </xsl:stylesheet> 443 ''' 444 source = self.parse(xml) 445 styledoc = self.parse(xslt) 446 transform = etree.XSLT(styledoc) 447 result = transform(source) 448 result = transform(source) 449 etree.tostring(result.getroot()) 450 result = transform(source) 451 etree.tostring(result.getroot()) 452 str(result) 453 454 result1 = transform(source) 455 result2 = transform(source) 456 self.assertEquals(str(result1), str(result2)) 457 result = transform(source) 458 str(result)
459
460 - def test_xslt_empty(self):
461 # could segfault if result contains "empty document" 462 xml = '<blah/>' 463 xslt = ''' 464 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 465 <xsl:template match="/" /> 466 </xsl:stylesheet> 467 ''' 468 469 source = self.parse(xml) 470 styledoc = self.parse(xslt) 471 style = etree.XSLT(styledoc) 472 result = style(source) 473 self.assertEqual('', str(result))
474
475 - def test_xslt_message(self):
476 xml = '<blah/>' 477 xslt = ''' 478 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 479 <xsl:template match="/"> 480 <xsl:message>TEST TEST TEST</xsl:message> 481 </xsl:template> 482 </xsl:stylesheet> 483 ''' 484 485 source = self.parse(xml) 486 styledoc = self.parse(xslt) 487 style = etree.XSLT(styledoc) 488 result = style(source) 489 self.assertEqual('', str(result)) 490 self.assert_("TEST TEST TEST" in [entry.message 491 for entry in style.error_log])
492
494 xml = '<blah/>' 495 xslt = ''' 496 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 497 <xsl:template match="/"> 498 <xsl:message terminate="yes">TEST TEST TEST</xsl:message> 499 </xsl:template> 500 </xsl:stylesheet> 501 ''' 502 503 source = self.parse(xml) 504 styledoc = self.parse(xslt) 505 style = etree.XSLT(styledoc) 506 result = style(source) 507 self.assertEqual('', str(result)) 508 self.assert_("TEST TEST TEST" in [entry.message 509 for entry in style.error_log])
510
511 - def test_xslt_shortcut(self):
512 tree = self.parse('<a><b>B</b><c>C</c></a>') 513 style = self.parse('''\ 514 <xsl:stylesheet version="1.0" 515 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 516 <xsl:template match="*" /> 517 <xsl:template match="/"> 518 <doc> 519 <foo><xsl:value-of select="$bar" /></foo> 520 <foo><xsl:value-of select="$baz" /></foo> 521 </doc> 522 </xsl:template> 523 </xsl:stylesheet>''') 524 525 result = tree.xslt(style, bar="'Bar'", baz="'Baz'") 526 self.assertEquals( 527 '<doc><foo>Bar</foo><foo>Baz</foo></doc>', 528 etree.tostring(result.getroot()))
529
530 - def test_multiple_elementrees(self):
531 tree = self.parse('<a><b>B</b><c>C</c></a>') 532 style = self.parse('''\ 533 <xsl:stylesheet version="1.0" 534 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 535 <xsl:template match="a"><A><xsl:apply-templates/></A></xsl:template> 536 <xsl:template match="b"><B><xsl:apply-templates/></B></xsl:template> 537 <xsl:template match="c"><C><xsl:apply-templates/></C></xsl:template> 538 </xsl:stylesheet>''') 539 540 self.assertEquals(self._rootstring(tree), 541 '<a><b>B</b><c>C</c></a>') 542 result = tree.xslt(style) 543 self.assertEquals(self._rootstring(tree), 544 '<a><b>B</b><c>C</c></a>') 545 self.assertEquals(self._rootstring(result), 546 '<A><B>B</B><C>C</C></A>') 547 548 b_tree = etree.ElementTree(tree.getroot()[0]) 549 self.assertEquals(self._rootstring(b_tree), 550 '<b>B</b>') 551 result = b_tree.xslt(style) 552 self.assertEquals(self._rootstring(tree), 553 '<a><b>B</b><c>C</c></a>') 554 self.assertEquals(self._rootstring(result), 555 '<B>B</B>') 556 557 c_tree = etree.ElementTree(tree.getroot()[1]) 558 self.assertEquals(self._rootstring(c_tree), 559 '<c>C</c>') 560 result = c_tree.xslt(style) 561 self.assertEquals(self._rootstring(tree), 562 '<a><b>B</b><c>C</c></a>') 563 self.assertEquals(self._rootstring(result), 564 '<C>C</C>')
565
566 - def test_extensions1(self):
567 tree = self.parse('<a><b>B</b></a>') 568 style = self.parse('''\ 569 <xsl:stylesheet version="1.0" 570 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 571 xmlns:myns="testns" 572 exclude-result-prefixes="myns"> 573 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template> 574 </xsl:stylesheet>''') 575 576 def mytext(ctxt, values): 577 return 'X' * len(values)
578 579 result = tree.xslt(style, {('testns', 'mytext') : mytext}) 580 self.assertEquals(self._rootstring(result), 581 '<A>X</A>')
582
583 - def test_extensions2(self):
584 tree = self.parse('<a><b>B</b></a>') 585 style = self.parse('''\ 586 <xsl:stylesheet version="1.0" 587 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 588 xmlns:myns="testns" 589 exclude-result-prefixes="myns"> 590 <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template> 591 </xsl:stylesheet>''') 592 593 def mytext(ctxt, values): 594 return 'X' * len(values)
595 596 namespace = etree.FunctionNamespace('testns') 597 namespace['mytext'] = mytext 598 599 result = tree.xslt(style) 600 self.assertEquals(self._rootstring(result), 601 '<A>X</A>') 602
603 - def test_extension_element(self):
604 tree = self.parse('<a><b>B</b></a>') 605 style = self.parse('''\ 606 <xsl:stylesheet version="1.0" 607 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 608 xmlns:myns="testns" 609 extension-element-prefixes="myns" 610 exclude-result-prefixes="myns"> 611 <xsl:template match="a"> 612 <A><myns:myext>b</myns:myext></A> 613 </xsl:template> 614 </xsl:stylesheet>''') 615 616 class MyExt(etree.XSLTExtension): 617 def execute(self, context, self_node, input_node, output_parent): 618 child = etree.Element(self_node.text) 619 child.text = 'X' 620 output_parent.append(child)
621 622 extensions = { ('testns', 'myext') : MyExt() } 623 624 result = tree.xslt(style, extensions=extensions) 625 self.assertEquals(self._rootstring(result), 626 '<A><b>X</b></A>') 627
628 - def test_extension_element_content(self):
629 tree = self.parse('<a><b>B</b></a>') 630 style = self.parse('''\ 631 <xsl:stylesheet version="1.0" 632 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 633 xmlns:myns="testns" 634 extension-element-prefixes="myns"> 635 <xsl:template match="a"> 636 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 637 </xsl:template> 638 </xsl:stylesheet>''') 639 640 class MyExt(etree.XSLTExtension): 641 def execute(self, context, self_node, input_node, output_parent): 642 output_parent.extend(list(self_node)[1:])
643 644 extensions = { ('testns', 'myext') : MyExt() } 645 646 result = tree.xslt(style, extensions=extensions) 647 self.assertEquals(self._rootstring(result), 648 '<A><y>Y</y><z/></A>') 649
650 - def test_extension_element_apply_templates(self):
651 tree = self.parse('<a><b>B</b></a>') 652 style = self.parse('''\ 653 <xsl:stylesheet version="1.0" 654 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 655 xmlns:myns="testns" 656 extension-element-prefixes="myns"> 657 <xsl:template match="a"> 658 <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 659 </xsl:template> 660 <xsl:template match="x" /> 661 <xsl:template match="z">XYZ</xsl:template> 662 </xsl:stylesheet>''') 663 664 class MyExt(etree.XSLTExtension): 665 def execute(self, context, self_node, input_node, output_parent): 666 for child in self_node: 667 for result in self.apply_templates(context, child): 668 if isinstance(result, basestring): 669 el = etree.Element("T") 670 el.text = result 671 else: 672 el = result 673 output_parent.append(el)
674 675 extensions = { ('testns', 'myext') : MyExt() } 676 677 result = tree.xslt(style, extensions=extensions) 678 self.assertEquals(self._rootstring(result), 679 '<A><T>Y</T><T>XYZ</T></A>') 680
681 - def test_extension_element_raise(self):
682 tree = self.parse('<a><b>B</b></a>') 683 style = self.parse('''\ 684 <xsl:stylesheet version="1.0" 685 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 686 xmlns:myns="testns" 687 extension-element-prefixes="myns" 688 exclude-result-prefixes="myns"> 689 <xsl:template match="a"> 690 <A><myns:myext>b</myns:myext></A> 691 </xsl:template> 692 </xsl:stylesheet>''') 693 694 class MyError(Exception): 695 pass
696 697 class MyExt(etree.XSLTExtension): 698 def execute(self, context, self_node, input_node, output_parent): 699 raise MyError("expected!") 700 701 extensions = { ('testns', 'myext') : MyExt() } 702 self.assertRaises(MyError, tree.xslt, style, extensions=extensions) 703
704 - def test_xslt_document_XML(self):
705 # make sure document('') works from parsed strings 706 xslt = etree.XSLT(etree.XML("""\ 707 <xsl:stylesheet version="1.0" 708 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 709 <xsl:template match="/"> 710 <test>TEXT<xsl:copy-of select="document('')//test"/></test> 711 </xsl:template> 712 </xsl:stylesheet> 713 """)) 714 result = xslt(etree.XML('<a/>')) 715 root = result.getroot() 716 self.assertEquals(root.tag, 717 'test') 718 self.assertEquals(root[0].tag, 719 'test') 720 self.assertEquals(root[0].text, 721 'TEXT') 722 self.assertEquals(root[0][0].tag, 723 '{http://www.w3.org/1999/XSL/Transform}copy-of')
724
725 - def test_xslt_document_parse(self):
726 # make sure document('') works from loaded files 727 xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt"))) 728 result = xslt(etree.XML('<a/>')) 729 root = result.getroot() 730 self.assertEquals(root.tag, 731 'test') 732 self.assertEquals(root[0].tag, 733 '{http://www.w3.org/1999/XSL/Transform}stylesheet')
734
735 - def test_xslt_document_elementtree(self):
736 # make sure document('') works from loaded files 737 xslt = etree.XSLT(etree.ElementTree(file=fileInTestDir("test-document.xslt"))) 738 result = xslt(etree.XML('<a/>')) 739 root = result.getroot() 740 self.assertEquals(root.tag, 741 'test') 742 self.assertEquals(root[0].tag, 743 '{http://www.w3.org/1999/XSL/Transform}stylesheet')
744
745 - def test_xslt_document_error(self):
746 xslt = etree.XSLT(etree.XML("""\ 747 <xsl:stylesheet version="1.0" 748 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 749 <xsl:template match="/"> 750 <test>TEXT<xsl:copy-of select="document('uri:__junkfood__is__evil__')//test"/></test> 751 </xsl:template> 752 </xsl:stylesheet> 753 """)) 754 self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
755
756 - def test_xslt_document_XML_resolver(self):
757 # make sure document('') works when custom resolvers are in use 758 assertEquals = self.assertEquals 759 called = {'count' : 0} 760 class TestResolver(etree.Resolver): 761 def resolve(self, url, id, context): 762 assertEquals(url, 'file://ANYTHING') 763 called['count'] += 1 764 return self.resolve_string('<CALLED/>', context)
765 766 parser = etree.XMLParser() 767 parser.resolvers.add(TestResolver()) 768 769 xslt = etree.XSLT(etree.XML("""\ 770 <xsl:stylesheet version="1.0" 771 xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 772 xmlns:l="local"> 773 <xsl:template match="/"> 774 <test> 775 <xsl:for-each select="document('')//l:data/l:entry"> 776 <xsl:copy-of select="document('file://ANYTHING')"/> 777 <xsl:copy> 778 <xsl:attribute name="value"> 779 <xsl:value-of select="."/> 780 </xsl:attribute> 781 </xsl:copy> 782 </xsl:for-each> 783 </test> 784 </xsl:template> 785 <l:data> 786 <l:entry>A</l:entry> 787 <l:entry>B</l:entry> 788 </l:data> 789 </xsl:stylesheet> 790 """, parser)) 791 792 self.assertEquals(called['count'], 0) 793 result = xslt(etree.XML('<a/>')) 794 self.assertEquals(called['count'], 1) 795 796 root = result.getroot() 797 self.assertEquals(root.tag, 798 'test') 799 self.assertEquals(len(root), 4) 800 801 self.assertEquals(root[0].tag, 802 'CALLED') 803 self.assertEquals(root[1].tag, 804 '{local}entry') 805 self.assertEquals(root[1].text, 806 None) 807 self.assertEquals(root[1].get("value"), 808 'A') 809 self.assertEquals(root[2].tag, 810 'CALLED') 811 self.assertEquals(root[3].tag, 812 '{local}entry') 813 self.assertEquals(root[3].text, 814 None) 815 self.assertEquals(root[3].get("value"), 816 'B') 817
818 - def test_xslt_document_parse_allow(self):
819 access_control = etree.XSLTAccessControl(read_file=True) 820 xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")), 821 access_control = access_control) 822 result = xslt(etree.XML('<a/>')) 823 root = result.getroot() 824 self.assertEquals(root.tag, 825 'test') 826 self.assertEquals(root[0].tag, 827 '{http://www.w3.org/1999/XSL/Transform}stylesheet')
828
829 - def test_xslt_document_parse_deny(self):
830 access_control = etree.XSLTAccessControl(read_file=False) 831 xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")), 832 access_control = access_control) 833 self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
834
835 - def test_xslt_document_parse_deny_all(self):
836 access_control = etree.XSLTAccessControl.DENY_ALL 837 xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")), 838 access_control = access_control) 839 self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
840
841 - def test_xslt_move_result(self):
842 root = etree.XML('''\ 843 <transform> 844 <widget displayType="fieldset"/> 845 </transform>''') 846 847 xslt = etree.XSLT(etree.XML('''\ 848 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 849 <xsl:output method="html" indent="no"/> 850 <xsl:template match="/"> 851 <html> 852 <xsl:apply-templates/> 853 </html> 854 </xsl:template> 855 856 <xsl:template match="widget"> 857 <xsl:element name="{@displayType}"/> 858 </xsl:template> 859 860 </xsl:stylesheet>''')) 861 862 result = xslt(root[0]) 863 root[:] = result.getroot()[:] 864 del root # segfaulted before
865
866 - def test_xslt_pi(self):
867 tree = self.parse('''\ 868 <?xml version="1.0"?> 869 <?xml-stylesheet type="text/xsl" href="%s"?> 870 <a> 871 <b>B</b> 872 <c>C</c> 873 </a>''' % fileInTestDir("test1.xslt")) 874 875 style_root = tree.getroot().getprevious().parseXSL().getroot() 876 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet", 877 style_root.tag)
878
879 - def test_xslt_pi_embedded_xmlid(self):
880 # test xml:id dictionary lookup mechanism 881 tree = self.parse('''\ 882 <?xml version="1.0"?> 883 <?xml-stylesheet type="text/xsl" href="#style"?> 884 <a> 885 <b>B</b> 886 <c>C</c> 887 <xsl:stylesheet version="1.0" xml:id="style" 888 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 889 <xsl:template match="*" /> 890 <xsl:template match="/"> 891 <foo><xsl:value-of select="/a/b/text()" /></foo> 892 </xsl:template> 893 </xsl:stylesheet> 894 </a>''') 895 896 style_root = tree.getroot().getprevious().parseXSL().getroot() 897 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet", 898 style_root.tag) 899 900 st = etree.XSLT(style_root) 901 res = st(tree) 902 self.assertEquals('''\ 903 <?xml version="1.0"?> 904 <foo>B</foo> 905 ''', 906 str(res))
907
908 - def test_xslt_pi_embedded_id(self):
909 # test XPath lookup mechanism 910 tree = self.parse('''\ 911 <?xml version="1.0"?> 912 <?xml-stylesheet type="text/xsl" href="#style"?> 913 <a> 914 <b>B</b> 915 <c>C</c> 916 </a>''') 917 918 style = self.parse('''\ 919 <xsl:stylesheet version="1.0" xml:id="style" 920 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 921 <xsl:template match="*" /> 922 <xsl:template match="/"> 923 <foo><xsl:value-of select="/a/b/text()" /></foo> 924 </xsl:template> 925 </xsl:stylesheet> 926 ''') 927 928 tree.getroot().append(style.getroot()) 929 930 style_root = tree.getroot().getprevious().parseXSL().getroot() 931 self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet", 932 style_root.tag) 933 934 st = etree.XSLT(style_root) 935 res = st(tree) 936 self.assertEquals('''\ 937 <?xml version="1.0"?> 938 <foo>B</foo> 939 ''', 940 str(res))
941
942 - def test_xslt_pi_get(self):
943 tree = self.parse('''\ 944 <?xml version="1.0"?> 945 <?xml-stylesheet type="text/xsl" href="TEST"?> 946 <a> 947 <b>B</b> 948 <c>C</c> 949 </a>''') 950 951 pi = tree.getroot().getprevious() 952 self.assertEquals("TEST", pi.get("href"))
953
954 - def test_xslt_pi_get_all(self):
955 tree = self.parse('''\ 956 <?xml version="1.0"?> 957 <?xml-stylesheet type="text/xsl" href="TEST"?> 958 <a> 959 <b>B</b> 960 <c>C</c> 961 </a>''') 962 963 pi = tree.getroot().getprevious() 964 self.assertEquals("TEST", pi.get("href")) 965 self.assertEquals("text/xsl", pi.get("type")) 966 self.assertEquals(None, pi.get("motz"))
967
968 - def test_xslt_pi_get_all_reversed(self):
969 tree = self.parse('''\ 970 <?xml version="1.0"?> 971 <?xml-stylesheet href="TEST" type="text/xsl"?> 972 <a> 973 <b>B</b> 974 <c>C</c> 975 </a>''') 976 977 pi = tree.getroot().getprevious() 978 self.assertEquals("TEST", pi.get("href")) 979 self.assertEquals("text/xsl", pi.get("type")) 980 self.assertEquals(None, pi.get("motz"))
981
982 - def test_xslt_pi_get_unknown(self):
983 tree = self.parse('''\ 984 <?xml version="1.0"?> 985 <?xml-stylesheet type="text/xsl" href="TEST"?> 986 <a> 987 <b>B</b> 988 <c>C</c> 989 </a>''') 990 991 pi = tree.getroot().getprevious() 992 self.assertEquals(None, pi.get("unknownattribute"))
993
994 - def test_xslt_pi_set_replace(self):
995 tree = self.parse('''\ 996 <?xml version="1.0"?> 997 <?xml-stylesheet type="text/xsl" href="TEST"?> 998 <a> 999 <b>B</b> 1000 <c>C</c> 1001 </a>''') 1002 1003 pi = tree.getroot().getprevious() 1004 self.assertEquals("TEST", pi.get("href")) 1005 1006 pi.set("href", "TEST123") 1007 self.assertEquals("TEST123", pi.get("href"))
1008
1009 - def test_xslt_pi_set_new(self):
1010 tree = self.parse('''\ 1011 <?xml version="1.0"?> 1012 <?xml-stylesheet type="text/xsl"?> 1013 <a> 1014 <b>B</b> 1015 <c>C</c> 1016 </a>''') 1017 1018 pi = tree.getroot().getprevious() 1019 self.assertEquals(None, pi.get("href")) 1020 1021 pi.set("href", "TEST") 1022 self.assertEquals("TEST", pi.get("href"))
1023
1024 - def test_exslt_regexp_test(self):
1025 xslt = etree.XSLT(etree.XML("""\ 1026 <xsl:stylesheet version="1.0" 1027 xmlns:regexp="http://exslt.org/regular-expressions" 1028 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1029 <xsl:template match="*"> 1030 <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test> 1031 </xsl:template> 1032 </xsl:stylesheet> 1033 """)) 1034 result = xslt(etree.XML('<a><b>123</b><b>098</b><b>987</b></a>')) 1035 root = result.getroot() 1036 self.assertEquals(root.tag, 1037 'test') 1038 self.assertEquals(len(root), 1) 1039 self.assertEquals(root[0].tag, 1040 'b') 1041 self.assertEquals(root[0].text, 1042 '987')
1043
1044 - def test_exslt_regexp_replace(self):
1045 xslt = etree.XSLT(etree.XML("""\ 1046 <xsl:stylesheet version="1.0" 1047 xmlns:regexp="http://exslt.org/regular-expressions" 1048 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1049 <xsl:template match="*"> 1050 <test> 1051 <xsl:copy-of select="regexp:replace(string(.), 'd.', '', 'XX')"/> 1052 <xsl:text>-</xsl:text> 1053 <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/> 1054 </test> 1055 </xsl:template> 1056 </xsl:stylesheet> 1057 """)) 1058 result = xslt(etree.XML('<a>abdCdEeDed</a>')) 1059 root = result.getroot() 1060 self.assertEquals(root.tag, 1061 'test') 1062 self.assertEquals(len(root), 0) 1063 self.assertEquals(root.text, 'abXXdEeDed-abXXXXeXXd')
1064
1065 - def test_exslt_regexp_match(self):
1066 xslt = etree.XSLT(etree.XML("""\ 1067 <xsl:stylesheet version="1.0" 1068 xmlns:regexp="http://exslt.org/regular-expressions" 1069 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1070 <xsl:template match="*"> 1071 <test> 1072 <test1><xsl:copy-of select="regexp:match(string(.), 'd.')"/></test1> 1073 <test2><xsl:copy-of select="regexp:match(string(.), 'd.', 'g')"/></test2> 1074 <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i> 1075 </test> 1076 </xsl:template> 1077 </xsl:stylesheet> 1078 """)) 1079 result = xslt(etree.XML('<a>abdCdEeDed</a>')) 1080 root = result.getroot() 1081 self.assertEquals(root.tag, 'test') 1082 self.assertEquals(len(root), 3) 1083 1084 self.assertEquals(len(root[0]), 1) 1085 self.assertEquals(root[0][0].tag, 'match') 1086 self.assertEquals(root[0][0].text, 'dC') 1087 1088 self.assertEquals(len(root[1]), 2) 1089 self.assertEquals(root[1][0].tag, 'match') 1090 self.assertEquals(root[1][0].text, 'dC') 1091 self.assertEquals(root[1][1].tag, 'match') 1092 self.assertEquals(root[1][1].text, 'dE') 1093 1094 self.assertEquals(len(root[2]), 3) 1095 self.assertEquals(root[2][0].tag, 'match') 1096 self.assertEquals(root[2][0].text, 'dC') 1097 self.assertEquals(root[2][1].tag, 'match') 1098 self.assertEquals(root[2][1].text, 'dE') 1099 self.assertEquals(root[2][2].tag, 'match') 1100 self.assertEquals(root[2][2].text, 'De')
1101
1102 - def test_exslt_regexp_match_groups(self):
1103 xslt = etree.XSLT(etree.XML("""\ 1104 <xsl:stylesheet version="1.0" 1105 xmlns:regexp="http://exslt.org/regular-expressions" 1106 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1107 <xsl:template match="/"> 1108 <test> 1109 <xsl:for-each select="regexp:match( 1110 '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )"> 1111 <test1><xsl:value-of select="."/></test1> 1112 </xsl:for-each> 1113 </test> 1114 </xsl:template> 1115 </xsl:stylesheet> 1116 """)) 1117 result = xslt(etree.XML('<a/>')) 1118 root = result.getroot() 1119 self.assertEquals(root.tag, 'test') 1120 self.assertEquals(len(root), 4) 1121 1122 self.assertEquals(root[0].text, "123abc567") 1123 self.assertEquals(root[1].text, "123") 1124 self.assertEquals(root[2].text, "abc") 1125 self.assertEquals(root[3].text, "567")
1126
1127 - def test_exslt_regexp_match1(self):
1128 # taken from http://www.exslt.org/regexp/functions/match/index.html 1129 xslt = etree.XSLT(etree.XML("""\ 1130 <xsl:stylesheet version="1.0" 1131 xmlns:regexp="http://exslt.org/regular-expressions" 1132 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1133 <xsl:template match="/"> 1134 <test> 1135 <xsl:for-each select="regexp:match( 1136 'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml', 1137 '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')"> 1138 <test1><xsl:value-of select="."/></test1> 1139 </xsl:for-each> 1140 </test> 1141 </xsl:template> 1142 </xsl:stylesheet> 1143 """)) 1144 result = xslt(etree.XML('<a/>')) 1145 root = result.getroot() 1146 self.assertEquals(root.tag, 'test') 1147 self.assertEquals(len(root), 5) 1148 1149 self.assertEquals( 1150 root[0].text, 1151 "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml") 1152 self.assertEquals( 1153 root[1].text, 1154 "http") 1155 self.assertEquals( 1156 root[2].text, 1157 "www.bayes.co.uk") 1158 self.assertFalse(root[3].text) 1159 self.assertEquals( 1160 root[4].text, 1161 "/xml/index.xml?/xml/utils/rechecker.xml")
1162
1163 - def test_exslt_regexp_match2(self):
1164 # taken from http://www.exslt.org/regexp/functions/match/index.html 1165 xslt = etree.XSLT(etree.XML("""\ 1166 <xsl:stylesheet version="1.0" 1167 xmlns:regexp="http://exslt.org/regular-expressions" 1168 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1169 <xsl:template match="/"> 1170 <test> 1171 <xsl:for-each select="regexp:match( 1172 'This is a test string', '(\w+)', 'g')"> 1173 <test1><xsl:value-of select="."/></test1> 1174 </xsl:for-each> 1175 </test> 1176 </xsl:template> 1177 </xsl:stylesheet> 1178 """)) 1179 result = xslt(etree.XML('<a/>')) 1180 root = result.getroot() 1181 self.assertEquals(root.tag, 'test') 1182 self.assertEquals(len(root), 5) 1183 1184 self.assertEquals(root[0].text, "This") 1185 self.assertEquals(root[1].text, "is") 1186 self.assertEquals(root[2].text, "a") 1187 self.assertEquals(root[3].text, "test") 1188 self.assertEquals(root[4].text, "string")
1189
1190 - def _test_exslt_regexp_match3(self):
1191 # taken from http://www.exslt.org/regexp/functions/match/index.html 1192 # THIS IS NOT SUPPORTED! 1193 xslt = etree.XSLT(etree.XML("""\ 1194 <xsl:stylesheet version="1.0" 1195 xmlns:regexp="http://exslt.org/regular-expressions" 1196 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1197 <xsl:template match="/"> 1198 <test> 1199 <xsl:for-each select="regexp:match( 1200 'This is a test string', '([a-z])+ ', 'g')"> 1201 <test1><xsl:value-of select="."/></test1> 1202 </xsl:for-each> 1203 </test> 1204 </xsl:template> 1205 </xsl:stylesheet> 1206 """)) 1207 result = xslt(etree.XML('<a/>')) 1208 root = result.getroot() 1209 self.assertEquals(root.tag, 'test') 1210 self.assertEquals(len(root), 4) 1211 1212 self.assertEquals(root[0].text, "his") 1213 self.assertEquals(root[1].text, "is") 1214 self.assertEquals(root[2].text, "a") 1215 self.assertEquals(root[3].text, "test")
1216
1217 - def _test_exslt_regexp_match4(self):
1218 # taken from http://www.exslt.org/regexp/functions/match/index.html 1219 # THIS IS NOT SUPPORTED! 1220 xslt = etree.XSLT(etree.XML("""\ 1221 <xsl:stylesheet version="1.0" 1222 xmlns:regexp="http://exslt.org/regular-expressions" 1223 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 1224 <xsl:template match="/"> 1225 <test> 1226 <xsl:for-each select="regexp:match( 1227 'This is a test string', '([a-z])+ ', 'gi')"> 1228 <test1><xsl:value-of select="."/></test1> 1229 </xsl:for-each> 1230 </test> 1231 </xsl:template> 1232 </xsl:stylesheet> 1233 """)) 1234 result = xslt(etree.XML('<a/>')) 1235 root = result.getroot() 1236 self.assertEquals(root.tag, 'test') 1237 self.assertEquals(len(root), 4) 1238 1239 self.assertEquals(root[0].text, "This") 1240 self.assertEquals(root[1].text, "is") 1241 self.assertEquals(root[2].text, "a") 1242 self.assertEquals(root[3].text, "test")
1243
1244 -def test_suite():
1245 suite = unittest.TestSuite() 1246 suite.addTests([unittest.makeSuite(ETreeXSLTTestCase)]) 1247 suite.addTests( 1248 [doctest.DocFileSuite('../../../doc/extensions.txt')]) 1249 suite.addTests( 1250 [doctest.DocFileSuite('../../../doc/xpathxslt.txt')]) 1251 return suite
1252 1253 if __name__ == '__main__': 1254 print 'to test use test.py %s' % __file__ 1255