1   
   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)  
  12   
  13  is_python3 = sys.version_info[0] >= 3 
  14   
  15  try: 
  16      unicode 
  17  except NameError:  
  18      unicode = str 
  19   
  20  try: 
  21      basestring 
  22  except NameError:  
  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   
  29      """XSLT tests etree""" 
  30           
  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.assertEqual('''\ 
  45  <?xml version="1.0"?> 
  46  <foo>B</foo> 
  47  ''', 
  48                            str(res)) 
   49   
  52   
  55   
  56      if False and etree.LIBXSLT_VERSION >= (1,1,15): 
  57           
  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           
  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.assertEqual('''\ 
  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.assertEqual('''\ 
  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.assertEqual('''\ 
  99  <?xml version="1.0"?> 
 100  <foo>B</foo> 
 101  ''', 
 102                            str(res)) 
  103   
 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.assertEqual(expected, 
 124                                str(bytes(res), 'UTF-8')) 
 125          else: 
 126              self.assertEqual(expected, 
 127                                unicode(str(res), 'UTF-8')) 
  128   
 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.assertEqual(expected, 
 149                                str(bytes(res), 'UTF-16')) 
 150          else: 
 151              self.assertEqual(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.assertEqual(expected, result) 
  179   
 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.assertEqual(expected, 
 199                            unicode(res)) 
  200   
 202          tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>' 
 203          ).decode("unicode_escape")) 
 204          style = self.parse('''\ 
 205  <xsl:stylesheet version="1.0" 
 206      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 207    <xsl:output encoding="UTF-16" standalone="no"/> 
 208    <xsl:template match="/"> 
 209      <foo><xsl:value-of select="/a/b/text()" /></foo> 
 210    </xsl:template> 
 211  </xsl:stylesheet>''') 
 212   
 213          st = etree.XSLT(style) 
 214          res = st(tree) 
 215          expected = _bytes('''\ 
 216  <?xml version="1.0" standalone="no"?> 
 217  <foo>\\uF8D2</foo> 
 218  ''').decode("unicode_escape") 
 219          self.assertEqual(expected, 
 220                           unicode(res)) 
  221   
 234   
 251   
 253          tree = self.parse('<a/>') 
 254          style = self.parse('''\ 
 255  <xsl:stylesheet version="1.0" 
 256      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 257      <xsl:foo /> 
 258  </xsl:stylesheet>''') 
 259          self.assertRaises(etree.XSLTParseError, 
 260                            etree.XSLT, style) 
  261   
 263          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 264          style = self.parse('''\ 
 265  <xsl:stylesheet version="1.0" 
 266      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 267    <xsl:template match="/"> 
 268      <foo><xsl:value-of select="$bar" /></foo> 
 269    </xsl:template> 
 270  </xsl:stylesheet>''') 
 271   
 272          st = etree.XSLT(style) 
 273          res = st(tree, bar="'Bar'") 
 274          self.assertEqual('''\ 
 275  <?xml version="1.0"?> 
 276  <foo>Bar</foo> 
 277  ''', 
 278                            str(res)) 
  279   
 281          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 282          style = self.parse('''\ 
 283  <xsl:stylesheet version="1.0" 
 284      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 285    <xsl:template match="/"> 
 286      <foo><xsl:value-of select="$bar" /></foo> 
 287    </xsl:template> 
 288  </xsl:stylesheet>''') 
 289   
 290          st = etree.XSLT(style) 
 291          res = st(tree, bar=etree.XSLT.strparam('''it's me, "Bar"''')) 
 292          self.assertEqual('''\ 
 293  <?xml version="1.0"?> 
 294  <foo>it's me, "Bar"</foo> 
 295  ''', 
 296                            str(res)) 
  297   
 299          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 300          style = self.parse('''\ 
 301  <xsl:stylesheet version="1.0" 
 302      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 303    <xsl:param name="bar"/> 
 304    <xsl:template match="/"> 
 305      <foo><xsl:value-of select="$bar" /></foo> 
 306    </xsl:template> 
 307  </xsl:stylesheet>''') 
 308   
 309          st = etree.XSLT(style) 
 310          res = self.assertRaises(etree.XSLTApplyError, 
 311                                  st, tree, bar="<test/>") 
 312          res = self.assertRaises(etree.XSLTApplyError, 
 313                                  st, tree, bar="....") 
  314   
 315      if etree.LIBXSLT_VERSION < (1,1,18): 
 316           
 318               
 319              tree = self.parse('<a><b>B</b><c>C</c></a>') 
 320              style = self.parse('''\ 
 321  <xsl:stylesheet version="1.0" 
 322      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 323    <xsl:template match="/"> 
 324      <foo><xsl:value-of select="$bar" /></foo> 
 325    </xsl:template> 
 326  </xsl:stylesheet>''') 
 327   
 328              st = etree.XSLT(style) 
 329              self.assertRaises(etree.XSLTApplyError, 
 330                                st.apply, tree) 
  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    <xsl:template match="/"> 
 339      <foo><xsl:value-of select="$bar" /></foo> 
 340      <foo><xsl:value-of select="$baz" /></foo> 
 341    </xsl:template> 
 342  </xsl:stylesheet>''') 
 343   
 344          st = etree.XSLT(style) 
 345          res = st(tree, bar="'Bar'", baz="'Baz'") 
 346          self.assertEqual('''\ 
 347  <?xml version="1.0"?> 
 348  <foo>Bar</foo><foo>Baz</foo> 
 349  ''', 
 350                            str(res)) 
  351           
 353          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 354          style = self.parse('''\ 
 355  <xsl:stylesheet version="1.0" 
 356      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 357    <xsl:template match="*" /> 
 358    <xsl:template match="/"> 
 359      <foo><xsl:value-of select="$bar" /></foo> 
 360    </xsl:template> 
 361  </xsl:stylesheet>''') 
 362   
 363          st = etree.XSLT(style) 
 364          res = st(tree, bar="/a/b/text()") 
 365          self.assertEqual('''\ 
 366  <?xml version="1.0"?> 
 367  <foo>B</foo> 
 368  ''', 
 369                            str(res)) 
  370   
 372          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 373          style = self.parse('''\ 
 374  <xsl:stylesheet version="1.0" 
 375      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 376    <xsl:template match="*" /> 
 377    <xsl:template match="/"> 
 378      <foo><xsl:value-of select="$bar" /></foo> 
 379    </xsl:template> 
 380  </xsl:stylesheet>''') 
 381   
 382          st = etree.XSLT(style) 
 383          res = st(tree, bar=etree.XPath("/a/b/text()")) 
 384          self.assertEqual('''\ 
 385  <?xml version="1.0"?> 
 386  <foo>B</foo> 
 387  ''', 
 388                            str(res)) 
  389           
 391          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 392          style = self.parse('''\ 
 393  <xsl:stylesheet version="1.0" 
 394      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 395    <xsl:param name="bar" select="'Default'" /> 
 396    <xsl:template match="*" /> 
 397    <xsl:template match="/"> 
 398      <foo><xsl:value-of select="$bar" /></foo> 
 399    </xsl:template> 
 400  </xsl:stylesheet>''') 
 401   
 402          st = etree.XSLT(style) 
 403          res = st(tree, bar="'Bar'") 
 404          self.assertEqual('''\ 
 405  <?xml version="1.0"?> 
 406  <foo>Bar</foo> 
 407  ''', 
 408                            str(res)) 
 409          res = st(tree) 
 410          self.assertEqual('''\ 
 411  <?xml version="1.0"?> 
 412  <foo>Default</foo> 
 413  ''', 
 414                            str(res)) 
  415           
 417          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 418          style = self.parse('''\ 
 419  <xsl:stylesheet version="1.0" 
 420      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 421    <xsl:output method="html"/> 
 422    <xsl:strip-space elements="*"/> 
 423    <xsl:template match="/"> 
 424      <html><body><xsl:value-of select="/a/b/text()" /></body></html> 
 425    </xsl:template> 
 426  </xsl:stylesheet>''') 
 427   
 428          st = etree.XSLT(style) 
 429          res = st(tree) 
 430          self.assertEqual('<html><body>B</body></html>', 
 431                            str(res).strip()) 
  432   
 436   
 442   
 465   
 490   
 492           
 493          xml = '<blah/>' 
 494          xslt = ''' 
 495          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
 496            <xsl:template match="/" /> 
 497          </xsl:stylesheet> 
 498          ''' 
 499   
 500          source = self.parse(xml) 
 501          styledoc = self.parse(xslt) 
 502          style = etree.XSLT(styledoc) 
 503          result = style(source) 
 504          self.assertEqual('', str(result)) 
  505   
 507          xml = '<blah/>' 
 508          xslt = ''' 
 509          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
 510            <xsl:template match="/"> 
 511              <xsl:message>TEST TEST TEST</xsl:message> 
 512            </xsl:template> 
 513          </xsl:stylesheet> 
 514          ''' 
 515   
 516          source = self.parse(xml) 
 517          styledoc = self.parse(xslt) 
 518          style = etree.XSLT(styledoc) 
 519          result = style(source) 
 520          self.assertEqual('', str(result)) 
 521          self.assertTrue("TEST TEST TEST" in [entry.message 
 522                                            for entry in style.error_log]) 
  523   
 525          xml = '<blah/>' 
 526          xslt = ''' 
 527          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
 528            <xsl:template match="/"> 
 529              <xsl:message terminate="yes">TEST TEST TEST</xsl:message> 
 530            </xsl:template> 
 531          </xsl:stylesheet> 
 532          ''' 
 533   
 534          source = self.parse(xml) 
 535          styledoc = self.parse(xslt) 
 536          style = etree.XSLT(styledoc) 
 537   
 538          self.assertRaises(etree.XSLTApplyError, style, source) 
 539          self.assertTrue("TEST TEST TEST" in [entry.message 
 540                                            for entry in style.error_log]) 
  541   
 543          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 544          style = self.parse('''\ 
 545  <xsl:stylesheet version="1.0" 
 546      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 547    <xsl:template match="*" /> 
 548    <xsl:template match="/"> 
 549      <doc> 
 550      <foo><xsl:value-of select="$bar" /></foo> 
 551      <foo><xsl:value-of select="$baz" /></foo> 
 552      </doc> 
 553    </xsl:template> 
 554  </xsl:stylesheet>''') 
 555   
 556          result = tree.xslt(style, bar="'Bar'", baz="'Baz'") 
 557          self.assertEqual( 
 558              _bytes('<doc><foo>Bar</foo><foo>Baz</foo></doc>'), 
 559              etree.tostring(result.getroot())) 
  560           
 562          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 563          style = self.parse('''\ 
 564  <xsl:stylesheet version="1.0" 
 565      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 566    <xsl:template match="a"><A><xsl:apply-templates/></A></xsl:template> 
 567    <xsl:template match="b"><B><xsl:apply-templates/></B></xsl:template> 
 568    <xsl:template match="c"><C><xsl:apply-templates/></C></xsl:template> 
 569  </xsl:stylesheet>''') 
 570   
 571          self.assertEqual(self._rootstring(tree), 
 572                            _bytes('<a><b>B</b><c>C</c></a>')) 
 573          result = tree.xslt(style) 
 574          self.assertEqual(self._rootstring(tree), 
 575                            _bytes('<a><b>B</b><c>C</c></a>')) 
 576          self.assertEqual(self._rootstring(result), 
 577                            _bytes('<A><B>B</B><C>C</C></A>')) 
 578   
 579          b_tree = etree.ElementTree(tree.getroot()[0]) 
 580          self.assertEqual(self._rootstring(b_tree), 
 581                            _bytes('<b>B</b>')) 
 582          result = b_tree.xslt(style) 
 583          self.assertEqual(self._rootstring(tree), 
 584                            _bytes('<a><b>B</b><c>C</c></a>')) 
 585          self.assertEqual(self._rootstring(result), 
 586                            _bytes('<B>B</B>')) 
 587   
 588          c_tree = etree.ElementTree(tree.getroot()[1]) 
 589          self.assertEqual(self._rootstring(c_tree), 
 590                            _bytes('<c>C</c>')) 
 591          result = c_tree.xslt(style) 
 592          self.assertEqual(self._rootstring(tree), 
 593                            _bytes('<a><b>B</b><c>C</c></a>')) 
 594          self.assertEqual(self._rootstring(result), 
 595                            _bytes('<C>C</C>')) 
  596   
 598           
 599          xslt = etree.XSLT(etree.XML("""\ 
 600  <xsl:stylesheet version="1.0" 
 601     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 602    <xsl:template match="/"> 
 603      <test>TEXT<xsl:copy-of select="document('')//test"/></test> 
 604    </xsl:template> 
 605  </xsl:stylesheet> 
 606  """)) 
 607          result = xslt(etree.XML('<a/>')) 
 608          root = result.getroot() 
 609          self.assertEqual(root.tag, 
 610                            'test') 
 611          self.assertEqual(root[0].tag, 
 612                            'test') 
 613          self.assertEqual(root[0].text, 
 614                            'TEXT') 
 615          self.assertEqual(root[0][0].tag, 
 616                            '{http://www.w3.org/1999/XSL/Transform}copy-of') 
  617   
 627   
 637   
 639          xslt = etree.XSLT(etree.XML("""\ 
 640  <xsl:stylesheet version="1.0" 
 641     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 642    <xsl:template match="/"> 
 643      <test>TEXT<xsl:copy-of select="document('uri:__junkfood__is__evil__')//test"/></test> 
 644    </xsl:template> 
 645  </xsl:stylesheet> 
 646  """)) 
 647          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>')) 
  648   
 650           
 651          assertEqual = self.assertEqual 
 652          called = {'count' : 0} 
 653          class TestResolver(etree.Resolver): 
 654              def resolve(self, url, id, context): 
 655                  assertEqual(url, 'file://ANYTHING') 
 656                  called['count'] += 1 
 657                  return self.resolve_string('<CALLED/>', context) 
   658   
 659          parser = etree.XMLParser() 
 660          parser.resolvers.add(TestResolver()) 
 661   
 662          xslt = etree.XSLT(etree.XML(_bytes("""\ 
 663  <xsl:stylesheet version="1.0" 
 664     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 665     xmlns:l="local"> 
 666    <xsl:template match="/"> 
 667      <test> 
 668        <xsl:for-each select="document('')//l:data/l:entry"> 
 669          <xsl:copy-of select="document('file://ANYTHING')"/> 
 670          <xsl:copy> 
 671            <xsl:attribute name="value"> 
 672              <xsl:value-of select="."/> 
 673            </xsl:attribute> 
 674          </xsl:copy> 
 675        </xsl:for-each> 
 676      </test> 
 677    </xsl:template> 
 678    <l:data> 
 679      <l:entry>A</l:entry> 
 680      <l:entry>B</l:entry> 
 681    </l:data> 
 682  </xsl:stylesheet> 
 683  """), parser)) 
 684   
 685          self.assertEqual(called['count'], 0) 
 686          result = xslt(etree.XML('<a/>')) 
 687          self.assertEqual(called['count'], 1) 
 688   
 689          root = result.getroot() 
 690          self.assertEqual(root.tag, 
 691                            'test') 
 692          self.assertEqual(len(root), 4) 
 693   
 694          self.assertEqual(root[0].tag, 
 695                            'CALLED') 
 696          self.assertEqual(root[1].tag, 
 697                            '{local}entry') 
 698          self.assertEqual(root[1].text, 
 699                            None) 
 700          self.assertEqual(root[1].get("value"), 
 701                            'A') 
 702          self.assertEqual(root[2].tag, 
 703                            'CALLED') 
 704          self.assertEqual(root[3].tag, 
 705                            '{local}entry') 
 706          self.assertEqual(root[3].text, 
 707                            None) 
 708          self.assertEqual(root[3].get("value"), 
 709                            'B') 
 710   
 712          assertEqual = self.assertEqual 
 713          called = {'count' : 0} 
 714          expected_url = None 
 715          class TestResolver(etree.Resolver): 
 716              def resolve(self, url, id, context): 
 717                  assertEqual(url, expected_url) 
 718                  called['count'] += 1 
 719                  return self.resolve_string('<CALLED/>', context) 
  720   
 721          stylesheet_xml = _bytes("""\ 
 722  <xsl:stylesheet version="1.0" 
 723     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 724     xmlns:l="local"> 
 725    <xsl:template match="/"> 
 726      <xsl:copy-of select="document('test.xml')"/> 
 727    </xsl:template> 
 728  </xsl:stylesheet> 
 729  """) 
 730   
 731          parser = etree.XMLParser() 
 732          parser.resolvers.add(TestResolver()) 
 733   
 734           
 735          expected_url = 'test.xml' 
 736          xslt = etree.XSLT(etree.XML(stylesheet_xml, parser)) 
 737   
 738          self.assertEqual(called['count'], 0) 
 739          result = xslt(etree.XML('<a/>')) 
 740          self.assertEqual(called['count'], 1) 
 741   
 742           
 743          called['count'] = 0 
 744          expected_url = 'MY/BASE/test.xml'   
 745          xslt = etree.XSLT(etree.XML( 
 746              stylesheet_xml, parser, 
 747              base_url=os.path.join('MY', 'BASE', 'FILE'))) 
 748   
 749          self.assertEqual(called['count'], 0) 
 750          result = xslt(etree.XML('<a/>')) 
 751          self.assertEqual(called['count'], 1) 
 752   
 753           
 754          called['count'] = 0 
 755          expected_url = 'http://server.com/BASE/DIR/test.xml' 
 756          xslt = etree.XSLT(etree.XML( 
 757              stylesheet_xml, parser, 
 758              base_url='http://server.com/BASE/DIR/FILE')) 
 759   
 760          self.assertEqual(called['count'], 0) 
 761          result = xslt(etree.XML('<a/>')) 
 762          self.assertEqual(called['count'], 1) 
 763   
 764           
 765          called['count'] = 0 
 766          expected_url = 'file://BASE/DIR/test.xml' 
 767          xslt = etree.XSLT(etree.XML( 
 768              stylesheet_xml, parser, 
 769              base_url='file://BASE/DIR/FILE')) 
 770   
 771          self.assertEqual(called['count'], 0) 
 772          result = xslt(etree.XML('<a/>')) 
 773          self.assertEqual(called['count'], 1) 
 774   
 785   
 791   
 797   
 806   
 808          root = etree.XML(_bytes('''\ 
 809          <transform> 
 810            <widget displayType="fieldset"/> 
 811          </transform>''')) 
 812   
 813          xslt = etree.XSLT(etree.XML(_bytes('''\ 
 814          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 815            <xsl:output method="html" indent="no"/> 
 816            <xsl:template match="/"> 
 817              <html> 
 818                <xsl:apply-templates/> 
 819              </html> 
 820            </xsl:template> 
 821   
 822            <xsl:template match="widget"> 
 823              <xsl:element name="{@displayType}"/> 
 824            </xsl:template> 
 825   
 826          </xsl:stylesheet>'''))) 
 827   
 828          result = xslt(root[0]) 
 829          root[:] = result.getroot()[:] 
 830          del root  
  831           
 833          tree = self.parse('''\ 
 834  <?xml version="1.0"?> 
 835  <?xml-stylesheet type="text/xsl" href="%s"?> 
 836  <a> 
 837    <b>B</b> 
 838    <c>C</c> 
 839  </a>''' % fileInTestDir("test1.xslt")) 
 840   
 841          style_root = tree.getroot().getprevious().parseXSL().getroot() 
 842          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 
 843                            style_root.tag) 
  844   
 846           
 847          tree = self.parse('''\ 
 848  <?xml version="1.0"?> 
 849  <?xml-stylesheet type="text/xsl" href="#style"?> 
 850  <a> 
 851    <b>B</b> 
 852    <c>C</c> 
 853    <xsl:stylesheet version="1.0" xml:id="style" 
 854        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 855      <xsl:template match="*" /> 
 856      <xsl:template match="/"> 
 857        <foo><xsl:value-of select="/a/b/text()" /></foo> 
 858      </xsl:template> 
 859    </xsl:stylesheet> 
 860  </a>''') 
 861   
 862          style_root = tree.getroot().getprevious().parseXSL().getroot() 
 863          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 
 864                            style_root.tag) 
 865   
 866          st = etree.XSLT(style_root) 
 867          res = st(tree) 
 868          self.assertEqual('''\ 
 869  <?xml version="1.0"?> 
 870  <foo>B</foo> 
 871  ''', 
 872                            str(res)) 
  873   
 875           
 876          tree = self.parse('''\ 
 877  <?xml version="1.0"?> 
 878  <?xml-stylesheet type="text/xsl" href="#style"?> 
 879  <a> 
 880    <b>B</b> 
 881    <c>C</c> 
 882  </a>''') 
 883   
 884          style = self.parse('''\ 
 885  <xsl:stylesheet version="1.0" xml:id="style" 
 886      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 887    <xsl:template match="*" /> 
 888    <xsl:template match="/"> 
 889      <foo><xsl:value-of select="/a/b/text()" /></foo> 
 890    </xsl:template> 
 891  </xsl:stylesheet> 
 892  ''') 
 893   
 894          tree.getroot().append(style.getroot()) 
 895   
 896          style_root = tree.getroot().getprevious().parseXSL().getroot() 
 897          self.assertEqual("{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.assertEqual('''\ 
 903  <?xml version="1.0"?> 
 904  <foo>B</foo> 
 905  ''', 
 906                            str(res)) 
  907   
 909          tree = self.parse('''\ 
 910  <?xml version="1.0"?> 
 911  <?xml-stylesheet type="text/xsl" href="TEST"?> 
 912  <a> 
 913    <b>B</b> 
 914    <c>C</c> 
 915  </a>''') 
 916   
 917          pi = tree.getroot().getprevious() 
 918          self.assertEqual("TEST", pi.get("href")) 
  919   
 921          tree = self.parse('''\ 
 922  <?xml version="1.0"?> 
 923  <?xml-stylesheet type="text/xsl" href="TEST"?> 
 924  <a> 
 925    <b>B</b> 
 926    <c>C</c> 
 927  </a>''') 
 928   
 929          pi = tree.getroot().getprevious() 
 930          self.assertEqual("TEST", pi.get("href")) 
 931          self.assertEqual("text/xsl", pi.get("type")) 
 932          self.assertEqual(None, pi.get("motz")) 
  933   
 935          tree = self.parse('''\ 
 936  <?xml version="1.0"?> 
 937  <?xml-stylesheet href="TEST" type="text/xsl"?> 
 938  <a> 
 939    <b>B</b> 
 940    <c>C</c> 
 941  </a>''') 
 942   
 943          pi = tree.getroot().getprevious() 
 944          self.assertEqual("TEST", pi.get("href")) 
 945          self.assertEqual("text/xsl", pi.get("type")) 
 946          self.assertEqual(None, pi.get("motz")) 
  947   
 949          tree = self.parse('''\ 
 950  <?xml version="1.0"?> 
 951  <?xml-stylesheet type="text/xsl" href="TEST"?> 
 952  <a> 
 953    <b>B</b> 
 954    <c>C</c> 
 955  </a>''') 
 956   
 957          pi = tree.getroot().getprevious() 
 958          self.assertEqual(None, pi.get("unknownattribute")) 
  959   
 961          tree = self.parse('''\ 
 962  <?xml version="1.0"?> 
 963  <?xml-stylesheet type="text/xsl" href="TEST"?> 
 964  <a> 
 965    <b>B</b> 
 966    <c>C</c> 
 967  </a>''') 
 968   
 969          pi = tree.getroot().getprevious() 
 970          self.assertEqual("TEST", pi.get("href")) 
 971   
 972          pi.set("href", "TEST123") 
 973          self.assertEqual("TEST123", pi.get("href")) 
  974   
 976          tree = self.parse('''\ 
 977  <?xml version="1.0"?> 
 978  <?xml-stylesheet type="text/xsl"?> 
 979  <a> 
 980    <b>B</b> 
 981    <c>C</c> 
 982  </a>''') 
 983   
 984          pi = tree.getroot().getprevious() 
 985          self.assertEqual(None, pi.get("href")) 
 986   
 987          pi.set("href", "TEST") 
 988          self.assertEqual("TEST", pi.get("href")) 
  989   
 991      """EXSLT tests""" 
 992   
 994          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 995          style = self.parse('''\ 
 996  <xsl:stylesheet version="1.0" 
 997      xmlns:str="http://exslt.org/strings" 
 998      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 999      exclude-result-prefixes="str xsl"> 
