1   
   2   
   3  """ 
   4  Test cases related to XSLT processing 
   5  """ 
   6   
   7  import io 
   8  import sys 
   9  import copy 
  10  import gzip 
  11  import os.path 
  12  import unittest 
  13  import contextlib 
  14  from textwrap import dedent 
  15  from tempfile import NamedTemporaryFile 
  16   
  17  this_dir = os.path.dirname(__file__) 
  18  if this_dir not in sys.path: 
  19      sys.path.insert(0, this_dir)  
  20   
  21  is_python3 = sys.version_info[0] >= 3 
  22   
  23  try: 
  24      unicode 
  25  except NameError:  
  26      unicode = str 
  27   
  28  try: 
  29      basestring 
  30  except NameError:  
  31      basestring = str 
  32   
  33  from .common_imports import etree, BytesIO, HelperTestCase, fileInTestDir 
  34  from .common_imports import doctest, _bytes, _str, make_doctest, skipif 
  37      """XSLT tests etree""" 
  38           
  40          tree = self.parse('<a><b>B</b><c>C</c></a>') 
  41          style = self.parse('''\ 
  42  <xsl:stylesheet version="1.0" 
  43      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
  44    <xsl:template match="*" /> 
  45    <xsl:template match="/"> 
  46      <foo><xsl:value-of select="/a/b/text()" /></foo> 
  47    </xsl:template> 
  48  </xsl:stylesheet>''') 
  49   
  50          st = etree.XSLT(style) 
  51          res = st(tree) 
  52          self.assertEqual('''\ 
  53  <?xml version="1.0"?> 
  54  <foo>B</foo> 
  55  ''', 
  56                            str(res)) 
   57   
  60   
  63   
  65          style = self.parse('''\ 
  66  <xsl:stylesheet version="1.0" 
  67          xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
  68      <xsl:stylesheet /> 
  69  </xsl:stylesheet>''') 
  70   
  71          self.assertRaises( 
  72              etree.XSLTParseError, etree.XSLT, style) 
   73   
  75          tree = self.parse('<a><b>B</b><c>C</c></a>') 
  76          style = self.parse('''\ 
  77  <xsl:stylesheet version="1.0" 
  78      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
  79    <xsl:template match="*" /> 
  80    <xsl:template match="/"> 
  81      <foo><xsl:value-of select="/a/b/text()" /></foo> 
  82    </xsl:template> 
  83  </xsl:stylesheet>''') 
  84   
  85          transform = etree.XSLT(style) 
  86          res = transform(tree) 
  87          self.assertEqual('''\ 
  88  <?xml version="1.0"?> 
  89  <foo>B</foo> 
  90  ''', 
  91                            str(res)) 
  92   
  93          transform_copy = copy.deepcopy(transform) 
  94          res = transform_copy(tree) 
  95          self.assertEqual('''\ 
  96  <?xml version="1.0"?> 
  97  <foo>B</foo> 
  98  ''', 
  99                            str(res)) 
 100   
 101          transform = etree.XSLT(style) 
 102          res = transform(tree) 
 103          self.assertEqual('''\ 
 104  <?xml version="1.0"?> 
 105  <foo>B</foo> 
 106  ''', 
 107                            str(res)) 
  108   
 109      @contextlib.contextmanager 
 110 -    def _xslt_setup( 
 111              self, encoding='UTF-16', expected_encoding=None, 
 112              expected="""<?xml version="1.0" encoding="%(ENCODING)s"?><foo>\\uF8D2</foo>"""): 
  113          tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>' 
 114                                   ).decode("unicode_escape")) 
 115          style = self.parse('''\ 
 116  <xsl:stylesheet version="1.0" 
 117      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 118    <xsl:output encoding="%(ENCODING)s"/> 
 119    <xsl:template match="/"> 
 120      <foo><xsl:value-of select="/a/b/text()" /></foo> 
 121    </xsl:template> 
 122  </xsl:stylesheet>''' % {'ENCODING': encoding}) 
 123   
 124          st = etree.XSLT(style) 
 125          res = st(tree) 
 126          expected = _bytes(dedent(expected).strip()).decode("unicode_escape").replace('\n', '') % { 
 127              'ENCODING': expected_encoding or encoding, 
 128          } 
 129   
 130          data = [res] 
 131          yield data 
 132          self.assertEqual(expected, data[0].replace('\n', '')) 
  133   
 135          with self._xslt_setup(encoding='UTF-8') as res: 
 136              res[0] = unicode(bytes(res[0]), 'UTF-8') 
 137              assert 'UTF-8' in res[0] 
  138   
 140          with self._xslt_setup() as res: 
 141              res[0] = unicode(bytes(res[0]), 'UTF-16') 
 142              assert 'UTF-16' in res[0] 
  143   
 145          with self._xslt_setup(encoding='UTF-8', expected_encoding='UTF-16') as res: 
 146              f = BytesIO() 
 147              res[0].write(f, encoding='UTF-16') 
 148              if is_python3: 
 149                  output = str(f.getvalue(), 'UTF-16') 
 150              else: 
 151                  output = unicode(str(f.getvalue()), 'UTF-16') 
 152              res[0] = output.replace("'", '"') 
  153   
 155          with self._xslt_setup() as res: 
 156              f = BytesIO() 
 157              res[0].write_output(f) 
 158              res[0] = f.getvalue().decode('UTF-16') 
  159   
 161          class Writer(object): 
 162              def write(self, data): 
 163                  raise ValueError("FAILED!") 
   164   
 165          try: 
 166              with self._xslt_setup() as res: 
 167                  res[0].write_output(Writer()) 
 168          except ValueError as exc: 
 169              self.assertTrue("FAILED!" in str(exc), exc) 
 170          else: 
 171              self.assertTrue(False, "exception not raised") 
 172   
 174          with self._xslt_setup() as res: 
 175              f = NamedTemporaryFile(delete=False) 
 176              try: 
 177                  try: 
 178                      res[0].write_output(f) 
 179                  finally: 
 180                      f.close() 
 181                  with io.open(f.name, encoding='UTF-16') as f: 
 182                      res[0] = f.read() 
 183              finally: 
 184                  os.unlink(f.name) 
  185   
 187          with self._xslt_setup() as res: 
 188              f = NamedTemporaryFile(delete=False) 
 189              try: 
 190                  try: 
 191                      res[0].write_output(f.name, compression=9) 
 192                  finally: 
 193                      f.close() 
 194                  with contextlib.closing(gzip.GzipFile(f.name)) as f: 
 195                      res[0] = f.read().decode("UTF-16") 
 196              finally: 
 197                  os.unlink(f.name) 
  198   
 200          expected = ''' 
 201              <?xml version="1.0"?> 
 202              <foo>\\uF8D2</foo> 
 203          ''' 
 204          with self._xslt_setup(expected=expected) as res: 
 205              res[0] = unicode(res[0]) 
  206   
 208          tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>' 
 209          ).decode("unicode_escape")) 
 210          style = self.parse('''\ 
 211  <xsl:stylesheet version="1.0" 
 212      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 213    <xsl:output encoding="UTF-16" standalone="no"/> 
 214    <xsl:template match="/"> 
 215      <foo><xsl:value-of select="/a/b/text()" /></foo> 
 216    </xsl:template> 
 217  </xsl:stylesheet>''') 
 218   
 219          st = etree.XSLT(style) 
 220          res = st(tree) 
 221          expected = _bytes('''\ 
 222  <?xml version="1.0" standalone="no"?> 
 223  <foo>\\uF8D2</foo> 
 224  ''').decode("unicode_escape") 
 225          self.assertEqual(expected, 
 226                           unicode(res)) 
  227   
 240   
 257   
 259          style = self.parse('''\ 
 260  <xsl:stylesheet version="1.0" 
 261      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 262      <xsl:foo /> 
 263  </xsl:stylesheet>''') 
 264          self.assertRaises(etree.XSLTParseError, 
 265                            etree.XSLT, style) 
  266   
 268          tree = self.parse('<a/>') 
 269          style = self.parse('''\ 
 270  <xsl:stylesheet version="1.0" 
 271      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 272      <xsl:foo /> 
 273  </xsl:stylesheet>''') 
 274          self.assertRaises(etree.XSLTParseError, 
 275                            etree.XSLT, style) 
 276          exc = None 
 277          try: 
 278              etree.XSLT(style) 
 279          except etree.XSLTParseError as e: 
 280              exc = e 
 281          else: 
 282              self.assertFalse(True, "XSLT processing should have failed but didn't") 
 283          self.assertTrue(exc is not None) 
 284          self.assertTrue(len(exc.error_log)) 
 285          for error in exc.error_log: 
 286              self.assertTrue(':ERROR:XSLT:' in str(error)) 
  287   
 289          tree = self.parse('<a/>') 
 290          style = self.parse('''\ 
 291  <xsl:stylesheet version="1.0" 
 292      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 293      <xsl:template match="a"> 
 294          <xsl:copy> 
 295              <xsl:message terminate="yes">FAIL</xsl:message> 
 296          </xsl:copy> 
 297      </xsl:template> 
 298  </xsl:stylesheet>''') 
 299          self.assertRaises(etree.XSLTApplyError, 
 300                            etree.XSLT(style), tree) 
 301   
 302          transform = etree.XSLT(style) 
 303          exc = None 
 304          try: 
 305              transform(tree) 
 306          except etree.XSLTApplyError as e: 
 307              exc = e 
 308          else: 
 309              self.assertFalse(True, "XSLT processing should have failed but didn't") 
 310   
 311          self.assertTrue(exc is not None) 
 312          self.assertTrue(len(exc.error_log)) 
 313          self.assertEqual(len(transform.error_log), len(exc.error_log)) 
 314          for error in exc.error_log: 
 315              self.assertTrue(':ERROR:XSLT:' in str(error)) 
 316          for error in transform.error_log: 
 317              self.assertTrue(':ERROR:XSLT:' in str(error)) 
  318   
 320          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 321          style = self.parse('''\ 
 322  <xsl:stylesheet version="1.0" 
 323      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 324    <xsl:template match="/"> 
 325      <foo><xsl:value-of select="$bar" /></foo> 
 326    </xsl:template> 
 327  </xsl:stylesheet>''') 
 328   
 329          st = etree.XSLT(style) 
 330          res = st(tree, bar="'Bar'") 
 331          self.assertEqual('''\ 
 332  <?xml version="1.0"?> 
 333  <foo>Bar</foo> 
 334  ''', 
 335                            str(res)) 
  336   
 338          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 339          style = self.parse('''\ 
 340  <xsl:stylesheet version="1.0" 
 341      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 342    <xsl:template match="/"> 
 343      <foo><xsl:value-of select="$bar" /></foo> 
 344    </xsl:template> 
 345  </xsl:stylesheet>''') 
 346   
 347          st = etree.XSLT(style) 
 348          res = st(tree, bar=etree.XSLT.strparam('''it's me, "Bar"''')) 
 349          self.assertEqual('''\ 
 350  <?xml version="1.0"?> 
 351  <foo>it's me, "Bar"</foo> 
 352  ''', 
 353                            str(res)) 
  354   
 356          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 357          style = self.parse('''\ 
 358  <xsl:stylesheet version="1.0" 
 359      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 360    <xsl:param name="bar"/> 
 361    <xsl:template match="/"> 
 362      <foo><xsl:value-of select="$bar" /></foo> 
 363    </xsl:template> 
 364  </xsl:stylesheet>''') 
 365   
 366          st = etree.XSLT(style) 
 367          res = self.assertRaises(etree.XSLTApplyError, 
 368                                  st, tree, bar="<test/>") 
 369          res = self.assertRaises(etree.XSLTApplyError, 
 370                                  st, tree, bar="....") 
  371   
 373           
 374          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 375          style = self.parse('''\ 
 376  <xsl:stylesheet version="1.0" 
 377      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 378    <xsl:template match="/"> 
 379      <foo><xsl:value-of select="$bar" /></foo> 
 380    </xsl:template> 
 381  </xsl:stylesheet>''') 
 382   
 383          st = etree.XSLT(style) 
 384           
 385          self.assertRaises(etree.XSLTApplyError, st.apply, tree) 
  386   
 388          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 389          style = self.parse('''\ 
 390  <xsl:stylesheet version="1.0" 
 391      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 392    <xsl:template match="*" /> 
 393    <xsl:template match="/"> 
 394      <foo><xsl:value-of select="$bar" /></foo> 
 395      <foo><xsl:value-of select="$baz" /></foo> 
 396    </xsl:template> 
 397  </xsl:stylesheet>''') 
 398   
 399          st = etree.XSLT(style) 
 400          res = st(tree, bar="'Bar'", baz="'Baz'") 
 401          self.assertEqual('''\ 
 402  <?xml version="1.0"?> 
 403  <foo>Bar</foo><foo>Baz</foo> 
 404  ''', 
 405                            str(res)) 
  406           
 408          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 409          style = self.parse('''\ 
 410  <xsl:stylesheet version="1.0" 
 411      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 412    <xsl:template match="*" /> 
 413    <xsl:template match="/"> 
 414      <foo><xsl:value-of select="$bar" /></foo> 
 415    </xsl:template> 
 416  </xsl:stylesheet>''') 
 417   
 418          st = etree.XSLT(style) 
 419          res = st(tree, bar="/a/b/text()") 
 420          self.assertEqual('''\ 
 421  <?xml version="1.0"?> 
 422  <foo>B</foo> 
 423  ''', 
 424                            str(res)) 
  425   
 427          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 428          style = self.parse('''\ 
 429  <xsl:stylesheet version="1.0" 
 430      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 431    <xsl:template match="*" /> 
 432    <xsl:template match="/"> 
 433      <foo><xsl:value-of select="$bar" /></foo> 
 434    </xsl:template> 
 435  </xsl:stylesheet>''') 
 436   
 437          st = etree.XSLT(style) 
 438          res = st(tree, bar=etree.XPath("/a/b/text()")) 
 439          self.assertEqual('''\ 
 440  <?xml version="1.0"?> 
 441  <foo>B</foo> 
 442  ''', 
 443                            str(res)) 
  444           
 446          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 447          style = self.parse('''\ 
 448  <xsl:stylesheet version="1.0" 
 449      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 450    <xsl:param name="bar" select="'Default'" /> 
 451    <xsl:template match="*" /> 
 452    <xsl:template match="/"> 
 453      <foo><xsl:value-of select="$bar" /></foo> 
 454    </xsl:template> 
 455  </xsl:stylesheet>''') 
 456   
 457          st = etree.XSLT(style) 
 458          res = st(tree, bar="'Bar'") 
 459          self.assertEqual('''\ 
 460  <?xml version="1.0"?> 
 461  <foo>Bar</foo> 
 462  ''', 
 463                            str(res)) 
 464          res = st(tree) 
 465          self.assertEqual('''\ 
 466  <?xml version="1.0"?> 
 467  <foo>Default</foo> 
 468  ''', 
 469                            str(res)) 
  470           
 472          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 473          style = self.parse('''\ 
 474  <xsl:stylesheet version="1.0" 
 475      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 476    <xsl:output method="html"/> 
 477    <xsl:strip-space elements="*"/> 
 478    <xsl:template match="/"> 
 479      <html><body><xsl:value-of select="/a/b/text()" /></body></html> 
 480    </xsl:template> 
 481  </xsl:stylesheet>''') 
 482   
 483          st = etree.XSLT(style) 
 484          res = st(tree) 
 485          self.assertEqual('<html><body>B</body></html>', 
 486                            str(res).strip()) 
  487   
 491   
 497   
 520   
 545   
 547           
 548          xml = '<blah/>' 
 549          xslt = ''' 
 550          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
 551            <xsl:template match="/" /> 
 552          </xsl:stylesheet> 
 553          ''' 
 554   
 555          source = self.parse(xml) 
 556          styledoc = self.parse(xslt) 
 557          style = etree.XSLT(styledoc) 
 558          result = style(source) 
 559          self.assertEqual('', str(result)) 
  560   
 562          xml = '<blah/>' 
 563          xslt = ''' 
 564          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
 565            <xsl:template match="/"> 
 566              <xsl:message>TEST TEST TEST</xsl:message> 
 567            </xsl:template> 
 568          </xsl:stylesheet> 
 569          ''' 
 570   
 571          source = self.parse(xml) 
 572          styledoc = self.parse(xslt) 
 573          style = etree.XSLT(styledoc) 
 574          result = style(source) 
 575          self.assertEqual('', str(result)) 
 576          self.assertTrue("TEST TEST TEST" in [entry.message 
 577                                            for entry in style.error_log]) 
  578   
 580          xml = '<blah/>' 
 581          xslt = ''' 
 582          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
 583            <xsl:template match="/"> 
 584              <xsl:message terminate="yes">TEST TEST TEST</xsl:message> 
 585            </xsl:template> 
 586          </xsl:stylesheet> 
 587          ''' 
 588   
 589          source = self.parse(xml) 
 590          styledoc = self.parse(xslt) 
 591          style = etree.XSLT(styledoc) 
 592   
 593          self.assertRaises(etree.XSLTApplyError, style, source) 
 594          self.assertTrue("TEST TEST TEST" in [entry.message 
 595                                            for entry in style.error_log]) 
  596   
 598          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 599          style = self.parse('''\ 
 600  <xsl:stylesheet version="1.0" 
 601      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 602    <xsl:template match="*" /> 
 603    <xsl:template match="/"> 
 604      <doc> 
 605      <foo><xsl:value-of select="$bar" /></foo> 
 606      <foo><xsl:value-of select="$baz" /></foo> 
 607      </doc> 
 608    </xsl:template> 
 609  </xsl:stylesheet>''') 
 610   
 611          result = tree.xslt(style, bar="'Bar'", baz="'Baz'") 
 612          self.assertEqual( 
 613              _bytes('<doc><foo>Bar</foo><foo>Baz</foo></doc>'), 
 614              etree.tostring(result.getroot())) 
  615           
 617          tree = self.parse('<a><b>B</b><c>C</c></a>') 
 618          style = self.parse('''\ 
 619  <xsl:stylesheet version="1.0" 
 620      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 621    <xsl:template match="a"><A><xsl:apply-templates/></A></xsl:template> 
 622    <xsl:template match="b"><B><xsl:apply-templates/></B></xsl:template> 
 623    <xsl:template match="c"><C><xsl:apply-templates/></C></xsl:template> 
 624  </xsl:stylesheet>''') 
 625   
 626          self.assertEqual(self._rootstring(tree), 
 627                            _bytes('<a><b>B</b><c>C</c></a>')) 
 628          result = tree.xslt(style) 
 629          self.assertEqual(self._rootstring(tree), 
 630                            _bytes('<a><b>B</b><c>C</c></a>')) 
 631          self.assertEqual(self._rootstring(result), 
 632                            _bytes('<A><B>B</B><C>C</C></A>')) 
 633   
 634          b_tree = etree.ElementTree(tree.getroot()[0]) 
 635          self.assertEqual(self._rootstring(b_tree), 
 636                            _bytes('<b>B</b>')) 
 637          result = b_tree.xslt(style) 
 638          self.assertEqual(self._rootstring(tree), 
 639                            _bytes('<a><b>B</b><c>C</c></a>')) 
 640          self.assertEqual(self._rootstring(result), 
 641                            _bytes('<B>B</B>')) 
 642   
 643          c_tree = etree.ElementTree(tree.getroot()[1]) 
 644          self.assertEqual(self._rootstring(c_tree), 
 645                            _bytes('<c>C</c>')) 
 646          result = c_tree.xslt(style) 
 647          self.assertEqual(self._rootstring(tree), 
 648                            _bytes('<a><b>B</b><c>C</c></a>')) 
 649          self.assertEqual(self._rootstring(result), 
 650                            _bytes('<C>C</C>')) 
  651   
 653           
 654          xslt = etree.XSLT(etree.XML("""\ 
 655  <xsl:stylesheet version="1.0" 
 656     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 657    <xsl:template match="/"> 
 658      <test>TEXT<xsl:copy-of select="document('')//test"/></test> 
 659    </xsl:template> 
 660  </xsl:stylesheet> 
 661  """)) 
 662          result = xslt(etree.XML('<a/>')) 
 663          root = result.getroot() 
 664          self.assertEqual(root.tag, 
 665                            'test') 
 666          self.assertEqual(root[0].tag, 
 667                            'test') 
 668          self.assertEqual(root[0].text, 
 669                            'TEXT') 
 670          self.assertEqual(root[0][0].tag, 
 671                            '{http://www.w3.org/1999/XSL/Transform}copy-of') 
  672   
 682   
 692   
 694          xslt = etree.XSLT(etree.XML("""\ 
 695  <xsl:stylesheet version="1.0" 
 696     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 697    <xsl:template match="/"> 
 698      <test>TEXT<xsl:copy-of select="document('uri:__junkfood__is__evil__')//test"/></test> 
 699    </xsl:template> 
 700  </xsl:stylesheet> 
 701  """)) 
 702   
 703          errors = None 
 704          try: 
 705              xslt(etree.XML('<a/>')) 
 706          except etree.XSLTApplyError as exc: 
 707              errors = exc.error_log 
 708          else: 
 709              self.assertFalse(True, "XSLT processing should have failed but didn't") 
 710   
 711          self.assertTrue(len(errors)) 
 712          for error in errors: 
 713              if ':ERROR:XSLT:' in str(error): 
 714                  break 
 715          else: 
 716              self.assertFalse(True, 'No XSLT errors found in error log:\n%s' % errors) 
  717   
 719           
 720          assertEqual = self.assertEqual 
 721          called = {'count' : 0} 
 722          class TestResolver(etree.Resolver): 
 723              def resolve(self, url, id, context): 
 724                  assertEqual(url, 'file://ANYTHING') 
 725                  called['count'] += 1 
 726                  return self.resolve_string('<CALLED/>', context) 
  727   
 728          parser = etree.XMLParser() 
 729          parser.resolvers.add(TestResolver()) 
 730   
 731          xslt = etree.XSLT(etree.XML(_bytes("""\ 
 732  <xsl:stylesheet version="1.0" 
 733     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 734     xmlns:l="local"> 
 735    <xsl:template match="/"> 
 736      <test> 
 737        <xsl:for-each select="document('')//l:data/l:entry"> 
 738          <xsl:copy-of select="document('file://ANYTHING')"/> 
 739          <xsl:copy> 
 740            <xsl:attribute name="value"> 
 741              <xsl:value-of select="."/> 
 742            </xsl:attribute> 
 743          </xsl:copy> 
 744        </xsl:for-each> 
 745      </test> 
 746    </xsl:template> 
 747    <l:data> 
 748      <l:entry>A</l:entry> 
 749      <l:entry>B</l:entry> 
 750    </l:data> 
 751  </xsl:stylesheet> 
 752  """), parser)) 
 753   
 754          self.assertEqual(called['count'], 0) 
 755          result = xslt(etree.XML('<a/>')) 
 756          self.assertEqual(called['count'], 1) 
 757   
 758          root = result.getroot() 
 759          self.assertEqual(root.tag, 
 760                            'test') 
 761          self.assertEqual(len(root), 4) 
 762   
 763          self.assertEqual(root[0].tag, 
 764                            'CALLED') 
 765          self.assertEqual(root[1].tag, 
 766                            '{local}entry') 
 767          self.assertEqual(root[1].text, 
 768                            None) 
 769          self.assertEqual(root[1].get("value"), 
 770                            'A') 
 771          self.assertEqual(root[2].tag, 
 772                            'CALLED') 
 773          self.assertEqual(root[3].tag, 
 774                            '{local}entry') 
 775          self.assertEqual(root[3].text, 
 776                            None) 
 777          self.assertEqual(root[3].get("value"), 
 778                            'B') 
 779   
 781          assertEqual = self.assertEqual 
 782          called = {'count' : 0} 
 783          expected_url = None 
 784          class TestResolver(etree.Resolver): 
 785              def resolve(self, url, id, context): 
 786                  assertEqual(url, expected_url) 
 787                  called['count'] += 1 
 788                  return self.resolve_string('<CALLED/>', context) 
  789   
 790          stylesheet_xml = _bytes("""\ 
 791  <xsl:stylesheet version="1.0" 
 792     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
 793     xmlns:l="local"> 
 794    <xsl:template match="/"> 
 795      <xsl:copy-of select="document('test.xml')"/> 
 796    </xsl:template> 
 797  </xsl:stylesheet> 
 798  """) 
 799   
 800          parser = etree.XMLParser() 
 801          parser.resolvers.add(TestResolver()) 
 802   
 803           
 804          expected_url = 'test.xml' 
 805          xslt = etree.XSLT(etree.XML(stylesheet_xml, parser)) 
 806   
 807          self.assertEqual(called['count'], 0) 
 808          result = xslt(etree.XML('<a/>')) 
 809          self.assertEqual(called['count'], 1) 
 810   
 811           
 812          called['count'] = 0 
 813          expected_url = 'MY/BASE/test.xml'   
 814          xslt = etree.XSLT(etree.XML( 
 815              stylesheet_xml, parser, 
 816              base_url=os.path.join('MY', 'BASE', 'FILE'))) 
 817   
 818          self.assertEqual(called['count'], 0) 
 819          result = xslt(etree.XML('<a/>')) 
 820          self.assertEqual(called['count'], 1) 
 821   
 822           
 823          called['count'] = 0 
 824          expected_url = 'http://server.com/BASE/DIR/test.xml' 
 825          xslt = etree.XSLT(etree.XML( 
 826              stylesheet_xml, parser, 
 827              base_url='http://server.com/BASE/DIR/FILE')) 
 828   
 829          self.assertEqual(called['count'], 0) 
 830          result = xslt(etree.XML('<a/>')) 
 831          self.assertEqual(called['count'], 1) 
 832   
 833           
 834          called['count'] = 0 
 835          expected_url = 'file://BASE/DIR/test.xml' 
 836          xslt = etree.XSLT(etree.XML( 
 837              stylesheet_xml, parser, 
 838              base_url='file://BASE/DIR/FILE')) 
 839   
 840          self.assertEqual(called['count'], 0) 
 841          result = xslt(etree.XML('<a/>')) 
 842          self.assertEqual(called['count'], 1) 
 843   
 854   
 860   
 866   
 875   
 877          root = etree.XML(_bytes('''\ 
 878          <transform> 
 879            <widget displayType="fieldset"/> 
 880          </transform>''')) 
 881   
 882          xslt = etree.XSLT(etree.XML(_bytes('''\ 
 883          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 884            <xsl:output method="html" indent="no"/> 
 885            <xsl:template match="/"> 
 886              <html> 
 887                <xsl:apply-templates/> 
 888              </html> 
 889            </xsl:template> 
 890   
 891            <xsl:template match="widget"> 
 892              <xsl:element name="{@displayType}"/> 
 893            </xsl:template> 
 894   
 895          </xsl:stylesheet>'''))) 
 896   
 897          result = xslt(root[0]) 
 898          root[:] = result.getroot()[:] 
 899          del root  
  900           
 902          tree = self.parse('''\ 
 903  <?xml version="1.0"?> 
 904  <?xml-stylesheet type="text/xsl" href="%s"?> 
 905  <a> 
 906    <b>B</b> 
 907    <c>C</c> 
 908  </a>''' % fileInTestDir("test1.xslt")) 
 909   
 910          style_root = tree.getroot().getprevious().parseXSL().getroot() 
 911          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 
 912                            style_root.tag) 
  913   
 915           
 916          tree = self.parse('''\ 
 917  <?xml version="1.0"?> 
 918  <?xml-stylesheet type="text/xsl" href="#style"?> 
 919  <a> 
 920    <b>B</b> 
 921    <c>C</c> 
 922    <xsl:stylesheet version="1.0" xml:id="style" 
 923        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 924      <xsl:template match="*" /> 
 925      <xsl:template match="/"> 
 926        <foo><xsl:value-of select="/a/b/text()" /></foo> 
 927      </xsl:template> 
 928    </xsl:stylesheet> 
 929  </a>''') 
 930   
 931          style_root = tree.getroot().getprevious().parseXSL().getroot() 
 932          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 
 933                            style_root.tag) 
 934   
 935          st = etree.XSLT(style_root) 
 936          res = st(tree) 
 937          self.assertEqual('''\ 
 938  <?xml version="1.0"?> 
 939  <foo>B</foo> 
 940  ''', 
 941                            str(res)) 
  942   
 944           
 945          tree = self.parse('''\ 
 946  <?xml version="1.0"?> 
 947  <?xml-stylesheet type="text/xsl" href="#style"?> 
 948  <a> 
 949    <b>B</b> 
 950    <c>C</c> 
 951  </a>''') 
 952   
 953          style = self.parse('''\ 
 954  <xsl:stylesheet version="1.0" xml:id="style" 
 955      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 956    <xsl:template match="*" /> 
 957    <xsl:template match="/"> 
 958      <foo><xsl:value-of select="/a/b/text()" /></foo> 
 959    </xsl:template> 
 960  </xsl:stylesheet> 
 961  ''') 
 962   
 963          tree.getroot().append(style.getroot()) 
 964   
 965          style_root = tree.getroot().getprevious().parseXSL().getroot() 
 966          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet", 
 967                            style_root.tag) 
 968   
 969          st = etree.XSLT(style_root) 
 970          res = st(tree) 
 971          self.assertEqual('''\ 
 972  <?xml version="1.0"?> 
 973  <foo>B</foo> 
 974  ''', 
 975                            str(res)) 
  976   
 978          tree = self.parse('''\ 
 979  <?xml version="1.0"?> 
 980  <?xml-stylesheet type="text/xsl" href="TEST"?> 
 981  <a> 
 982    <b>B</b> 
 983    <c>C</c> 
 984  </a>''') 
 985   
 986          pi = tree.getroot().getprevious() 
 987          self.assertEqual("TEST", pi.get("href")) 
  988   
 990          tree = self.parse('''\ 
 991  <?xml version="1.0"?> 
 992  <?xml-stylesheet type="text/xsl" href="TEST"?> 
 993  <a> 
 994    <b>B</b> 
 995    <c>C</c> 
 996  </a>''') 
 997   
 998          pi = tree.getroot().getprevious() 
 999          self.assertEqual("TEST", pi.get("href")) 
1000          self.assertEqual("text/xsl", pi.get("type")) 
1001          self.assertEqual(None, pi.get("motz")) 
 1002   
1004          tree = self.parse('''\ 
1005  <?xml version="1.0"?> 
1006  <?xml-stylesheet href="TEST" type="text/xsl"?> 
1007  <a> 
1008    <b>B</b> 
1009    <c>C</c> 
1010  </a>''') 
1011   
1012          pi = tree.getroot().getprevious() 
1013          self.assertEqual("TEST", pi.get("href")) 
1014          self.assertEqual("text/xsl", pi.get("type")) 
1015          self.assertEqual(None, pi.get("motz")) 
 1016   
1018          tree = self.parse('''\ 
1019  <?xml version="1.0"?> 
1020  <?xml-stylesheet type="text/xsl" href="TEST"?> 
1021  <a> 
1022    <b>B</b> 
1023    <c>C</c> 
1024  </a>''') 
1025   
1026          pi = tree.getroot().getprevious() 
1027          self.assertEqual(None, pi.get("unknownattribute")) 
 1028   
1030          tree = self.parse('''\ 
1031  <?xml version="1.0"?> 
1032  <?xml-stylesheet type="text/xsl" href="TEST"?> 
1033  <a> 
1034    <b>B</b> 
1035    <c>C</c> 
1036  </a>''') 
1037   
1038          pi = tree.getroot().getprevious() 
1039          self.assertEqual("TEST", pi.get("href")) 
1040   
1041          pi.set("href", "TEST123") 
1042          self.assertEqual("TEST123", pi.get("href")) 
 1043   