1000    <xsl:template match="text()"> 
1001      <xsl:value-of select="str:align(string(.), '***', 'center')" /> 
1002    </xsl:template> 
1003    <xsl:template match="*"> 
1004      <xsl:copy> 
1005        <xsl:apply-templates/> 
1006      </xsl:copy> 
1007    </xsl:template> 
1008  </xsl:stylesheet>''') 
1009   
1010          st = etree.XSLT(style) 
1011          res = st(tree) 
1012          self.assertEqual('''\ 
1013  <?xml version="1.0"?> 
1014  <a><b>*B*</b><c>*C*</c></a> 
1015  ''', 
1016                            str(res)) 
 1017   
1018      if etree.LIBXSLT_VERSION >= (1,1,21): 
1020              tree = self.parse('<a><b>B</b><c>C</c></a>') 
1021              style = self.parse('''\ 
1022        <xsl:stylesheet version = "1.0" 
1023            xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 
1024            xmlns:str="http://exslt.org/strings" 
1025            extension-element-prefixes="str"> 
1026   
1027            <xsl:template match="/"> 
1028              <h1 class="{str:replace('abc', 'b', 'x')}">test</h1> 
1029            </xsl:template> 
1030   
1031        </xsl:stylesheet>''') 
1032   
1033              st = etree.XSLT(style) 
1034              res = st(tree) 
1035              self.assertEqual('''\ 
1036  <?xml version="1.0"?> 
1037  <h1 class="axc">test</h1> 
1038  ''', 
1039                                str(res)) 
 1040   
1042          tree = self.parse('<a><b>B</b><c>C</c></a>') 
1043          style = self.parse('''\ 
1044  <xsl:stylesheet version="1.0" 
1045      xmlns:math="http://exslt.org/math" 
1046      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1047      exclude-result-prefixes="math xsl"> 
1048    <xsl:template match="*"> 
1049      <xsl:copy> 
1050        <xsl:attribute name="pi"> 
1051          <xsl:value-of select="math:constant('PI', count(*)+2)"/> 
1052        </xsl:attribute> 
1053        <xsl:apply-templates/> 
1054      </xsl:copy> 
1055    </xsl:template> 
1056  </xsl:stylesheet>''') 
1057   
1058          st = etree.XSLT(style) 
1059          res = st(tree) 
1060          self.assertEqual('''\ 
1061  <?xml version="1.0"?> 
1062  <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a> 
1063  ''', 
1064                            str(res)) 
 1065   
1067          xslt = etree.XSLT(etree.XML(_bytes("""\ 
1068  <xsl:stylesheet version="1.0" 
1069     xmlns:regexp="http://exslt.org/regular-expressions" 
1070     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1071    <xsl:template match="*"> 
1072      <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test> 
1073    </xsl:template> 
1074  </xsl:stylesheet> 
1075  """))) 
1076          result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>'))) 
1077          root = result.getroot() 
1078          self.assertEqual(root.tag, 
1079                            'test') 
1080          self.assertEqual(len(root), 1) 
1081          self.assertEqual(root[0].tag, 
1082                            'b') 
1083          self.assertEqual(root[0].text, 
1084                            '987') 
 1085   
1087          xslt = etree.XSLT(etree.XML("""\ 
1088  <xsl:stylesheet version="1.0" 
1089     xmlns:regexp="http://exslt.org/regular-expressions" 
1090     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1091    <xsl:template match="*"> 
1092      <test> 
1093        <xsl:copy-of select="regexp:replace(string(.), 'd.', '',   'XX')"/> 
1094        <xsl:text>-</xsl:text> 
1095        <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/> 
1096      </test> 
1097    </xsl:template> 
1098  </xsl:stylesheet> 
1099  """)) 
1100          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>'))) 
1101          root = result.getroot() 
1102          self.assertEqual(root.tag, 
1103                            'test') 
1104          self.assertEqual(len(root), 0) 
1105          self.assertEqual(root.text, 'abXXdEeDed-abXXXXeXXd') 
 1106   
1108          xslt = etree.XSLT(etree.XML("""\ 
1109  <xsl:stylesheet version="1.0" 
1110     xmlns:regexp="http://exslt.org/regular-expressions" 
1111     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1112    <xsl:template match="*"> 
1113      <test> 
1114        <test1><xsl:copy-of  select="regexp:match(string(.), 'd.')"/></test1> 
1115        <test2><xsl:copy-of  select="regexp:match(string(.), 'd.', 'g')"/></test2> 
1116        <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i> 
1117      </test> 
1118    </xsl:template> 
1119  </xsl:stylesheet> 
1120  """)) 
1121          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>'))) 
1122          root = result.getroot() 
1123          self.assertEqual(root.tag,  'test') 
1124          self.assertEqual(len(root), 3) 
1125   
1126          self.assertEqual(len(root[0]), 1) 
1127          self.assertEqual(root[0][0].tag, 'match') 
1128          self.assertEqual(root[0][0].text, 'dC') 
1129   
1130          self.assertEqual(len(root[1]), 2) 
1131          self.assertEqual(root[1][0].tag, 'match') 
1132          self.assertEqual(root[1][0].text, 'dC') 
1133          self.assertEqual(root[1][1].tag, 'match') 
1134          self.assertEqual(root[1][1].text, 'dE') 
1135   
1136          self.assertEqual(len(root[2]), 3) 
1137          self.assertEqual(root[2][0].tag, 'match') 
1138          self.assertEqual(root[2][0].text, 'dC') 
1139          self.assertEqual(root[2][1].tag, 'match') 
1140          self.assertEqual(root[2][1].text, 'dE') 
1141          self.assertEqual(root[2][2].tag, 'match') 
1142          self.assertEqual(root[2][2].text, 'De') 
 1143   
1145          xslt = etree.XSLT(etree.XML(_bytes("""\ 
1146  <xsl:stylesheet version="1.0" 
1147     xmlns:regexp="http://exslt.org/regular-expressions" 
1148     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1149    <xsl:template match="/"> 
1150      <test> 
1151        <xsl:for-each select="regexp:match( 
1152              '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )"> 
1153          <test1><xsl:value-of select="."/></test1> 
1154        </xsl:for-each> 
1155      </test> 
1156    </xsl:template> 
1157  </xsl:stylesheet> 
1158  """))) 
1159          result = xslt(etree.XML(_bytes('<a/>'))) 
1160          root = result.getroot() 
1161          self.assertEqual(root.tag,  'test') 
1162          self.assertEqual(len(root), 4) 
1163   
1164          self.assertEqual(root[0].text, "123abc567") 
1165          self.assertEqual(root[1].text, "123") 
1166          self.assertEqual(root[2].text, "abc") 
1167          self.assertEqual(root[3].text, "567") 
 1168   
1170           
1171          xslt = etree.XSLT(etree.XML(_bytes("""\ 
1172  <xsl:stylesheet version="1.0" 
1173     xmlns:regexp="http://exslt.org/regular-expressions" 
1174     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1175    <xsl:template match="/"> 
1176      <test> 
1177        <xsl:for-each select="regexp:match( 
1178              'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml', 
1179              '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')"> 
1180          <test1><xsl:value-of select="."/></test1> 
1181        </xsl:for-each> 
1182      </test> 
1183    </xsl:template> 
1184  </xsl:stylesheet> 
1185  """))) 
1186          result = xslt(etree.XML(_bytes('<a/>'))) 
1187          root = result.getroot() 
1188          self.assertEqual(root.tag,  'test') 
1189          self.assertEqual(len(root), 5) 
1190   
1191          self.assertEqual( 
1192              root[0].text, 
1193              "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml") 
1194          self.assertEqual( 
1195              root[1].text, 
1196              "http") 
1197          self.assertEqual( 
1198              root[2].text, 
1199              "www.bayes.co.uk") 
1200          self.assertFalse(root[3].text) 
1201          self.assertEqual( 
1202              root[4].text, 
1203              "/xml/index.xml?/xml/utils/rechecker.xml") 
 1204   
1206           
1207          xslt = etree.XSLT(self.parse("""\ 
1208  <xsl:stylesheet version="1.0" 
1209     xmlns:regexp="http://exslt.org/regular-expressions" 
1210     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1211    <xsl:template match="/"> 
1212      <test> 
1213        <xsl:for-each select="regexp:match( 
1214              'This is a test string', '(\w+)', 'g')"> 
1215          <test1><xsl:value-of select="."/></test1> 
1216        </xsl:for-each> 
1217      </test> 
1218    </xsl:template> 
1219  </xsl:stylesheet> 
1220  """)) 
1221          result = xslt(etree.XML(_bytes('<a/>'))) 
1222          root = result.getroot() 
1223          self.assertEqual(root.tag,  'test') 
1224          self.assertEqual(len(root), 5) 
1225   
1226          self.assertEqual(root[0].text, "This") 
1227          self.assertEqual(root[1].text, "is") 
1228          self.assertEqual(root[2].text, "a") 
1229          self.assertEqual(root[3].text, "test") 
1230          self.assertEqual(root[4].text, "string") 
 1231   
1233           
1234           
1235          xslt = etree.XSLT(etree.XML(_bytes("""\ 
1236  <xsl:stylesheet version="1.0" 
1237     xmlns:regexp="http://exslt.org/regular-expressions" 
1238     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1239    <xsl:template match="/"> 
1240      <test> 
1241        <xsl:for-each select="regexp:match( 
1242              'This is a test string', '([a-z])+ ', 'g')"> 
1243          <test1><xsl:value-of select="."/></test1> 
1244        </xsl:for-each> 
1245      </test> 
1246    </xsl:template> 
1247  </xsl:stylesheet> 
1248  """))) 
1249          result = xslt(etree.XML(_bytes('<a/>'))) 
1250          root = result.getroot() 
1251          self.assertEqual(root.tag,  'test') 
1252          self.assertEqual(len(root), 4) 
1253   
1254          self.assertEqual(root[0].text, "his") 
1255          self.assertEqual(root[1].text, "is") 
1256          self.assertEqual(root[2].text, "a") 
1257          self.assertEqual(root[3].text, "test") 
 1258   
1260           
1261           
1262          xslt = etree.XSLT(etree.XML(_bytes("""\ 
1263  <xsl:stylesheet version="1.0" 
1264     xmlns:regexp="http://exslt.org/regular-expressions" 
1265     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1266    <xsl:template match="/"> 
1267      <test> 
1268        <xsl:for-each select="regexp:match( 
1269              'This is a test string', '([a-z])+ ', 'gi')"> 
1270          <test1><xsl:value-of select="."/></test1> 
1271        </xsl:for-each> 
1272      </test> 
1273    </xsl:template> 
1274  </xsl:stylesheet> 
1275  """))) 
1276          result = xslt(etree.XML(_bytes('<a/>'))) 
1277          root = result.getroot() 
1278          self.assertEqual(root.tag,  'test') 
1279          self.assertEqual(len(root), 4) 
1280   
1281          self.assertEqual(root[0].text, "This") 
1282          self.assertEqual(root[1].text, "is") 
1283          self.assertEqual(root[2].text, "a") 
1284          self.assertEqual(root[3].text, "test") 
  1285   
1286   
1287 -class ETreeXSLTExtFuncTestCase(HelperTestCase): 
 1288      """Tests for XPath extension functions in XSLT.""" 
1289   
1290 -    def test_extensions1(self): 
 1291          tree = self.parse('<a><b>B</b></a>') 
1292          style = self.parse('''\ 
1293  <xsl:stylesheet version="1.0" 
1294      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1295      xmlns:myns="testns" 
1296      exclude-result-prefixes="myns"> 
1297    <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template> 
1298  </xsl:stylesheet>''') 
1299   
1300          def mytext(ctxt, values): 
1301              return 'X' * len(values) 
 1302   
1303          result = tree.xslt(style, {('testns', 'mytext') : mytext}) 
1304          self.assertEqual(self._rootstring(result), 
1305                            _bytes('<A>X</A>')) 
 1306   
1307 -    def test_extensions2(self): 
 1308          tree = self.parse('<a><b>B</b></a>') 
1309          style = self.parse('''\ 
1310  <xsl:stylesheet version="1.0" 
1311      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1312      xmlns:myns="testns" 
1313      exclude-result-prefixes="myns"> 
1314    <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template> 
1315  </xsl:stylesheet>''') 
1316   
1317          def mytext(ctxt, values): 
1318              return 'X' * len(values) 
 1319   
1320          namespace = etree.FunctionNamespace('testns') 
1321          namespace['mytext'] = mytext 
1322   
1323          result = tree.xslt(style) 
1324          self.assertEqual(self._rootstring(result), 
1325                            _bytes('<A>X</A>')) 
1326   
1328          tree = self.parse('<a><b>B</b><b/></a>') 
1329          style = self.parse('''\ 
1330  <xsl:stylesheet version="1.0" 
1331      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1332      xmlns:myns="testns" 
1333      exclude-result-prefixes="myns"> 
1334    <xsl:template match="a"> 
1335      <xsl:variable name="content"> 
1336         <xsl:apply-templates/> 
1337      </xsl:variable> 
1338      <A><xsl:value-of select="myns:mytext($content)"/></A> 
1339    </xsl:template> 
1340    <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template> 
1341  </xsl:stylesheet>''') 
1342   
1343          def mytext(ctxt, values): 
1344              for value in values: 
1345                  self.assertTrue(hasattr(value, 'tag'), 
1346                               "%s is not an Element" % type(value)) 
1347                  self.assertEqual(value.tag, 'b') 
1348                  self.assertEqual(value.text, 'BBB') 
1349              return 'X'.join([el.tag for el in values]) 
 1350   
1351          namespace = etree.FunctionNamespace('testns') 
1352          namespace['mytext'] = mytext 
1353   
1354          result = tree.xslt(style) 
1355          self.assertEqual(self._rootstring(result), 
1356                           _bytes('<A>bXb</A>')) 
1357   
1359          tree = self.parse('<a><b>B<c/>C</b><b/></a>') 
1360          style = self.parse('''\ 
1361  <xsl:stylesheet version="1.0" 
1362      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1363      xmlns:myns="testns" 
1364      exclude-result-prefixes="myns"> 
1365    <xsl:template match="b"> 
1366      <A><xsl:value-of select="myns:myext()"/></A> 
1367    </xsl:template> 
1368  </xsl:stylesheet>''') 
1369   
1370          def extfunc(ctxt): 
1371              text_content = ctxt.context_node.xpath('text()') 
1372              return 'x'.join(text_content) 
 1373   
1374          namespace = etree.FunctionNamespace('testns') 
1375          namespace['myext'] = extfunc 
1376   
1377          result = tree.xslt(style) 
1378          self.assertEqual(self._rootstring(result), 
1379                           _bytes('<A>BxC</A>')) 
1380   
1382           
1383          class Resolver(etree.Resolver): 
1384              def resolve(self, system_url, public_id, context): 
1385                  assert system_url == 'extdoc.xml' 
1386                  return self.resolve_string(b'<a><b>B<c/>C</b><b/></a>', context) 
 1387   
1388          parser = etree.XMLParser() 
1389          parser.resolvers.add(Resolver()) 
1390   
1391          tree = self.parse(b'<a><b/><b/></a>') 
1392          transform = etree.XSLT(self.parse(b'''\ 
1393  <xsl:stylesheet version="1.0" 
1394      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1395      xmlns:mypre="testns" 
1396      exclude-result-prefixes="mypre"> 
1397    <xsl:template match="b"> 
1398      <B><xsl:value-of select="mypre:myext()"/></B> 
1399    </xsl:template> 
1400    <xsl:template match="a"> 
1401      <A><xsl:apply-templates select="document('extdoc.xml')//b" /></A> 
1402    </xsl:template> 
1403  </xsl:stylesheet>''', parser=parser)) 
1404   
1405          def extfunc(ctxt): 
1406              text_content = ctxt.context_node.xpath('text()') 
1407              return 'x'.join(text_content) 
1408   
1409          namespace = etree.FunctionNamespace('testns') 
1410          namespace['myext'] = extfunc 
1411   
1412          result = transform(tree) 
1413          self.assertEqual(self._rootstring(result), 
1414                           _bytes('<A><B>BxC</B><B/></A>')) 
1415   
1416   
1417 -class ETreeXSLTExtElementTestCase(HelperTestCase): 
 1418      """Tests for extension elements in XSLT.""" 
1419   
1421          tree = self.parse('<a><b>B</b></a>') 
1422          style = self.parse('''\ 
1423  <xsl:stylesheet version="1.0" 
1424      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1425      xmlns:myns="testns" 
1426      extension-element-prefixes="myns" 
1427      exclude-result-prefixes="myns"> 
1428    <xsl:template match="a"> 
1429      <A><myns:myext>b</myns:myext></A> 
1430    </xsl:template> 
1431  </xsl:stylesheet>''') 
1432   
1433          class MyExt(etree.XSLTExtension): 
1434              def execute(self, context, self_node, input_node, output_parent): 
1435                  child = etree.Element(self_node.text) 
1436                  child.text = 'X' 
1437                  output_parent.append(child) 
  1438   
1439          extensions = { ('testns', 'myext') : MyExt() } 
1440   
1441          result = tree.xslt(style, extensions=extensions) 
1442          self.assertEqual(self._rootstring(result), 
1443                            _bytes('<A><b>X</b></A>')) 
1444   
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      exclude-result-prefixes="myns"> 
1453    <xsl:template match="/"> 
1454      <A><myns:myext>b</myns:myext></A> 
1455    </xsl:template> 
1456  </xsl:stylesheet>''') 
1457   
1458          tags = [] 
1459   
1460          class MyExt(etree.XSLTExtension): 
1461              def execute(self, context, self_node, input_node, output_parent): 
1462                  tags.append(input_node.tag) 
 1463   