1045          tree = self.parse('''\ 
1046  <?xml version="1.0"?> 
1047  <?xml-stylesheet type="text/xsl"?> 
1048  <a> 
1049    <b>B</b> 
1050    <c>C</c> 
1051  </a>''') 
1052   
1053          pi = tree.getroot().getprevious() 
1054          self.assertEqual(None, pi.get("href")) 
1055   
1056          pi.set("href", "TEST") 
1057          self.assertEqual("TEST", pi.get("href")) 
 1058   
1060      """EXSLT tests""" 
1061   
1063          tree = self.parse('<a><b>B</b><c>C</c></a>') 
1064          style = self.parse('''\ 
1065  <xsl:stylesheet version="1.0" 
1066      xmlns:str="http://exslt.org/strings" 
1067      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1068      exclude-result-prefixes="str xsl"> 
1069    <xsl:template match="text()"> 
1070      <xsl:value-of select="str:align(string(.), '***', 'center')" /> 
1071    </xsl:template> 
1072    <xsl:template match="*"> 
1073      <xsl:copy> 
1074        <xsl:apply-templates/> 
1075      </xsl:copy> 
1076    </xsl:template> 
1077  </xsl:stylesheet>''') 
1078   
1079          st = etree.XSLT(style) 
1080          res = st(tree) 
1081          self.assertEqual('''\ 
1082  <?xml version="1.0"?> 
1083  <a><b>*B*</b><c>*C*</c></a> 
1084  ''', 
1085                            str(res)) 
 1086   