1464          extensions = { ('testns', 'myext') : MyExt() } 
1465   
1466          result = tree.xslt(style, extensions=extensions) 
1467          self.assertEqual(tags, ['a']) 
1468   
1470          tree = self.parse('<?test toast?><a><!--a comment--><?another pi?></a>') 
1471          style = self.parse('''\ 
1472  <xsl:stylesheet version="1.0" 
1473      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1474      xmlns:myns="testns" 
1475      extension-element-prefixes="myns" 
1476      exclude-result-prefixes="myns"> 
1477    <xsl:template match="/"> 
1478      <ROOT><xsl:apply-templates /></ROOT> 
1479    </xsl:template> 
1480    <xsl:template match="comment()"> 
1481      <A><myns:myext>b</myns:myext></A> 
1482    </xsl:template> 
1483    <xsl:template match="processing-instruction()"> 
1484      <A><myns:myext>b</myns:myext></A> 
1485    </xsl:template> 
1486  </xsl:stylesheet>''') 
1487   
1488          text = [] 
1489   
1490          class MyExt(etree.XSLTExtension): 
1491              def execute(self, context, self_node, input_node, output_parent): 
1492                  text.append(input_node.text) 
 1493   
1494          extensions = { ('testns', 'myext') : MyExt() } 
1495   
1496          result = tree.xslt(style, extensions=extensions) 
1497          self.assertEqual(text, ['toast', 'a comment', 'pi']) 
1498   
1500           
1501          tree = self.parse('<a test="A"><b attr="B"/></a>') 
1502          style = self.parse('''\ 
1503  <xsl:stylesheet version="1.0" 
1504      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1505      xmlns:myns="testns" 
1506      extension-element-prefixes="myns" 
1507      exclude-result-prefixes="myns"> 
1508    <xsl:template match="@test"> 
1509      <A><myns:myext>b</myns:myext></A> 
1510    </xsl:template> 
1511    <xsl:template match="@attr"> 
1512      <A><myns:myext>b</myns:myext></A> 
1513    </xsl:template> 
1514  </xsl:stylesheet>''') 
1515   
1516          text = [] 
1517   
1518          class MyExt(etree.XSLTExtension): 
1519              def execute(self, context, self_node, attr_value, output_parent): 
1520                  text.append(attr_value) 
 1521   
1522          extensions = { ('testns', 'myext') : MyExt() } 
1523   
1524          result = tree.xslt(style, extensions=extensions) 
1525          self.assertEqual(text, ['A', 'B']) 
1526   
1528          tree = self.parse('<a><b>B</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      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 
1536    </xsl:template> 
1537  </xsl:stylesheet>''') 
1538   
1539          class MyExt(etree.XSLTExtension): 
1540              def execute(self, context, self_node, input_node, output_parent): 
1541                  output_parent.extend(list(self_node)[1:]) 
 1542   
1543          extensions = { ('testns', 'myext') : MyExt() } 
1544   
1545          result = tree.xslt(style, extensions=extensions) 
1546          self.assertEqual(self._rootstring(result), 
1547                            _bytes('<A><y>Y</y><z/></A>')) 
1548   
1550          tree = self.parse('<a><b>B</b></a>') 
1551          style = self.parse('''\ 
1552  <xsl:stylesheet version="1.0" 
1553      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1554      xmlns:myns="testns" 
1555      extension-element-prefixes="myns"> 
1556    <xsl:template match="a"> 
1557      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 
1558    </xsl:template> 
1559    <xsl:template match="x" /> 
1560    <xsl:template match="z">XYZ</xsl:template> 
1561  </xsl:stylesheet>''') 
1562   
1563          class MyExt(etree.XSLTExtension): 
1564              def execute(self, context, self_node, input_node, output_parent): 
1565                  for child in self_node: 
1566                      for result in self.apply_templates(context, child): 
1567                          if isinstance(result, basestring): 
1568                              el = etree.Element("T") 
1569                              el.text = result 
1570                          else: 
1571                              el = result 
1572                          output_parent.append(el) 
 1573   
1574          extensions = { ('testns', 'myext') : MyExt() } 
1575   
1576          result = tree.xslt(style, extensions=extensions) 
1577          self.assertEqual(self._rootstring(result), 
1578                            _bytes('<A><T>Y</T><T>XYZ</T></A>')) 
1579   
1581          tree = self.parse('<a><b>B</b></a>') 
1582          style = self.parse('''\ 
1583  <xsl:stylesheet version="1.0" 
1584      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1585      xmlns:myns="testns" 
1586      extension-element-prefixes="myns"> 
1587    <xsl:template match="a"> 
1588      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 
1589    </xsl:template> 
1590    <xsl:template match="x"><X/></xsl:template> 
1591    <xsl:template match="z">XYZ</xsl:template> 
1592  </xsl:stylesheet>''') 
1593   
1594          class MyExt(etree.XSLTExtension): 
1595              def execute(self, context, self_node, input_node, output_parent): 
1596                  for child in self_node: 
1597                      for result in self.apply_templates(context, child, 
1598                                                         elements_only=True): 
1599                          assert not isinstance(result, basestring) 
1600                          output_parent.append(result) 
 1601   
1602          extensions = { ('testns', 'myext') : MyExt() } 
1603   
1604          result = tree.xslt(style, extensions=extensions) 
1605          self.assertEqual(self._rootstring(result), 
1606                            _bytes('<A><X/></A>')) 
1607   
1609          tree = self.parse('<a><b>B</b></a>') 
1610          style = self.parse('''\ 
1611  <xsl:stylesheet version="1.0" 
1612      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1613      xmlns:myns="testns" 
1614      extension-element-prefixes="myns"> 
1615    <xsl:template match="a"> 
1616      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 
1617    </xsl:template> 
1618    <xsl:template match="x"><X/></xsl:template> 
1619    <xsl:template match="y"><xsl:text>   </xsl:text></xsl:template> 
1620    <xsl:template match="z">XYZ</xsl:template> 
1621  </xsl:stylesheet>''') 
1622   
1623          class MyExt(etree.XSLTExtension): 
1624              def execute(self, context, self_node, input_node, output_parent): 
1625                  for child in self_node: 
1626                      for result in self.apply_templates(context, child, 
1627                                                         remove_blank_text=True): 
1628                          if isinstance(result, basestring): 
1629                              assert result.strip() 
1630                              el = etree.Element("T") 
1631                              el.text = result 
1632                          else: 
1633                              el = result 
1634                          output_parent.append(el) 
 1635   
1636          extensions = { ('testns', 'myext') : MyExt() } 
1637   
1638          result = tree.xslt(style, extensions=extensions) 
1639          self.assertEqual(self._rootstring(result), 
1640                            _bytes('<A><X/><T>XYZ</T></A>')) 
1641   
1643          tree = self.parse('<a><b>B</b></a>') 
1644          style = self.parse('''\ 
1645  <xsl:stylesheet version="1.0" 
1646      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1647      xmlns:myns="testns" 
1648      extension-element-prefixes="myns"> 
1649    <xsl:template match="a"> 
1650      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 
1651    </xsl:template> 
1652    <xsl:template match="x" /> 
1653    <xsl:template match="z">XYZ</xsl:template> 
1654  </xsl:stylesheet>''') 
1655   
1656          class MyExt(etree.XSLTExtension): 
1657              def execute(self, context, self_node, input_node, output_parent): 
1658                  for child in self_node: 
1659                      self.apply_templates(context, child, output_parent) 
 1660   
1661          extensions = { ('testns', 'myext') : MyExt() } 
1662   
1663          result = tree.xslt(style, extensions=extensions) 
1664          self.assertEqual(self._rootstring(result), 
1665                            _bytes('<A>YXYZ</A>')) 
1666   
1668          tree = self.parse('<a><b>B</b></a>') 
1669          style = self.parse('''\ 
1670  <xsl:stylesheet version="1.0" 
1671      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1672      xmlns:myns="testns" 
1673      extension-element-prefixes="myns"> 
1674    <xsl:template match="a"> 
1675      <myns:myext><x>X</x><y>Y</y><z/></myns:myext> 
1676    </xsl:template> 
1677    <xsl:template match="x"><xsl:processing-instruction name="test">TEST</xsl:processing-instruction></xsl:template> 
1678    <xsl:template match="y"><Y>XYZ</Y></xsl:template> 
1679    <xsl:template match="z"><xsl:comment>TEST</xsl:comment></xsl:template> 
1680  </xsl:stylesheet>''') 
1681   
1682          class MyExt(etree.XSLTExtension): 
1683              def execute(self, context, self_node, input_node, output_parent): 
1684                  for child in self_node: 
1685                      self.apply_templates(context, child, output_parent) 
 1686   
1687          extensions = { ('testns', 'myext') : MyExt() } 
1688   
1689          result = tree.xslt(style, extensions=extensions) 
1690          self.assertEqual(etree.tostring(result), 
1691                            _bytes('<?test TEST?><Y>XYZ</Y><!--TEST-->')) 
1692   
1694          tree = self.parse('<a><b>E</b></a>') 
1695          style = self.parse('''\ 
1696  <xsl:stylesheet version="1.0" 
1697      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1698      xmlns:myns="testns" 
1699      extension-element-prefixes="myns"> 
1700    <xsl:template match="a"> 
1701      <xsl:variable name="testvar">yo</xsl:variable> 
1702      <A> 
1703        <myns:myext> 
1704          <xsl:attribute name="attr"> 
1705            <xsl:value-of select="$testvar" /> 
1706          </xsl:attribute> 
1707          <B> 
1708            <xsl:choose> 
1709              <xsl:when test="1 = 2"><C/></xsl:when> 
1710              <xsl:otherwise><D><xsl:value-of select="b/text()" /></D></xsl:otherwise> 
1711            </xsl:choose> 
1712          </B> 
1713        </myns:myext> 
1714      </A> 
1715    </xsl:template> 
1716  </xsl:stylesheet>''') 
1717   
1718          class MyExt(etree.XSLTExtension): 
1719              def execute(self, context, self_node, input_node, output_parent): 
1720                  el = etree.Element('MY') 
1721                  self.process_children(context, el) 
1722                  output_parent.append(el) 
 1723   
1724          extensions = { ('testns', 'myext') : MyExt() } 
1725   
1726          result = tree.xslt(style, extensions=extensions) 
1727          self.assertEqual(self._rootstring(result), 
1728                            _bytes('<A><MYattr="yo"><B><D>E</D></B></MY></A>')) 
1729   
1731          tree = self.parse('<a/>') 
1732          style = self.parse('''\ 
1733  <xsl:stylesheet version="1.0" 
1734      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1735      xmlns:myns="testns" 
1736      extension-element-prefixes="myns"> 
1737    <xsl:template match="a"> 
1738      <myns:myext> 
1739        <A/> 
1740      </myns:myext> 
1741    </xsl:template> 
1742  </xsl:stylesheet>''') 
1743   
1744          class MyExt(etree.XSLTExtension): 
1745              def execute(self, context, self_node, input_node, output_parent): 
1746                  self.process_children(context, output_parent) 
 1747   
1748          extensions = { ('testns', 'myext') : MyExt() } 
1749   
1750          result = tree.xslt(style, extensions=extensions) 
1751          self.assertEqual(self._rootstring(result), 
1752                            _bytes('<A/>')) 
1753   
1755          tree = self.parse('<a/>') 
1756          style = self.parse('''\ 
1757  <xsl:stylesheet version="1.0" 
1758      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1759      xmlns:myns="testns" 
1760      extension-element-prefixes="myns"> 
1761    <xsl:template match="a"> 
1762      <myns:myext> 
1763        <A/> 
1764      </myns:myext> 
1765    </xsl:template> 
1766  </xsl:stylesheet>''') 
1767   
1768          class MyExt(etree.XSLTExtension): 
1769              def execute(self, context, self_node, input_node, output_parent): 
1770                  self.process_children(context, self_node) 
 1771   
1772          extensions = { ('testns', 'myext') : MyExt() } 
1773   
1774          self.assertRaises(TypeError, tree.xslt, style, extensions=extensions) 
1775   
1777          tree = self.parse('<a/>') 
1778          style = self.parse('''\ 
1779  <xsl:stylesheet version="1.0" 
1780      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1781      xmlns:myns="testns" 
1782      extension-element-prefixes="myns"> 
1783    <xsl:template match="a"> 
1784      <myns:myext> 
1785        <A><myns:myext><B/></myns:myext></A> 
1786      </myns:myext> 
1787    </xsl:template> 
1788  </xsl:stylesheet>''') 
1789   
1790          class MyExt(etree.XSLTExtension): 
1791              callback_call_counter = 0 
1792              def execute(self, context, self_node, input_node, output_parent): 
1793                  self.callback_call_counter += 1 
1794                  el = etree.Element('MY', n=str(self.callback_call_counter)) 
1795                  self.process_children(context, el) 
1796                  output_parent.append(el) 
 1797   
1798          extensions = { ('testns', 'myext') : MyExt() } 
1799   
1800          result = tree.xslt(style, extensions=extensions) 
1801          self.assertEqual(self._rootstring(result), 
1802                            _bytes('<MYn="1"><A><MYn="2"><B/></MY></A></MY>')) 
1803   
1805          tree = self.parse('<a><b>B</b></a>') 
1806          style = self.parse('''\ 
1807  <xsl:stylesheet version="1.0" 
1808      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1809      xmlns:myns="testns" 
1810      extension-element-prefixes="myns" 
1811      exclude-result-prefixes="myns"> 
1812    <xsl:template match="a"> 
1813      <A><myns:myext>b</myns:myext></A> 
1814    </xsl:template> 
1815  </xsl:stylesheet>''') 
1816   
1817          class MyError(Exception): 
1818              pass 
 1819   
1820          class MyExt(etree.XSLTExtension): 
1821              def execute(self, context, self_node, input_node, output_parent): 
1822                  raise MyError("expected!") 
1823   
1824          extensions = { ('testns', 'myext') : MyExt() } 
1825          self.assertRaises(MyError, tree.xslt, style, extensions=extensions) 
1826   
1827       
1828       
1830          tree = self.parse("""\ 
1831  <text> 
1832    <par>This is <format>arbitrary</format> text in a paragraph</par> 
1833  </text>""") 
1834          style = self.parse("""\ 
1835  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my" extension-element-prefixes="my" version="1.0"> 
1836    <xsl:template match="par"> 
1837      <my:par><xsl:apply-templates /></my:par> 
1838    </xsl:template> 
1839    <xsl:template match="format"> 
1840      <my:format><xsl:apply-templates /></my:format> 
1841    </xsl:template> 
1842  </xsl:stylesheet> 
1843  """) 
1844          test = self 
1845          calls = [] 
1846   
1847          class ExtMyPar(etree.XSLTExtension): 
1848              def execute(self, context, self_node, input_node, output_parent): 
1849                  calls.append('par') 
1850                  p = etree.Element("p") 
1851                  p.attrib["style"] = "color:red" 
1852                  self.process_children(context, p) 
1853                  output_parent.append(p) 
 1854   
1855          class ExtMyFormat(etree.XSLTExtension): 
1856              def execute(self, context, self_node, input_node, output_parent): 
1857                  calls.append('format') 
1858                  content = self.process_children(context) 
1859                  test.assertEqual(1, len(content)) 
1860                  test.assertEqual('arbitrary', content[0]) 
1861                  test.assertEqual('This is ', output_parent.text) 
1862                  output_parent.text += '*-%s-*' % content[0] 
1863   
1864          extensions = {("my", "par"): ExtMyPar(), ("my", "format"): ExtMyFormat()} 
1865          transform = etree.XSLT(style, extensions=extensions) 
1866          result = transform(tree) 
1867          self.assertEqual(['par', 'format'], calls) 
1868          self.assertEqual( 
1869              b'<p style="color:red">This is *-arbitrary-* text in a paragraph</p>\n', 
1870              etree.tostring(result)) 
1871   
1872   
1874      """XSLT tests for etree under Python 3""" 
1875   
1876      pytestmark = skipif('sys.version_info < (3,0)') 
1877   
1879          tree = self.parse('<a><b>B</b><c>C</c></a>') 
1880          style = self.parse('''\ 
1881  <xsl:stylesheet version="1.0" 
1882      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1883    <xsl:template match="*" /> 
1884    <xsl:template match="/"> 
1885      <foo><xsl:value-of select="/a/b/text()" /></foo> 
1886    </xsl:template> 
1887  </xsl:stylesheet>''') 
1888   
1889          st = etree.XSLT(style) 
1890          res = st(tree) 
1891          self.assertEqual(_bytes('''\ 
1892  <?xml version="1.0"?> 
1893  <foo>B</foo> 
1894  '''), 
1895                            bytes(res)) 
 1896   
1898          tree = self.parse('<a><b>B</b><c>C</c></a>') 
1899          style = self.parse('''\ 
1900  <xsl:stylesheet version="1.0" 
1901      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1902    <xsl:template match="*" /> 
1903    <xsl:template match="/"> 
1904      <foo><xsl:value-of select="/a/b/text()" /></foo> 
1905    </xsl:template> 
1906  </xsl:stylesheet>''') 
1907   
1908          st = etree.XSLT(style) 
1909          res = st(tree) 
1910          self.assertEqual(_bytes('''\ 
1911  <?xml version="1.0"?> 
1912  <foo>B</foo> 
1913  '''), 
1914                            bytearray(res)) 
 1915   
1917          tree = self.parse('<a><b>B</b><c>C</c></a>') 
1918          style = self.parse('''\ 
1919  <xsl:stylesheet version="1.0" 
1920      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1921    <xsl:template match="*" /> 
1922    <xsl:template match="/"> 
1923      <foo><xsl:value-of select="/a/b/text()" /></foo> 
1924    </xsl:template> 
1925  </xsl:stylesheet>''') 
1926   
1927          st = etree.XSLT(style) 
1928          res = st(tree) 
1929          self.assertEqual(_bytes('''\ 
1930  <?xml version="1.0"?> 
1931  <foo>B</foo> 
1932  '''), 
1933                            bytes(memoryview(res))) 
  1934   
1935   
1949   
1950  if __name__ == '__main__': 
1951      print('to test use test.py %s' % __file__) 
1952