1088          tree = self.parse('<a><b>B</b><c>C</c></a>') 
1089          style = self.parse('''\ 
1090            <xsl:stylesheet version = "1.0" 
1091                xmlns:xsl='http://www.w3.org/1999/XSL/Transform' 
1092                xmlns:str="http://exslt.org/strings" 
1093                extension-element-prefixes="str"> 
1094   
1095                <xsl:template match="/"> 
1096                  <h1 class="{str:replace('abc', 'b', 'x')}">test</h1> 
1097                </xsl:template> 
1098   
1099            </xsl:stylesheet>''') 
1100   
1101          st = etree.XSLT(style) 
1102          res = st(tree) 
1103          self.assertEqual(str(res), '''\ 
1104  <?xml version="1.0"?> 
1105  <h1 class="axc">test</h1> 
1106  ''') 
 1107   
1109          tree = self.parse('<a><b>B</b><c>C</c></a>') 
1110          style = self.parse('''\ 
1111  <xsl:stylesheet version="1.0" 
1112      xmlns:math="http://exslt.org/math" 
1113      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1114      exclude-result-prefixes="math xsl"> 
1115    <xsl:template match="*"> 
1116      <xsl:copy> 
1117        <xsl:attribute name="pi"> 
1118          <xsl:value-of select="math:constant('PI', count(*)+2)"/> 
1119        </xsl:attribute> 
1120        <xsl:apply-templates/> 
1121      </xsl:copy> 
1122    </xsl:template> 
1123  </xsl:stylesheet>''') 
1124   
1125          st = etree.XSLT(style) 
1126          res = st(tree) 
1127          self.assertEqual('''\ 
1128  <?xml version="1.0"?> 
1129  <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a> 
1130  ''', 
1131                            str(res)) 
 1132   
1134          xslt = etree.XSLT(etree.XML(_bytes("""\ 
1135  <xsl:stylesheet version="1.0" 
1136     xmlns:regexp="http://exslt.org/regular-expressions" 
1137     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1138    <xsl:template match="*"> 
1139      <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test> 
1140    </xsl:template> 
1141  </xsl:stylesheet> 
1142  """))) 
1143          result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>'))) 
1144          root = result.getroot() 
1145          self.assertEqual(root.tag, 
1146                            'test') 
1147          self.assertEqual(len(root), 1) 
1148          self.assertEqual(root[0].tag, 
1149                            'b') 
1150          self.assertEqual(root[0].text, 
1151                            '987') 
 1152   
1154          xslt = etree.XSLT(etree.XML("""\ 
1155  <xsl:stylesheet version="1.0" 
1156     xmlns:regexp="http://exslt.org/regular-expressions" 
1157     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1158    <xsl:template match="*"> 
1159      <test> 
1160        <xsl:copy-of select="regexp:replace(string(.), 'd.', '',   'XX')"/> 
1161        <xsl:text>-</xsl:text> 
1162        <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/> 
1163      </test> 
1164    </xsl:template> 
1165  </xsl:stylesheet> 
1166  """)) 
1167          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>'))) 
1168          root = result.getroot() 
1169          self.assertEqual(root.tag, 
1170                            'test') 
1171          self.assertEqual(len(root), 0) 
1172          self.assertEqual(root.text, 'abXXdEeDed-abXXXXeXXd') 
 1173   
1175          xslt = etree.XSLT(etree.XML("""\ 
1176  <xsl:stylesheet version="1.0" 
1177     xmlns:regexp="http://exslt.org/regular-expressions" 
1178     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1179    <xsl:template match="*"> 
1180      <test> 
1181        <test1><xsl:copy-of  select="regexp:match(string(.), 'd.')"/></test1> 
1182        <test2><xsl:copy-of  select="regexp:match(string(.), 'd.', 'g')"/></test2> 
1183        <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i> 
1184      </test> 
1185    </xsl:template> 
1186  </xsl:stylesheet> 
1187  """)) 
1188          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>'))) 
1189          root = result.getroot() 
1190          self.assertEqual(root.tag,  'test') 
1191          self.assertEqual(len(root), 3) 
1192   
1193          self.assertEqual(len(root[0]), 1) 
1194          self.assertEqual(root[0][0].tag, 'match') 
1195          self.assertEqual(root[0][0].text, 'dC') 
1196   
1197          self.assertEqual(len(root[1]), 2) 
1198          self.assertEqual(root[1][0].tag, 'match') 
1199          self.assertEqual(root[1][0].text, 'dC') 
1200          self.assertEqual(root[1][1].tag, 'match') 
1201          self.assertEqual(root[1][1].text, 'dE') 
1202   
1203          self.assertEqual(len(root[2]), 3) 
1204          self.assertEqual(root[2][0].tag, 'match') 
1205          self.assertEqual(root[2][0].text, 'dC') 
1206          self.assertEqual(root[2][1].tag, 'match') 
1207          self.assertEqual(root[2][1].text, 'dE') 
1208          self.assertEqual(root[2][2].tag, 'match') 
1209          self.assertEqual(root[2][2].text, 'De') 
 1210   
1212          xslt = etree.XSLT(etree.XML(_bytes("""\ 
1213  <xsl:stylesheet version="1.0" 
1214     xmlns:regexp="http://exslt.org/regular-expressions" 
1215     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1216    <xsl:template match="/"> 
1217      <test> 
1218        <xsl:for-each select="regexp:match( 
1219              '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )"> 
1220          <test1><xsl:value-of select="."/></test1> 
1221        </xsl:for-each> 
1222      </test> 
1223    </xsl:template> 
1224  </xsl:stylesheet> 
1225  """))) 
1226          result = xslt(etree.XML(_bytes('<a/>'))) 
1227          root = result.getroot() 
1228          self.assertEqual(root.tag,  'test') 
1229          self.assertEqual(len(root), 4) 
1230   
1231          self.assertEqual(root[0].text, "123abc567") 
1232          self.assertEqual(root[1].text, "123") 
1233          self.assertEqual(root[2].text, "abc") 
1234          self.assertEqual(root[3].text, "567") 
 1235   
1237           
1238          xslt = etree.XSLT(etree.XML(_bytes("""\ 
1239  <xsl:stylesheet version="1.0" 
1240     xmlns:regexp="http://exslt.org/regular-expressions" 
1241     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1242    <xsl:template match="/"> 
1243      <test> 
1244        <xsl:for-each select="regexp:match( 
1245              'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml', 
1246              '(\\w+):\\/\\/([^/:]+)(:\\d*)?([^# ]*)')"> 
1247          <test1><xsl:value-of select="."/></test1> 
1248        </xsl:for-each> 
1249      </test> 
1250    </xsl:template> 
1251  </xsl:stylesheet> 
1252  """))) 
1253          result = xslt(etree.XML(_bytes('<a/>'))) 
1254          root = result.getroot() 
1255          self.assertEqual(root.tag,  'test') 
1256          self.assertEqual(len(root), 5) 
1257   
1258          self.assertEqual( 
1259              root[0].text, 
1260              "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml") 
1261          self.assertEqual( 
1262              root[1].text, 
1263              "http") 
1264          self.assertEqual( 
1265              root[2].text, 
1266              "www.bayes.co.uk") 
1267          self.assertFalse(root[3].text) 
1268          self.assertEqual( 
1269              root[4].text, 
1270              "/xml/index.xml?/xml/utils/rechecker.xml") 
 1271   
1273           
1274          xslt = etree.XSLT(self.parse("""\ 
1275  <xsl:stylesheet version="1.0" 
1276     xmlns:regexp="http://exslt.org/regular-expressions" 
1277     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1278    <xsl:template match="/"> 
1279      <test> 
1280        <xsl:for-each select="regexp:match( 
1281              'This is a test string', '(\\w+)', 'g')"> 
1282          <test1><xsl:value-of select="."/></test1> 
1283        </xsl:for-each> 
1284      </test> 
1285    </xsl:template> 
1286  </xsl:stylesheet> 
1287  """)) 
1288          result = xslt(etree.XML(_bytes('<a/>'))) 
1289          root = result.getroot() 
1290          self.assertEqual(root.tag,  'test') 
1291          self.assertEqual(len(root), 5) 
1292   
1293          self.assertEqual(root[0].text, "This") 
1294          self.assertEqual(root[1].text, "is") 
1295          self.assertEqual(root[2].text, "a") 
1296          self.assertEqual(root[3].text, "test") 
1297          self.assertEqual(root[4].text, "string") 
 1298   
1300           
1301           
1302          xslt = etree.XSLT(etree.XML(_bytes("""\ 
1303  <xsl:stylesheet version="1.0" 
1304     xmlns:regexp="http://exslt.org/regular-expressions" 
1305     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1306    <xsl:template match="/"> 
1307      <test> 
1308        <xsl:for-each select="regexp:match( 
1309              'This is a test string', '([a-z])+ ', 'g')"> 
1310          <test1><xsl:value-of select="."/></test1> 
1311        </xsl:for-each> 
1312      </test> 
1313    </xsl:template> 
1314  </xsl:stylesheet> 
1315  """))) 
1316          result = xslt(etree.XML(_bytes('<a/>'))) 
1317          root = result.getroot() 
1318          self.assertEqual(root.tag,  'test') 
1319          self.assertEqual(len(root), 4) 
1320   
1321          self.assertEqual(root[0].text, "his") 
1322          self.assertEqual(root[1].text, "is") 
1323          self.assertEqual(root[2].text, "a") 
1324          self.assertEqual(root[3].text, "test") 
 1325   
1327           
1328           
1329          xslt = etree.XSLT(etree.XML(_bytes("""\ 
1330  <xsl:stylesheet version="1.0" 
1331     xmlns:regexp="http://exslt.org/regular-expressions" 
1332     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1333    <xsl:template match="/"> 
1334      <test> 
1335        <xsl:for-each select="regexp:match( 
1336              'This is a test string', '([a-z])+ ', 'gi')"> 
1337          <test1><xsl:value-of select="."/></test1> 
1338        </xsl:for-each> 
1339      </test> 
1340    </xsl:template> 
1341  </xsl:stylesheet> 
1342  """))) 
1343          result = xslt(etree.XML(_bytes('<a/>'))) 
1344          root = result.getroot() 
1345          self.assertEqual(root.tag,  'test') 
1346          self.assertEqual(len(root), 4) 
1347   
1348          self.assertEqual(root[0].text, "This") 
1349          self.assertEqual(root[1].text, "is") 
1350          self.assertEqual(root[2].text, "a") 
1351          self.assertEqual(root[3].text, "test") 
  1352   
1353   
1354 -class ETreeXSLTExtFuncTestCase(HelperTestCase): 
 1355      """Tests for XPath extension functions in XSLT.""" 
1356   
1357 -    def test_extensions1(self): 
 1358          tree = self.parse('<a><b>B</b></a>') 
1359          style = self.parse('''\ 
1360  <xsl:stylesheet version="1.0" 
1361      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1362      xmlns:myns="testns" 
1363      exclude-result-prefixes="myns"> 
1364    <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template> 
1365  </xsl:stylesheet>''') 
1366   
1367          def mytext(ctxt, values): 
1368              return 'X' * len(values) 
 1369   
1370          result = tree.xslt(style, {('testns', 'mytext') : mytext}) 
1371          self.assertEqual(self._rootstring(result), 
1372                            _bytes('<A>X</A>')) 
 1373   
1374 -    def test_extensions2(self): 
 1375          tree = self.parse('<a><b>B</b></a>') 
1376          style = self.parse('''\ 
1377  <xsl:stylesheet version="1.0" 
1378      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1379      xmlns:myns="testns" 
1380      exclude-result-prefixes="myns"> 
1381    <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template> 
1382  </xsl:stylesheet>''') 
1383   
1384          def mytext(ctxt, values): 
1385              return 'X' * len(values) 
 1386   
1387          namespace = etree.FunctionNamespace('testns') 
1388          namespace['mytext'] = mytext 
1389   
1390          result = tree.xslt(style) 
1391          self.assertEqual(self._rootstring(result), 
1392                            _bytes('<A>X</A>')) 
1393   
1395          tree = self.parse('<a><b>B</b><b/></a>') 
1396          style = self.parse('''\ 
1397  <xsl:stylesheet version="1.0" 
1398      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1399      xmlns:myns="testns" 
1400      exclude-result-prefixes="myns"> 
1401    <xsl:template match="a"> 
1402      <xsl:variable name="content"> 
1403         <xsl:apply-templates/> 
1404      </xsl:variable> 
1405      <A><xsl:value-of select="myns:mytext($content)"/></A> 
1406    </xsl:template> 
1407    <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template> 
1408  </xsl:stylesheet>''') 
1409   
1410          def mytext(ctxt, values): 
1411              for value in values: 
1412                  self.assertTrue(hasattr(value, 'tag'), 
1413                               "%s is not an Element" % type(value)) 
1414                  self.assertEqual(value.tag, 'b') 
1415                  self.assertEqual(value.text, 'BBB') 
1416              return 'X'.join([el.tag for el in values]) 
 1417   
1418          namespace = etree.FunctionNamespace('testns') 
1419          namespace['mytext'] = mytext 
1420   
1421          result = tree.xslt(style) 
1422          self.assertEqual(self._rootstring(result), 
1423                           _bytes('<A>bXb</A>')) 
1424   
1426          tree = self.parse('<a><b>B<c/>C</b><b/></a>') 
1427          style = self.parse('''\ 
1428  <xsl:stylesheet version="1.0" 
1429      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1430      xmlns:myns="testns" 
1431      exclude-result-prefixes="myns"> 
1432    <xsl:template match="b"> 
1433      <A><xsl:value-of select="myns:myext()"/></A> 
1434    </xsl:template> 
1435  </xsl:stylesheet>''') 
1436   
1437          def extfunc(ctxt): 
1438              text_content = ctxt.context_node.xpath('text()') 
1439              return 'x'.join(text_content) 
 1440   
1441          namespace = etree.FunctionNamespace('testns') 
1442          namespace['myext'] = extfunc 
1443   
1444          result = tree.xslt(style) 
1445          self.assertEqual(self._rootstring(result), 
1446                           _bytes('<A>BxC</A>')) 
1447   
1449           
1450          class Resolver(etree.Resolver): 
1451              def resolve(self, system_url, public_id, context): 
1452                  assert system_url == 'extdoc.xml' 
1453                  return self.resolve_string(b'<a><b>B<c/>C</b><b/></a>', context) 
 1454   
1455          parser = etree.XMLParser() 
1456          parser.resolvers.add(Resolver()) 
1457   
1458          tree = self.parse(b'<a><b/><b/></a>') 
1459          transform = etree.XSLT(self.parse(b'''\ 
1460  <xsl:stylesheet version="1.0" 
1461      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1462      xmlns:mypre="testns" 
1463      exclude-result-prefixes="mypre"> 
1464    <xsl:template match="b"> 
1465      <B><xsl:value-of select="mypre:myext()"/></B> 
1466    </xsl:template> 
1467    <xsl:template match="a"> 
1468      <A><xsl:apply-templates select="document('extdoc.xml')//b" /></A> 
1469    </xsl:template> 
1470  </xsl:stylesheet>''', parser=parser)) 
1471   
1472          def extfunc(ctxt): 
1473              text_content = ctxt.context_node.xpath('text()') 
1474              return 'x'.join(text_content) 
1475   
1476          namespace = etree.FunctionNamespace('testns') 
1477          namespace['myext'] = extfunc 
1478   
1479          result = transform(tree) 
1480          self.assertEqual(self._rootstring(result), 
1481                           _bytes('<A><B>BxC</B><B/></A>')) 
1482   
1483   
1484 -class ETreeXSLTExtElementTestCase(HelperTestCase): 
 1485      """Tests for extension elements in XSLT.""" 
1486   
1488          tree = self.parse('<a><b>B</b></a>') 
1489          style = self.parse('''\ 
1490  <xsl:stylesheet version="1.0" 
1491      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1492      xmlns:myns="testns" 
1493      extension-element-prefixes="myns" 
1494      exclude-result-prefixes="myns"> 
1495    <xsl:template match="a"> 
1496      <A><myns:myext>b</myns:myext></A> 
1497    </xsl:template> 
1498  </xsl:stylesheet>''') 
1499   
1500          class MyExt(etree.XSLTExtension): 
1501              def execute(self, context, self_node, input_node, output_parent): 
1502                  child = etree.Element(self_node.text) 
1503                  child.text = 'X' 
1504                  output_parent.append(child) 
  1505   
1506          extensions = { ('testns', 'myext') : MyExt() } 
1507   
1508          result = tree.xslt(style, extensions=extensions) 
1509          self.assertEqual(self._rootstring(result), 
1510                            _bytes('<A><b>X</b></A>')) 
1511   
1513          tree = self.parse('<a><b>B</b></a>') 
1514          style = self.parse('''\ 
1515  <xsl:stylesheet version="1.0" 
1516      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1517      xmlns:myns="testns" 
1518      extension-element-prefixes="myns" 
1519      exclude-result-prefixes="myns"> 
1520    <xsl:template match="/"> 
1521      <A><myns:myext>b</myns:myext></A> 
1522    </xsl:template> 
1523  </xsl:stylesheet>''') 
1524   
1525          tags = [] 
1526   
1527          class MyExt(etree.XSLTExtension): 
1528              def execute(self, context, self_node, input_node, output_parent): 
1529                  tags.append(input_node.tag) 
 1530   
1531          extensions = { ('testns', 'myext') : MyExt() } 
1532   
1533          result = tree.xslt(style, extensions=extensions) 
1534          self.assertEqual(tags, ['a']) 
1535   
1537          tree = self.parse('<?test toast?><a><!--a comment--><?another pi?></a>') 
1538          style = self.parse('''\ 
1539  <xsl:stylesheet version="1.0" 
1540      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1541      xmlns:myns="testns" 
1542      extension-element-prefixes="myns" 
1543      exclude-result-prefixes="myns"> 
1544    <xsl:template match="/"> 
1545      <ROOT><xsl:apply-templates /></ROOT> 
1546    </xsl:template> 
1547    <xsl:template match="comment()"> 
1548      <A><myns:myext>b</myns:myext></A> 
1549    </xsl:template> 
1550    <xsl:template match="processing-instruction()"> 
1551      <A><myns:myext>b</myns:myext></A> 
1552    </xsl:template> 
1553  </xsl:stylesheet>''') 
1554   
1555          text = [] 
1556   
1557          class MyExt(etree.XSLTExtension): 
1558              def execute(self, context, self_node, input_node, output_parent): 
1559                  text.append(input_node.text) 
 1560   
1561          extensions = { ('testns', 'myext') : MyExt() } 
1562   
1563          result = tree.xslt(style, extensions=extensions) 
1564          self.assertEqual(text, ['toast', 'a comment', 'pi']) 
1565   
1567           
1568          tree = self.parse('<a test="A"><b attr="B"/></a>') 
1569          style = self.parse('''\ 
1570  <xsl:stylesheet version="1.0" 
1571      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1572      xmlns:myns="testns" 
1573      extension-element-prefixes="myns" 
1574      exclude-result-prefixes="myns"> 
1575    <xsl:template match="@test"> 
1576      <A><myns:myext>b</myns:myext></A> 
1577    </xsl:template> 
1578    <xsl:template match="@attr"> 
1579      <A><myns:myext>b</myns:myext></A> 
1580    </xsl:template> 
1581  </xsl:stylesheet>''') 
1582   
1583          text = [] 
1584   
1585          class MyExt(etree.XSLTExtension): 
1586              def execute(self, context, self_node, attr_value, output_parent): 
1587                  text.append(attr_value) 
 1588   
1589          extensions = { ('testns', 'myext') : MyExt() } 
1590   
1591          result = tree.xslt(style, extensions=extensions) 
1592          self.assertEqual(text, ['A', 'B']) 
1593   
1595          tree = self.parse('<a><b>B</b></a>') 
1596          style = self.parse('''\ 
1597  <xsl:stylesheet version="1.0" 
1598      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1599      xmlns:myns="testns" 
1600      extension-element-prefixes="myns"> 
1601    <xsl:template match="a"> 
1602      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 
1603    </xsl:template> 
1604  </xsl:stylesheet>''') 
1605   
1606          class MyExt(etree.XSLTExtension): 
1607              def execute(self, context, self_node, input_node, output_parent): 
1608                  output_parent.extend(list(self_node)[1:]) 
 1609   
1610          extensions = { ('testns', 'myext') : MyExt() } 
1611   
1612          result = tree.xslt(style, extensions=extensions) 
1613          self.assertEqual(self._rootstring(result), 
1614                            _bytes('<A><y>Y</y><z/></A>')) 
1615   
1617          tree = self.parse('<a><b>B</b></a>') 
1618          style = self.parse('''\ 
1619  <xsl:stylesheet version="1.0" 
1620      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1621      xmlns:myns="testns" 
1622      extension-element-prefixes="myns"> 
1623    <xsl:template match="a"> 
1624      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 
1625    </xsl:template> 
1626    <xsl:template match="x" /> 
1627    <xsl:template match="z">XYZ</xsl:template> 
1628  </xsl:stylesheet>''') 
1629   
1630          class MyExt(etree.XSLTExtension): 
1631              def execute(self, context, self_node, input_node, output_parent): 
1632                  for child in self_node: 
1633                      for result in self.apply_templates(context, child): 
1634                          if isinstance(result, basestring): 
1635                              el = etree.Element("T") 
1636                              el.text = result 
1637                          else: 
1638                              el = result 
1639                          output_parent.append(el) 
 1640   
1641          extensions = { ('testns', 'myext') : MyExt() } 
1642   
1643          result = tree.xslt(style, extensions=extensions) 
1644          self.assertEqual(self._rootstring(result), 
1645                            _bytes('<A><T>Y</T><T>XYZ</T></A>')) 
1646   
1648          tree = self.parse('<a><b>B</b></a>') 
1649          style = self.parse('''\ 
1650  <xsl:stylesheet version="1.0" 
1651      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1652      xmlns:myns="testns" 
1653      extension-element-prefixes="myns"> 
1654    <xsl:template match="a"> 
1655      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 
1656    </xsl:template> 
1657    <xsl:template match="x"><X/></xsl:template> 
1658    <xsl:template match="z">XYZ</xsl:template> 
1659  </xsl:stylesheet>''') 
1660   
1661          class MyExt(etree.XSLTExtension): 
1662              def execute(self, context, self_node, input_node, output_parent): 
1663                  for child in self_node: 
1664                      for result in self.apply_templates(context, child, 
1665                                                         elements_only=True): 
1666                          assert not isinstance(result, basestring) 
1667                          output_parent.append(result) 
 1668   
1669          extensions = { ('testns', 'myext') : MyExt() } 
1670   
1671          result = tree.xslt(style, extensions=extensions) 
1672          self.assertEqual(self._rootstring(result), 
1673                            _bytes('<A><X/></A>')) 
1674   
1676          tree = self.parse('<a><b>B</b></a>') 
1677          style = self.parse('''\ 
1678  <xsl:stylesheet version="1.0" 
1679      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1680      xmlns:myns="testns" 
1681      extension-element-prefixes="myns"> 
1682    <xsl:template match="a"> 
1683      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 
1684    </xsl:template> 
1685    <xsl:template match="x"><X/></xsl:template> 
1686    <xsl:template match="y"><xsl:text>   </xsl:text></xsl:template> 
1687    <xsl:template match="z">XYZ</xsl:template> 
1688  </xsl:stylesheet>''') 
1689   
1690          class MyExt(etree.XSLTExtension): 
1691              def execute(self, context, self_node, input_node, output_parent): 
1692                  for child in self_node: 
1693                      for result in self.apply_templates(context, child, 
1694                                                         remove_blank_text=True): 
1695                          if isinstance(result, basestring): 
1696                              assert result.strip() 
1697                              el = etree.Element("T") 
1698                              el.text = result 
1699                          else: 
1700                              el = result 
1701                          output_parent.append(el) 
 1702   
1703          extensions = { ('testns', 'myext') : MyExt() } 
1704   
1705          result = tree.xslt(style, extensions=extensions) 
1706          self.assertEqual(self._rootstring(result), 
1707                            _bytes('<A><X/><T>XYZ</T></A>')) 
1708   
1710          tree = self.parse('<a><b>B</b></a>') 
1711          style = self.parse('''\ 
1712  <xsl:stylesheet version="1.0" 
1713      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1714      xmlns:myns="testns" 
1715      extension-element-prefixes="myns"> 
1716    <xsl:template match="a"> 
1717      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A> 
1718    </xsl:template> 
1719    <xsl:template match="x" /> 
1720    <xsl:template match="z">XYZ</xsl:template> 
1721  </xsl:stylesheet>''') 
1722   
1723          class MyExt(etree.XSLTExtension): 
1724              def execute(self, context, self_node, input_node, output_parent): 
1725                  for child in self_node: 
1726                      self.apply_templates(context, child, output_parent) 
 1727   
1728          extensions = { ('testns', 'myext') : MyExt() } 
1729   
1730          result = tree.xslt(style, extensions=extensions) 
1731          self.assertEqual(self._rootstring(result), 
1732                            _bytes('<A>YXYZ</A>')) 
1733   
1735          tree = self.parse('<a><b>B</b></a>') 
1736          style = self.parse('''\ 
1737  <xsl:stylesheet version="1.0" 
1738      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1739      xmlns:myns="testns" 
1740      extension-element-prefixes="myns"> 
1741    <xsl:template match="a"> 
1742      <myns:myext><x>X</x><y>Y</y><z/></myns:myext> 
1743    </xsl:template> 
1744    <xsl:template match="x"><xsl:processing-instruction name="test">TEST</xsl:processing-instruction></xsl:template> 
1745    <xsl:template match="y"><Y>XYZ</Y></xsl:template> 
1746    <xsl:template match="z"><xsl:comment>TEST</xsl:comment></xsl:template> 
1747  </xsl:stylesheet>''') 
1748   
1749          class MyExt(etree.XSLTExtension): 
1750              def execute(self, context, self_node, input_node, output_parent): 
1751                  for child in self_node: 
1752                      self.apply_templates(context, child, output_parent) 
 1753   
1754          extensions = { ('testns', 'myext') : MyExt() } 
1755   
1756          result = tree.xslt(style, extensions=extensions) 
1757          self.assertEqual(etree.tostring(result), 
1758                            _bytes('<?test TEST?><Y>XYZ</Y><!--TEST-->')) 
1759   
1761          tree = self.parse('<a><b>E</b></a>') 
1762          style = self.parse('''\ 
1763  <xsl:stylesheet version="1.0" 
1764      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1765      xmlns:myns="testns" 
1766      extension-element-prefixes="myns"> 
1767    <xsl:template match="a"> 
1768      <xsl:variable name="testvar">yo</xsl:variable> 
1769      <A> 
1770        <myns:myext> 
1771          <xsl:attribute name="attr"> 
1772            <xsl:value-of select="$testvar" /> 
1773          </xsl:attribute> 
1774          <B> 
1775            <xsl:choose> 
1776              <xsl:when test="1 = 2"><C/></xsl:when> 
1777              <xsl:otherwise><D><xsl:value-of select="b/text()" /></D></xsl:otherwise> 
1778            </xsl:choose> 
1779          </B> 
1780        </myns:myext> 
1781      </A> 
1782    </xsl:template> 
1783  </xsl:stylesheet>''') 
1784   
1785          class MyExt(etree.XSLTExtension): 
1786              def execute(self, context, self_node, input_node, output_parent): 
1787                  el = etree.Element('MY') 
1788                  self.process_children(context, el) 
1789                  output_parent.append(el) 
 1790   
1791          extensions = { ('testns', 'myext') : MyExt() } 
1792   
1793          result = tree.xslt(style, extensions=extensions) 
1794          self.assertEqual(self._rootstring(result), 
1795                            _bytes('<A><MYattr="yo"><B><D>E</D></B></MY></A>')) 
1796   
1798          tree = self.parse('<a/>') 
1799          style = self.parse('''\ 
1800  <xsl:stylesheet version="1.0" 
1801      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1802      xmlns:myns="testns" 
1803      extension-element-prefixes="myns"> 
1804    <xsl:template match="a"> 
1805      <myns:myext> 
1806        <A/> 
1807      </myns:myext> 
1808    </xsl:template> 
1809  </xsl:stylesheet>''') 
1810   
1811          class MyExt(etree.XSLTExtension): 
1812              def execute(self, context, self_node, input_node, output_parent): 
1813                  self.process_children(context, output_parent) 
 1814   
1815          extensions = { ('testns', 'myext') : MyExt() } 
1816   
1817          result = tree.xslt(style, extensions=extensions) 
1818          self.assertEqual(self._rootstring(result), 
1819                            _bytes('<A/>')) 
1820   
1822          tree = self.parse('<a/>') 
1823          style = self.parse('''\ 
1824  <xsl:stylesheet version="1.0" 
1825      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1826      xmlns:myns="testns" 
1827      extension-element-prefixes="myns"> 
1828    <xsl:template match="a"> 
1829      <myns:myext> 
1830        <A/> 
1831      </myns:myext> 
1832    </xsl:template> 
1833  </xsl:stylesheet>''') 
1834   
1835          class MyExt(etree.XSLTExtension): 
1836              def execute(self, context, self_node, input_node, output_parent): 
1837                  self.process_children(context, self_node) 
 1838   
1839          extensions = { ('testns', 'myext') : MyExt() } 
1840   
1841          self.assertRaises(TypeError, tree.xslt, style, extensions=extensions) 
1842   
1844          tree = self.parse('<a/>') 
1845          style = self.parse('''\ 
1846  <xsl:stylesheet version="1.0" 
1847      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1848      xmlns:myns="testns" 
1849      extension-element-prefixes="myns"> 
1850    <xsl:template match="a"> 
1851      <myns:myext> 
1852        <A><myns:myext><B/></myns:myext></A> 
1853      </myns:myext> 
1854    </xsl:template> 
1855  </xsl:stylesheet>''') 
1856   
1857          class MyExt(etree.XSLTExtension): 
1858              callback_call_counter = 0 
1859              def execute(self, context, self_node, input_node, output_parent): 
1860                  self.callback_call_counter += 1 
1861                  el = etree.Element('MY', n=str(self.callback_call_counter)) 
1862                  self.process_children(context, el) 
1863                  output_parent.append(el) 
 1864   
1865          extensions = { ('testns', 'myext') : MyExt() } 
1866   
1867          result = tree.xslt(style, extensions=extensions) 
1868          self.assertEqual(self._rootstring(result), 
1869                            _bytes('<MYn="1"><A><MYn="2"><B/></MY></A></MY>')) 
1870   
1872          tree = self.parse('<a><b>B</b></a>') 
1873          style = self.parse('''\ 
1874  <xsl:stylesheet version="1.0" 
1875      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
1876      xmlns:myns="testns" 
1877      extension-element-prefixes="myns" 
1878      exclude-result-prefixes="myns"> 
1879    <xsl:template match="a"> 
1880      <A><myns:myext>b</myns:myext></A> 
1881    </xsl:template> 
1882  </xsl:stylesheet>''') 
1883   
1884          class MyError(Exception): 
1885              pass 
 1886   
1887          class MyExt(etree.XSLTExtension): 
1888              def execute(self, context, self_node, input_node, output_parent): 
1889                  raise MyError("expected!") 
1890   
1891          extensions = { ('testns', 'myext') : MyExt() } 
1892          self.assertRaises(MyError, tree.xslt, style, extensions=extensions) 
1893   
1894       
1895       
1897          tree = self.parse("""\ 
1898  <text> 
1899    <par>This is <format>arbitrary</format> text in a paragraph</par> 
1900  </text>""") 
1901          style = self.parse("""\ 
1902  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my" extension-element-prefixes="my" version="1.0"> 
1903    <xsl:template match="par"> 
1904      <my:par><xsl:apply-templates /></my:par> 
1905    </xsl:template> 
1906    <xsl:template match="format"> 
1907      <my:format><xsl:apply-templates /></my:format> 
1908    </xsl:template> 
1909  </xsl:stylesheet> 
1910  """) 
1911          test = self 
1912          calls = [] 
1913   
1914          class ExtMyPar(etree.XSLTExtension): 
1915              def execute(self, context, self_node, input_node, output_parent): 
1916                  calls.append('par') 
1917                  p = etree.Element("p") 
1918                  p.attrib["style"] = "color:red" 
1919                  self.process_children(context, p) 
1920                  output_parent.append(p) 
 1921   
1922          class ExtMyFormat(etree.XSLTExtension): 
1923              def execute(self, context, self_node, input_node, output_parent): 
1924                  calls.append('format') 
1925                  content = self.process_children(context) 
1926                  test.assertEqual(1, len(content)) 
1927                  test.assertEqual('arbitrary', content[0]) 
1928                  test.assertEqual('This is ', output_parent.text) 
1929                  output_parent.text += '*-%s-*' % content[0] 
1930   
1931          extensions = {("my", "par"): ExtMyPar(), ("my", "format"): ExtMyFormat()} 
1932          transform = etree.XSLT(style, extensions=extensions) 
1933          result = transform(tree) 
1934          self.assertEqual(['par', 'format'], calls) 
1935          self.assertEqual( 
1936              b'<p style="color:red">This is *-arbitrary-* text in a paragraph</p>\n', 
1937              etree.tostring(result)) 
1938   
1941      """XSLT tests for etree under Python 3""" 
1942   
1943      pytestmark = skipif('sys.version_info < (3,0)') 
1944   
1946          tree = self.parse('<a><b>B</b><c>C</c></a>') 
1947          style = self.parse('''\ 
1948  <xsl:stylesheet version="1.0" 
1949      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1950    <xsl:template match="*" /> 
1951    <xsl:template match="/"> 
1952      <foo><xsl:value-of select="/a/b/text()" /></foo> 
1953    </xsl:template> 
1954  </xsl:stylesheet>''') 
1955   
1956          st = etree.XSLT(style) 
1957          res = st(tree) 
1958          self.assertEqual(_bytes('''\ 
1959  <?xml version="1.0"?> 
1960  <foo>B</foo> 
1961  '''), 
1962                            bytes(res)) 
 1963   
1965          tree = self.parse('<a><b>B</b><c>C</c></a>') 
1966          style = self.parse('''\ 
1967  <xsl:stylesheet version="1.0" 
1968      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1969    <xsl:template match="*" /> 
1970    <xsl:template match="/"> 
1971      <foo><xsl:value-of select="/a/b/text()" /></foo> 
1972    </xsl:template> 
1973  </xsl:stylesheet>''') 
1974   
1975          st = etree.XSLT(style) 
1976          res = st(tree) 
1977          self.assertEqual(_bytes('''\ 
1978  <?xml version="1.0"?> 
1979  <foo>B</foo> 
1980  '''), 
1981                            bytearray(res)) 
 1982   
1984          tree = self.parse('<a><b>B</b><c>C</c></a>') 
1985          style = self.parse('''\ 
1986  <xsl:stylesheet version="1.0" 
1987      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
1988    <xsl:template match="*" /> 
1989    <xsl:template match="/"> 
1990      <foo><xsl:value-of select="/a/b/text()" /></foo> 
1991    </xsl:template> 
1992  </xsl:stylesheet>''') 
1993   
1994          st = etree.XSLT(style) 
1995          res = st(tree) 
1996          self.assertEqual(_bytes('''\ 
1997  <?xml version="1.0"?> 
1998  <foo>B</foo> 
1999  '''), 
2000                            bytes(memoryview(res))) 
  2001   
2016   
2017  if __name__ == '__main__': 
2018      print('to test use test.py %s' % __file__) 
2019