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

# Source Code for Module lxml.tests.test_xslt

       1  # -*- coding: utf-8 -*-
       2
       3  """
       4  Test cases related to XSLT processing
       5  """
       6
       7  import unittest, copy, sys, os.path
       8
       9  this_dir = os.path.dirname(__file__)
      10  if this_dir not in sys.path:
      11      sys.path.insert(0, this_dir) # needed for Py3
      12
      13  is_python3 = sys.version_info[0] >= 3
      14
      15  try:
      16      unicode
      17  except NameError: # Python 3
      18      unicode = str
      19
      20  try:
      21      basestring
      22  except NameError: # Python 3
      23      basestring = str
      24
      25  from common_imports import etree, BytesIO, HelperTestCase, fileInTestDir
      26  from common_imports import doctest, _bytes, _str, make_doctest, skipif
      27
      28 -class ETreeXSLTTestCase(HelperTestCase):
      29      """XSLT tests etree"""
      30
      31 -    def test_xslt(self):
      32          tree = self.parse('<a><b>B</b><c>C</c></a>')
      33          style = self.parse('''\
      34  <xsl:stylesheet version="1.0"
      35      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      36    <xsl:template match="*" />
      37    <xsl:template match="/">
      38      <foo><xsl:value-of select="/a/b/text()" /></foo>
      39    </xsl:template>
      40  </xsl:stylesheet>''')
      41
      42          st = etree.XSLT(style)
      43          res = st(tree)
      44          self.assertEqual('''\
      45  <?xml version="1.0"?>
      46  <foo>B</foo>
      47  ''',
      48                            str(res))
      49
      50 -    def test_xslt_elementtree_error(self):
      51          self.assertRaises(ValueError, etree.XSLT, etree.ElementTree())
      52
      53 -    def test_xslt_input_none(self):
      54          self.assertRaises(TypeError, etree.XSLT, None)
      55
      56      if False and etree.LIBXSLT_VERSION >= (1,1,15):
      57          # earlier versions generate no error
      58          if etree.LIBXSLT_VERSION > (1,1,17):
      59 -            def test_xslt_invalid_stylesheet(self):
      60                  style = self.parse('''\
      61  <xsl:stylesheet version="1.0"
      62      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      63    <xsl:stylesheet />
      64  </xsl:stylesheet>''')
      65
      66                  self.assertRaises(
      67                      etree.XSLTParseError, etree.XSLT, style)
      68
      69 -    def test_xslt_copy(self):
      70          tree = self.parse('<a><b>B</b><c>C</c></a>')
      71          style = self.parse('''\
      72  <xsl:stylesheet version="1.0"
      73      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      74    <xsl:template match="*" />
      75    <xsl:template match="/">
      76      <foo><xsl:value-of select="/a/b/text()" /></foo>
      77    </xsl:template>
      78  </xsl:stylesheet>''')
      79
      80          transform = etree.XSLT(style)
      81          res = transform(tree)
      82          self.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
     104 -    def test_xslt_utf8(self):
     105          tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
     106                                   ).decode("unicode_escape"))
     107          style = self.parse('''\
     108  <xsl:stylesheet version="1.0"
     109      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     110    <xsl:output encoding="UTF-8"/>
     111    <xsl:template match="/">
     112      <foo><xsl:value-of select="/a/b/text()" /></foo>
     113    </xsl:template>
     114  </xsl:stylesheet>''')
     115
     116          st = etree.XSLT(style)
     117          res = st(tree)
     118          expected = _bytes('''\
     119  <?xml version="1.0" encoding="UTF-8"?>
     120  <foo>\\uF8D2</foo>
     121  ''').decode("unicode_escape")
     122          if is_python3:
     123              self.assertEqual(expected,
     124                                str(bytes(res), 'UTF-8'))
     125          else:
     126              self.assertEqual(expected,
     127                                unicode(str(res), 'UTF-8'))
     128
     129 -    def test_xslt_encoding(self):
     130          tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
     131                                   ).decode("unicode_escape"))
     132          style = self.parse('''\
     133  <xsl:stylesheet version="1.0"
     134      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     135    <xsl:output encoding="UTF-16"/>
     136    <xsl:template match="/">
     137      <foo><xsl:value-of select="/a/b/text()" /></foo>
     138    </xsl:template>
     139  </xsl:stylesheet>''')
     140
     141          st = etree.XSLT(style)
     142          res = st(tree)
     143          expected = _bytes('''\
     144  <?xml version="1.0" encoding="UTF-16"?>
     145  <foo>\\uF8D2</foo>
     146  ''').decode("unicode_escape")
     147          if is_python3:
     148              self.assertEqual(expected,
     149                                str(bytes(res), 'UTF-16'))
     150          else:
     151              self.assertEqual(expected,
     152                                unicode(str(res), 'UTF-16'))
     153
     154 -    def test_xslt_encoding_override(self):
     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
     180 -    def test_xslt_unicode(self):
     181          tree = self.parse(_bytes('<a><b>\\uF8D2</b><c>\\uF8D2</c></a>'
     182                                   ).decode("unicode_escape"))
     183          style = self.parse('''\
     184  <xsl:stylesheet version="1.0"
     185      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     186    <xsl:output encoding="UTF-16"/>
     187    <xsl:template match="/">
     188      <foo><xsl:value-of select="/a/b/text()" /></foo>
     189    </xsl:template>
     190  </xsl:stylesheet>''')
     191
     192          st = etree.XSLT(style)
     193          res = st(tree)
     194          expected = _bytes('''\
     195  <?xml version="1.0"?>
     196  <foo>\\uF8D2</foo>
     197  ''').decode("unicode_escape")
     198          self.assertEqual(expected,
     199                            unicode(res))
     200
     201 -    def test_xslt_unicode_standalone(self):
     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
     222 -    def test_xslt_input(self):
     223          style = self.parse('''\
     224  <xsl:stylesheet version="1.0"
     225      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     226    <xsl:template match="*" />
     227    <xsl:template match="/">
     228      <foo><xsl:value-of select="/a/b/text()" /></foo>
     229    </xsl:template>
     230  </xsl:stylesheet>''')
     231
     232          st = etree.XSLT(style)
     233          st = etree.XSLT(style.getroot())
     234
     235 -    def test_xslt_input_partial_doc(self):
     236          style = self.parse('''\
     237  <otherroot>
     238  <xsl:stylesheet version="1.0"
     239      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     240    <xsl:template match="*" />
     241    <xsl:template match="/">
     242      <foo><xsl:value-of select="/a/b/text()" /></foo>
     243    </xsl:template>
     244  </xsl:stylesheet>
     245  </otherroot>''')
     246
     247          self.assertRaises(etree.XSLTParseError, etree.XSLT, style)
     248          root_node = style.getroot()
     249          self.assertRaises(etree.XSLTParseError, etree.XSLT, root_node)
     250          st = etree.XSLT(root_node[0])
     251
     252 -    def test_xslt_broken(self):
     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
     262 -    def test_xslt_parameters(self):
     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
     280 -    def test_xslt_string_parameters(self):
     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
     298 -    def test_xslt_parameter_invalid(self):
     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          # later versions produce no error
     317 -        def test_xslt_parameter_missing(self):
     318              # apply() without needed parameter will lead to XSLTApplyError
     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
     332 -    def test_xslt_multiple_parameters(self):
     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
     352 -    def test_xslt_parameter_xpath(self):
     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
     371 -    def test_xslt_parameter_xpath_object(self):
     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
     390 -    def test_xslt_default_parameters(self):
     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
     416 -    def test_xslt_html_output(self):
     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
     433 -    def test_xslt_include(self):
     434          tree = etree.parse(fileInTestDir('test1.xslt'))
     435          st = etree.XSLT(tree)
     436
     437 -    def test_xslt_include_from_filelike(self):
     438          f = open(fileInTestDir('test1.xslt'), 'rb')
     439          tree = etree.parse(f)
     440          f.close()
     441          st = etree.XSLT(tree)
     442
     443 -    def test_xslt_multiple_transforms(self):
     444          xml = '<a/>'
     445          xslt = '''\
     446  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     447      <xsl:template match="/">
     448          <response>Some text</response>
     449      </xsl:template>
     450  </xsl:stylesheet>
     451  '''
     452          source = self.parse(xml)
     453          styledoc = self.parse(xslt)
     454          style = etree.XSLT(styledoc)
     455          result = style(source)
     456
     457          etree.tostring(result.getroot())
     458
     459          source = self.parse(xml)
     460          styledoc = self.parse(xslt)
     461          style = etree.XSLT(styledoc)
     462          result = style(source)
     463
     464          etree.tostring(result.getroot())
     465
     466 -    def test_xslt_repeat_transform(self):
     467          xml = '<a/>'
     468          xslt = '''\
     469  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     470      <xsl:template match="/">
     471          <response>Some text</response>
     472      </xsl:template>
     473  </xsl:stylesheet>
     474  '''
     475          source = self.parse(xml)
     476          styledoc = self.parse(xslt)
     477          transform = etree.XSLT(styledoc)
     478          result = transform(source)
     479          result = transform(source)
     480          etree.tostring(result.getroot())
     481          result = transform(source)
     482          etree.tostring(result.getroot())
     483          str(result)
     484
     485          result1 = transform(source)
     486          result2 = transform(source)
     487          self.assertEqual(str(result1), str(result2))
     488          result = transform(source)
     489          str(result)
     490
     491 -    def test_xslt_empty(self):
     492          # could segfault if result contains "empty document"
     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
     506 -    def test_xslt_message(self):
     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
     524 -    def test_xslt_message_terminate(self):
     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
     542 -    def test_xslt_shortcut(self):
     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
     561 -    def test_multiple_elementrees(self):
     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
     597 -    def test_xslt_document_XML(self):
     598          # make sure document('') works from parsed strings
     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
     618 -    def test_xslt_document_parse(self):
     619          # make sure document('') works from loaded files
     620          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")))
     621          result = xslt(etree.XML('<a/>'))
     622          root = result.getroot()
     623          self.assertEqual(root.tag,
     624                            'test')
     625          self.assertEqual(root[0].tag,
     626                            '{http://www.w3.org/1999/XSL/Transform}stylesheet')
     627
     628 -    def test_xslt_document_elementtree(self):
     629          # make sure document('') works from loaded files
     630          xslt = etree.XSLT(etree.ElementTree(file=fileInTestDir("test-document.xslt")))
     631          result = xslt(etree.XML('<a/>'))
     632          root = result.getroot()
     633          self.assertEqual(root.tag,
     634                            'test')
     635          self.assertEqual(root[0].tag,
     636                            '{http://www.w3.org/1999/XSL/Transform}stylesheet')
     637
     638 -    def test_xslt_document_error(self):
     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
     649 -    def test_xslt_document_XML_resolver(self):
     650          # make sure document('') works when custom resolvers are in use
     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
     711 -    def test_xslt_resolver_url_building(self):
     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          # test without base_url => relative path only
     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          # now the same thing with a stylesheet base URL on the filesystem
     743          called['count'] = 0
     744          expected_url = os.path.join('MY', 'BASE', 'test.xml')
     745          xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
     746                                      base_url=os.path.join('MY', 'BASE', 'FILE')))
     747
     748          self.assertEqual(called['count'], 0)
     749          result = xslt(etree.XML('<a/>'))
     750          self.assertEqual(called['count'], 1)
     751
     752          # now the same thing with a stylesheet base URL
     753          called['count'] = 0
     754          expected_url = 'http://server.com/BASE/DIR/test.xml'
     755          xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
     756                                      base_url='http://server.com/BASE/DIR/FILE'))
     757
     758          self.assertEqual(called['count'], 0)
     759          result = xslt(etree.XML('<a/>'))
     760          self.assertEqual(called['count'], 1)
     761
     762 -    def test_xslt_document_parse_allow(self):
     763          access_control = etree.XSLTAccessControl(read_file=True)
     764          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
     765                            access_control = access_control)
     766          result = xslt(etree.XML('<a/>'))
     767          root = result.getroot()
     768          self.assertEqual(root.tag,
     769                            'test')
     770          self.assertEqual(root[0].tag,
     771                            '{http://www.w3.org/1999/XSL/Transform}stylesheet')
     772
     773 -    def test_xslt_document_parse_deny(self):
     774          access_control = etree.XSLTAccessControl(read_file=False)
     775          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
     776                            access_control = access_control)
     777          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
     778
     779 -    def test_xslt_document_parse_deny_all(self):
     780          access_control = etree.XSLTAccessControl.DENY_ALL
     781          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
     782                            access_control = access_control)
     783          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
     784
     785 -    def test_xslt_move_result(self):
     786          root = etree.XML(_bytes('''\
     787          <transform>
     788            <widget displayType="fieldset"/>
     789          </transform>'''))
     790
     791          xslt = etree.XSLT(etree.XML(_bytes('''\
     792          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     793            <xsl:output method="html" indent="no"/>
     794            <xsl:template match="/">
     795              <html>
     796                <xsl:apply-templates/>
     797              </html>
     798            </xsl:template>
     799
     800            <xsl:template match="widget">
     801              <xsl:element name="{@displayType}"/>
     802            </xsl:template>
     803
     804          </xsl:stylesheet>''')))
     805
     806          result = xslt(root[0])
     807          root[:] = result.getroot()[:]
     808          del root # segfaulted before
     809
     810 -    def test_xslt_pi(self):
     811          tree = self.parse('''\
     812  <?xml version="1.0"?>
     813  <?xml-stylesheet type="text/xsl" href="%s"?>
     814  <a>
     815    <b>B</b>
     816    <c>C</c>
     817  </a>''' % fileInTestDir("test1.xslt"))
     818
     819          style_root = tree.getroot().getprevious().parseXSL().getroot()
     820          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
     821                            style_root.tag)
     822
     823 -    def test_xslt_pi_embedded_xmlid(self):
     824          # test xml:id dictionary lookup mechanism
     825          tree = self.parse('''\
     826  <?xml version="1.0"?>
     827  <?xml-stylesheet type="text/xsl" href="#style"?>
     828  <a>
     829    <b>B</b>
     830    <c>C</c>
     831    <xsl:stylesheet version="1.0" xml:id="style"
     832        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     833      <xsl:template match="*" />
     834      <xsl:template match="/">
     835        <foo><xsl:value-of select="/a/b/text()" /></foo>
     836      </xsl:template>
     837    </xsl:stylesheet>
     838  </a>''')
     839
     840          style_root = tree.getroot().getprevious().parseXSL().getroot()
     841          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
     842                            style_root.tag)
     843
     844          st = etree.XSLT(style_root)
     845          res = st(tree)
     846          self.assertEqual('''\
     847  <?xml version="1.0"?>
     848  <foo>B</foo>
     849  ''',
     850                            str(res))
     851
     852 -    def test_xslt_pi_embedded_id(self):
     853          # test XPath lookup mechanism
     854          tree = self.parse('''\
     855  <?xml version="1.0"?>
     856  <?xml-stylesheet type="text/xsl" href="#style"?>
     857  <a>
     858    <b>B</b>
     859    <c>C</c>
     860  </a>''')
     861
     862          style = self.parse('''\
     863  <xsl:stylesheet version="1.0" xml:id="style"
     864      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     865    <xsl:template match="*" />
     866    <xsl:template match="/">
     867      <foo><xsl:value-of select="/a/b/text()" /></foo>
     868    </xsl:template>
     869  </xsl:stylesheet>
     870  ''')
     871
     872          tree.getroot().append(style.getroot())
     873
     874          style_root = tree.getroot().getprevious().parseXSL().getroot()
     875          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
     876                            style_root.tag)
     877
     878          st = etree.XSLT(style_root)
     879          res = st(tree)
     880          self.assertEqual('''\
     881  <?xml version="1.0"?>
     882  <foo>B</foo>
     883  ''',
     884                            str(res))
     885
     886 -    def test_xslt_pi_get(self):
     887          tree = self.parse('''\
     888  <?xml version="1.0"?>
     889  <?xml-stylesheet type="text/xsl" href="TEST"?>
     890  <a>
     891    <b>B</b>
     892    <c>C</c>
     893  </a>''')
     894
     895          pi = tree.getroot().getprevious()
     896          self.assertEqual("TEST", pi.get("href"))
     897
     898 -    def test_xslt_pi_get_all(self):
     899          tree = self.parse('''\
     900  <?xml version="1.0"?>
     901  <?xml-stylesheet type="text/xsl" href="TEST"?>
     902  <a>
     903    <b>B</b>
     904    <c>C</c>
     905  </a>''')
     906
     907          pi = tree.getroot().getprevious()
     908          self.assertEqual("TEST", pi.get("href"))
     909          self.assertEqual("text/xsl", pi.get("type"))
     910          self.assertEqual(None, pi.get("motz"))
     911
     912 -    def test_xslt_pi_get_all_reversed(self):
     913          tree = self.parse('''\
     914  <?xml version="1.0"?>
     915  <?xml-stylesheet href="TEST" type="text/xsl"?>
     916  <a>
     917    <b>B</b>
     918    <c>C</c>
     919  </a>''')
     920
     921          pi = tree.getroot().getprevious()
     922          self.assertEqual("TEST", pi.get("href"))
     923          self.assertEqual("text/xsl", pi.get("type"))
     924          self.assertEqual(None, pi.get("motz"))
     925
     926 -    def test_xslt_pi_get_unknown(self):
     927          tree = self.parse('''\
     928  <?xml version="1.0"?>
     929  <?xml-stylesheet type="text/xsl" href="TEST"?>
     930  <a>
     931    <b>B</b>
     932    <c>C</c>
     933  </a>''')
     934
     935          pi = tree.getroot().getprevious()
     936          self.assertEqual(None, pi.get("unknownattribute"))
     937
     938 -    def test_xslt_pi_set_replace(self):
     939          tree = self.parse('''\
     940  <?xml version="1.0"?>
     941  <?xml-stylesheet type="text/xsl" href="TEST"?>
     942  <a>
     943    <b>B</b>
     944    <c>C</c>
     945  </a>''')
     946
     947          pi = tree.getroot().getprevious()
     948          self.assertEqual("TEST", pi.get("href"))
     949
     950          pi.set("href", "TEST123")
     951          self.assertEqual("TEST123", pi.get("href"))
     952
     953 -    def test_xslt_pi_set_new(self):
     954          tree = self.parse('''\
     955  <?xml version="1.0"?>
     956  <?xml-stylesheet type="text/xsl"?>
     957  <a>
     958    <b>B</b>
     959    <c>C</c>
     960  </a>''')
     961
     962          pi = tree.getroot().getprevious()
     963          self.assertEqual(None, pi.get("href"))
     964
     965          pi.set("href", "TEST")
     966          self.assertEqual("TEST", pi.get("href"))
     967
     968 -class ETreeEXSLTTestCase(HelperTestCase):
     969      """EXSLT tests"""
     970
     971 -    def test_exslt_str(self):
     972          tree = self.parse('<a><b>B</b><c>C</c></a>')
     973          style = self.parse('''\
     974  <xsl:stylesheet version="1.0"
     975      xmlns:str="http://exslt.org/strings"
     976      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     977      exclude-result-prefixes="str xsl">
     978    <xsl:template match="text()">
     979      <xsl:value-of select="str:align(string(.), '***', 'center')" />
     980    </xsl:template>
     981    <xsl:template match="*">
     982      <xsl:copy>
     983        <xsl:apply-templates/>
     984      </xsl:copy>
     985    </xsl:template>
     986  </xsl:stylesheet>''')
     987
     988          st = etree.XSLT(style)
     989          res = st(tree)
     990          self.assertEqual('''\
     991  <?xml version="1.0"?>
     992  <a><b>*B*</b><c>*C*</c></a>
     993  ''',
     994                            str(res))
     995
     996      if etree.LIBXSLT_VERSION >= (1,1,21):
     997 -        def test_exslt_str_attribute_replace(self):
     998              tree = self.parse('<a><b>B</b><c>C</c></a>')
     999              style = self.parse('''\
    1000        <xsl:stylesheet version = "1.0"
    1001            xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
    1002            xmlns:str="http://exslt.org/strings"
    1003            extension-element-prefixes="str">
    1004
    1005            <xsl:template match="/">
    1006              <h1 class="{str:replace('abc', 'b', 'x')}">test</h1>
    1007            </xsl:template>
    1008
    1009        </xsl:stylesheet>''')
    1010
    1011              st = etree.XSLT(style)
    1012              res = st(tree)
    1013              self.assertEqual('''\
    1014  <?xml version="1.0"?>
    1015  <h1 class="axc">test</h1>
    1016  ''',
    1017                                str(res))
    1018
    1019 -    def test_exslt_math(self):
    1020          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1021          style = self.parse('''\
    1022  <xsl:stylesheet version="1.0"
    1023      xmlns:math="http://exslt.org/math"
    1024      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1025      exclude-result-prefixes="math xsl">
    1026    <xsl:template match="*">
    1027      <xsl:copy>
    1028        <xsl:attribute name="pi">
    1029          <xsl:value-of select="math:constant('PI', count(*)+2)"/>
    1030        </xsl:attribute>
    1031        <xsl:apply-templates/>
    1032      </xsl:copy>
    1033    </xsl:template>
    1034  </xsl:stylesheet>''')
    1035
    1036          st = etree.XSLT(style)
    1037          res = st(tree)
    1038          self.assertEqual('''\
    1039  <?xml version="1.0"?>
    1040  <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a>
    1041  ''',
    1042                            str(res))
    1043
    1044 -    def test_exslt_regexp_test(self):
    1045          xslt = etree.XSLT(etree.XML(_bytes("""\
    1046  <xsl:stylesheet version="1.0"
    1047     xmlns:regexp="http://exslt.org/regular-expressions"
    1048     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1049    <xsl:template match="*">
    1050      <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test>
    1051    </xsl:template>
    1052  </xsl:stylesheet>
    1053  """)))
    1054          result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>')))
    1055          root = result.getroot()
    1056          self.assertEqual(root.tag,
    1057                            'test')
    1058          self.assertEqual(len(root), 1)
    1059          self.assertEqual(root[0].tag,
    1060                            'b')
    1061          self.assertEqual(root[0].text,
    1062                            '987')
    1063
    1064 -    def test_exslt_regexp_replace(self):
    1065          xslt = etree.XSLT(etree.XML("""\
    1066  <xsl:stylesheet version="1.0"
    1067     xmlns:regexp="http://exslt.org/regular-expressions"
    1068     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1069    <xsl:template match="*">
    1070      <test>
    1071        <xsl:copy-of select="regexp:replace(string(.), 'd.', '',   'XX')"/>
    1072        <xsl:text>-</xsl:text>
    1073        <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/>
    1074      </test>
    1075    </xsl:template>
    1076  </xsl:stylesheet>
    1077  """))
    1078          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
    1079          root = result.getroot()
    1080          self.assertEqual(root.tag,
    1081                            'test')
    1082          self.assertEqual(len(root), 0)
    1083          self.assertEqual(root.text, 'abXXdEeDed-abXXXXeXXd')
    1084
    1085 -    def test_exslt_regexp_match(self):
    1086          xslt = etree.XSLT(etree.XML("""\
    1087  <xsl:stylesheet version="1.0"
    1088     xmlns:regexp="http://exslt.org/regular-expressions"
    1089     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1090    <xsl:template match="*">
    1091      <test>
    1092        <test1><xsl:copy-of  select="regexp:match(string(.), 'd.')"/></test1>
    1093        <test2><xsl:copy-of  select="regexp:match(string(.), 'd.', 'g')"/></test2>
    1094        <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i>
    1095      </test>
    1096    </xsl:template>
    1097  </xsl:stylesheet>
    1098  """))
    1099          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
    1100          root = result.getroot()
    1101          self.assertEqual(root.tag,  'test')
    1102          self.assertEqual(len(root), 3)
    1103
    1104          self.assertEqual(len(root[0]), 1)
    1105          self.assertEqual(root[0][0].tag, 'match')
    1106          self.assertEqual(root[0][0].text, 'dC')
    1107
    1108          self.assertEqual(len(root[1]), 2)
    1109          self.assertEqual(root[1][0].tag, 'match')
    1110          self.assertEqual(root[1][0].text, 'dC')
    1111          self.assertEqual(root[1][1].tag, 'match')
    1112          self.assertEqual(root[1][1].text, 'dE')
    1113
    1114          self.assertEqual(len(root[2]), 3)
    1115          self.assertEqual(root[2][0].tag, 'match')
    1116          self.assertEqual(root[2][0].text, 'dC')
    1117          self.assertEqual(root[2][1].tag, 'match')
    1118          self.assertEqual(root[2][1].text, 'dE')
    1119          self.assertEqual(root[2][2].tag, 'match')
    1120          self.assertEqual(root[2][2].text, 'De')
    1121
    1122 -    def test_exslt_regexp_match_groups(self):
    1123          xslt = etree.XSLT(etree.XML(_bytes("""\
    1124  <xsl:stylesheet version="1.0"
    1125     xmlns:regexp="http://exslt.org/regular-expressions"
    1126     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1127    <xsl:template match="/">
    1128      <test>
    1129        <xsl:for-each select="regexp:match(
    1130              '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )">
    1131          <test1><xsl:value-of select="."/></test1>
    1132        </xsl:for-each>
    1133      </test>
    1134    </xsl:template>
    1135  </xsl:stylesheet>
    1136  """)))
    1137          result = xslt(etree.XML(_bytes('<a/>')))
    1138          root = result.getroot()
    1139          self.assertEqual(root.tag,  'test')
    1140          self.assertEqual(len(root), 4)
    1141
    1142          self.assertEqual(root[0].text, "123abc567")
    1143          self.assertEqual(root[1].text, "123")
    1144          self.assertEqual(root[2].text, "abc")
    1145          self.assertEqual(root[3].text, "567")
    1146
    1147 -    def test_exslt_regexp_match1(self):
    1148          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1149          xslt = etree.XSLT(etree.XML(_bytes("""\
    1150  <xsl:stylesheet version="1.0"
    1151     xmlns:regexp="http://exslt.org/regular-expressions"
    1152     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1153    <xsl:template match="/">
    1154      <test>
    1155        <xsl:for-each select="regexp:match(
    1156              'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml',
    1157              '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')">
    1158          <test1><xsl:value-of select="."/></test1>
    1159        </xsl:for-each>
    1160      </test>
    1161    </xsl:template>
    1162  </xsl:stylesheet>
    1163  """)))
    1164          result = xslt(etree.XML(_bytes('<a/>')))
    1165          root = result.getroot()
    1166          self.assertEqual(root.tag,  'test')
    1167          self.assertEqual(len(root), 5)
    1168
    1169          self.assertEqual(
    1170              root[0].text,
    1171              "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml")
    1172          self.assertEqual(
    1173              root[1].text,
    1174              "http")
    1175          self.assertEqual(
    1176              root[2].text,
    1177              "www.bayes.co.uk")
    1178          self.assertFalse(root[3].text)
    1179          self.assertEqual(
    1180              root[4].text,
    1181              "/xml/index.xml?/xml/utils/rechecker.xml")
    1182
    1183 -    def test_exslt_regexp_match2(self):
    1184          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1185          xslt = etree.XSLT(self.parse("""\
    1186  <xsl:stylesheet version="1.0"
    1187     xmlns:regexp="http://exslt.org/regular-expressions"
    1188     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1189    <xsl:template match="/">
    1190      <test>
    1191        <xsl:for-each select="regexp:match(
    1192              'This is a test string', '(\w+)', 'g')">
    1193          <test1><xsl:value-of select="."/></test1>
    1194        </xsl:for-each>
    1195      </test>
    1196    </xsl:template>
    1197  </xsl:stylesheet>
    1198  """))
    1199          result = xslt(etree.XML(_bytes('<a/>')))
    1200          root = result.getroot()
    1201          self.assertEqual(root.tag,  'test')
    1202          self.assertEqual(len(root), 5)
    1203
    1204          self.assertEqual(root[0].text, "This")
    1205          self.assertEqual(root[1].text, "is")
    1206          self.assertEqual(root[2].text, "a")
    1207          self.assertEqual(root[3].text, "test")
    1208          self.assertEqual(root[4].text, "string")
    1209
    1210 -    def _test_exslt_regexp_match3(self):
    1211          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1212          # THIS IS NOT SUPPORTED!
    1213          xslt = etree.XSLT(etree.XML(_bytes("""\
    1214  <xsl:stylesheet version="1.0"
    1215     xmlns:regexp="http://exslt.org/regular-expressions"
    1216     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1217    <xsl:template match="/">
    1218      <test>
    1219        <xsl:for-each select="regexp:match(
    1220              'This is a test string', '([a-z])+ ', 'g')">
    1221          <test1><xsl:value-of select="."/></test1>
    1222        </xsl:for-each>
    1223      </test>
    1224    </xsl:template>
    1225  </xsl:stylesheet>
    1226  """)))
    1227          result = xslt(etree.XML(_bytes('<a/>')))
    1228          root = result.getroot()
    1229          self.assertEqual(root.tag,  'test')
    1230          self.assertEqual(len(root), 4)
    1231
    1232          self.assertEqual(root[0].text, "his")
    1233          self.assertEqual(root[1].text, "is")
    1234          self.assertEqual(root[2].text, "a")
    1235          self.assertEqual(root[3].text, "test")
    1236
    1237 -    def _test_exslt_regexp_match4(self):
    1238          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1239          # THIS IS NOT SUPPORTED!
    1240          xslt = etree.XSLT(etree.XML(_bytes("""\
    1241  <xsl:stylesheet version="1.0"
    1242     xmlns:regexp="http://exslt.org/regular-expressions"
    1243     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1244    <xsl:template match="/">
    1245      <test>
    1246        <xsl:for-each select="regexp:match(
    1247              'This is a test string', '([a-z])+ ', 'gi')">
    1248          <test1><xsl:value-of select="."/></test1>
    1249        </xsl:for-each>
    1250      </test>
    1251    </xsl:template>
    1252  </xsl:stylesheet>
    1253  """)))
    1254          result = xslt(etree.XML(_bytes('<a/>')))
    1255          root = result.getroot()
    1256          self.assertEqual(root.tag,  'test')
    1257          self.assertEqual(len(root), 4)
    1258
    1259          self.assertEqual(root[0].text, "This")
    1260          self.assertEqual(root[1].text, "is")
    1261          self.assertEqual(root[2].text, "a")
    1262          self.assertEqual(root[3].text, "test")
    1263
    1264
    1265 -class ETreeXSLTExtFuncTestCase(HelperTestCase):
    1266      """Tests for XPath extension functions in XSLT."""
    1267
    1268 -    def test_extensions1(self):
    1269          tree = self.parse('<a><b>B</b></a>')
    1270          style = self.parse('''\
    1271  <xsl:stylesheet version="1.0"
    1272      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1273      xmlns:myns="testns"
    1274      exclude-result-prefixes="myns">
    1275    <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
    1276  </xsl:stylesheet>''')
    1277
    1278          def mytext(ctxt, values):
    1279              return 'X' * len(values)
    1280
    1281          result = tree.xslt(style, {('testns', 'mytext') : mytext})
    1282          self.assertEqual(self._rootstring(result),
    1283                            _bytes('<A>X</A>'))
    1284
    1285 -    def test_extensions2(self):
    1286          tree = self.parse('<a><b>B</b></a>')
    1287          style = self.parse('''\
    1288  <xsl:stylesheet version="1.0"
    1289      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1290      xmlns:myns="testns"
    1291      exclude-result-prefixes="myns">
    1292    <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
    1293  </xsl:stylesheet>''')
    1294
    1295          def mytext(ctxt, values):
    1296              return 'X' * len(values)
    1297
    1298          namespace = etree.FunctionNamespace('testns')
    1299          namespace['mytext'] = mytext
    1300
    1301          result = tree.xslt(style)
    1302          self.assertEqual(self._rootstring(result),
    1303                            _bytes('<A>X</A>'))
    1304
    1305 -    def test_variable_result_tree_fragment(self):
    1306          tree = self.parse('<a><b>B</b><b/></a>')
    1307          style = self.parse('''\
    1308  <xsl:stylesheet version="1.0"
    1309      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1310      xmlns:myns="testns"
    1311      exclude-result-prefixes="myns">
    1312    <xsl:template match="a">
    1313      <xsl:variable name="content">
    1314         <xsl:apply-templates/>
    1315      </xsl:variable>
    1316      <A><xsl:value-of select="myns:mytext($content)"/></A>
    1317    </xsl:template>
    1318    <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template>
    1319  </xsl:stylesheet>''')
    1320
    1321          def mytext(ctxt, values):
    1322              for value in values:
    1323                  self.assertTrue(hasattr(value, 'tag'),
    1324                               "%s is not an Element" % type(value))
    1325                  self.assertEqual(value.tag, 'b')
    1326                  self.assertEqual(value.text, 'BBB')
    1327              return 'X'.join([el.tag for el in values])
    1328
    1329          namespace = etree.FunctionNamespace('testns')
    1330          namespace['mytext'] = mytext
    1331
    1332          result = tree.xslt(style)
    1333          self.assertEqual(self._rootstring(result),
    1334                            _bytes('<A>bXb</A>'))
    1335
    1336
    1337 -class ETreeXSLTExtElementTestCase(HelperTestCase):
    1338      """Tests for extension elements in XSLT."""
    1339
    1340 -    def test_extension_element(self):
    1341          tree = self.parse('<a><b>B</b></a>')
    1342          style = self.parse('''\
    1343  <xsl:stylesheet version="1.0"
    1344      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1345      xmlns:myns="testns"
    1346      extension-element-prefixes="myns"
    1347      exclude-result-prefixes="myns">
    1348    <xsl:template match="a">
    1349      <A><myns:myext>b</myns:myext></A>
    1350    </xsl:template>
    1351  </xsl:stylesheet>''')
    1352
    1353          class MyExt(etree.XSLTExtension):
    1354              def execute(self, context, self_node, input_node, output_parent):
    1355                  child = etree.Element(self_node.text)
    1356                  child.text = 'X'
    1357                  output_parent.append(child)
    1358
    1359          extensions = { ('testns', 'myext') : MyExt() }
    1360
    1361          result = tree.xslt(style, extensions=extensions)
    1362          self.assertEqual(self._rootstring(result),
    1363                            _bytes('<A><b>X</b></A>'))
    1364
    1365 -    def test_extension_element_doc_context(self):
    1366          tree = self.parse('<a><b>B</b></a>')
    1367          style = self.parse('''\
    1368  <xsl:stylesheet version="1.0"
    1369      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1370      xmlns:myns="testns"
    1371      extension-element-prefixes="myns"
    1372      exclude-result-prefixes="myns">
    1373    <xsl:template match="/">
    1374      <A><myns:myext>b</myns:myext></A>
    1375    </xsl:template>
    1376  </xsl:stylesheet>''')
    1377
    1378          tags = []
    1379
    1380          class MyExt(etree.XSLTExtension):
    1381              def execute(self, context, self_node, input_node, output_parent):
    1382                  tags.append(input_node.tag)
    1383
    1384          extensions = { ('testns', 'myext') : MyExt() }
    1385
    1386          result = tree.xslt(style, extensions=extensions)
    1387          self.assertEqual(tags, ['a'])
    1388
    1389 -    def test_extension_element_comment_pi_context(self):
    1390          tree = self.parse('<?test toast?><a><!--a comment--><?another pi?></a>')
    1391          style = self.parse('''\
    1392  <xsl:stylesheet version="1.0"
    1393      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1394      xmlns:myns="testns"
    1395      extension-element-prefixes="myns"
    1396      exclude-result-prefixes="myns">
    1397    <xsl:template match="/">
    1398      <ROOT><xsl:apply-templates /></ROOT>
    1399    </xsl:template>
    1400    <xsl:template match="comment()">
    1401      <A><myns:myext>b</myns:myext></A>
    1402    </xsl:template>
    1403    <xsl:template match="processing-instruction()">
    1404      <A><myns:myext>b</myns:myext></A>
    1405    </xsl:template>
    1406  </xsl:stylesheet>''')
    1407
    1408          text = []
    1409
    1410          class MyExt(etree.XSLTExtension):
    1411              def execute(self, context, self_node, input_node, output_parent):
    1412                  text.append(input_node.text)
    1413
    1414          extensions = { ('testns', 'myext') : MyExt() }
    1415
    1416          result = tree.xslt(style, extensions=extensions)
    1417          self.assertEqual(text, ['toast', 'a comment', 'pi'])
    1418
    1419 -    def _test_extension_element_attribute_context(self):
    1420          # currently not supported
    1421          tree = self.parse('<a test="A"><b attr="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="@test">
    1429      <A><myns:myext>b</myns:myext></A>
    1430    </xsl:template>
    1431    <xsl:template match="@attr">
    1432      <A><myns:myext>b</myns:myext></A>
    1433    </xsl:template>
    1434  </xsl:stylesheet>''')
    1435
    1436          text = []
    1437
    1438          class MyExt(etree.XSLTExtension):
    1439              def execute(self, context, self_node, attr_value, output_parent):
    1440                  text.append(attr_value)
    1441
    1442          extensions = { ('testns', 'myext') : MyExt() }
    1443
    1444          result = tree.xslt(style, extensions=extensions)
    1445          self.assertEqual(text, ['A', 'B'])
    1446
    1447 -    def test_extension_element_content(self):
    1448          tree = self.parse('<a><b>B</b></a>')
    1449          style = self.parse('''\
    1450  <xsl:stylesheet version="1.0"
    1451      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1452      xmlns:myns="testns"
    1453      extension-element-prefixes="myns">
    1454    <xsl:template match="a">
    1455      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1456    </xsl:template>
    1457  </xsl:stylesheet>''')
    1458
    1459          class MyExt(etree.XSLTExtension):
    1460              def execute(self, context, self_node, input_node, output_parent):
    1461                  output_parent.extend(list(self_node)[1:])
    1462
    1463          extensions = { ('testns', 'myext') : MyExt() }
    1464
    1465          result = tree.xslt(style, extensions=extensions)
    1466          self.assertEqual(self._rootstring(result),
    1467                            _bytes('<A><y>Y</y><z/></A>'))
    1468
    1469 -    def test_extension_element_apply_templates(self):
    1470          tree = self.parse('<a><b>B</b></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    <xsl:template match="a">
    1477      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1478    </xsl:template>
    1479    <xsl:template match="x" />
    1480    <xsl:template match="z">XYZ</xsl:template>
    1481  </xsl:stylesheet>''')
    1482
    1483          class MyExt(etree.XSLTExtension):
    1484              def execute(self, context, self_node, input_node, output_parent):
    1485                  for child in self_node:
    1486                      for result in self.apply_templates(context, child):
    1487                          if isinstance(result, basestring):
    1488                              el = etree.Element("T")
    1489                              el.text = result
    1490                          else:
    1491                              el = result
    1492                          output_parent.append(el)
    1493
    1494          extensions = { ('testns', 'myext') : MyExt() }
    1495
    1496          result = tree.xslt(style, extensions=extensions)
    1497          self.assertEqual(self._rootstring(result),
    1498                            _bytes('<A><T>Y</T><T>XYZ</T></A>'))
    1499
    1500 -    def test_extension_element_apply_templates_elements_only(self):
    1501          tree = self.parse('<a><b>B</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    <xsl:template match="a">
    1508      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1509    </xsl:template>
    1510    <xsl:template match="x"><X/></xsl:template>
    1511    <xsl:template match="z">XYZ</xsl:template>
    1512  </xsl:stylesheet>''')
    1513
    1514          class MyExt(etree.XSLTExtension):
    1515              def execute(self, context, self_node, input_node, output_parent):
    1516                  for child in self_node:
    1517                      for result in self.apply_templates(context, child,
    1518                                                         elements_only=True):
    1519                          assert not isinstance(result, basestring)
    1520                          output_parent.append(result)
    1521
    1522          extensions = { ('testns', 'myext') : MyExt() }
    1523
    1524          result = tree.xslt(style, extensions=extensions)
    1525          self.assertEqual(self._rootstring(result),
    1526                            _bytes('<A><X/></A>'))
    1527
    1528 -    def test_extension_element_apply_templates_remove_blank_text(self):
    1529          tree = self.parse('<a><b>B</b></a>')
    1530          style = self.parse('''\
    1531  <xsl:stylesheet version="1.0"
    1532      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1533      xmlns:myns="testns"
    1534      extension-element-prefixes="myns">
    1535    <xsl:template match="a">
    1536      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1537    </xsl:template>
    1538    <xsl:template match="x"><X/></xsl:template>
    1539    <xsl:template match="y"><xsl:text>   </xsl:text></xsl:template>
    1540    <xsl:template match="z">XYZ</xsl:template>
    1541  </xsl:stylesheet>''')
    1542
    1543          class MyExt(etree.XSLTExtension):
    1544              def execute(self, context, self_node, input_node, output_parent):
    1545                  for child in self_node:
    1546                      for result in self.apply_templates(context, child,
    1547                                                         remove_blank_text=True):
    1548                          if isinstance(result, basestring):
    1549                              assert result.strip()
    1550                              el = etree.Element("T")
    1551                              el.text = result
    1552                          else:
    1553                              el = result
    1554                          output_parent.append(el)
    1555
    1556          extensions = { ('testns', 'myext') : MyExt() }
    1557
    1558          result = tree.xslt(style, extensions=extensions)
    1559          self.assertEqual(self._rootstring(result),
    1560                            _bytes('<A><X/><T>XYZ</T></A>'))
    1561
    1562 -    def test_extension_element_apply_templates_target_node(self):
    1563          tree = self.parse('<a><b>B</b></a>')
    1564          style = self.parse('''\
    1565  <xsl:stylesheet version="1.0"
    1566      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1567      xmlns:myns="testns"
    1568      extension-element-prefixes="myns">
    1569    <xsl:template match="a">
    1570      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1571    </xsl:template>
    1572    <xsl:template match="x" />
    1573    <xsl:template match="z">XYZ</xsl:template>
    1574  </xsl:stylesheet>''')
    1575
    1576          class MyExt(etree.XSLTExtension):
    1577              def execute(self, context, self_node, input_node, output_parent):
    1578                  for child in self_node:
    1579                      self.apply_templates(context, child, output_parent)
    1580
    1581          extensions = { ('testns', 'myext') : MyExt() }
    1582
    1583          result = tree.xslt(style, extensions=extensions)
    1584          self.assertEqual(self._rootstring(result),
    1585                            _bytes('<A>YXYZ</A>'))
    1586
    1587 -    def test_extension_element_apply_templates_target_node_doc(self):
    1588          tree = self.parse('<a><b>B</b></a>')
    1589          style = self.parse('''\
    1590  <xsl:stylesheet version="1.0"
    1591      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1592      xmlns:myns="testns"
    1593      extension-element-prefixes="myns">
    1594    <xsl:template match="a">
    1595      <myns:myext><x>X</x><y>Y</y><z/></myns:myext>
    1596    </xsl:template>
    1597    <xsl:template match="x"><xsl:processing-instruction name="test">TEST</xsl:processing-instruction></xsl:template>
    1598    <xsl:template match="y"><Y>XYZ</Y></xsl:template>
    1599    <xsl:template match="z"><xsl:comment>TEST</xsl:comment></xsl:template>
    1600  </xsl:stylesheet>''')
    1601
    1602          class MyExt(etree.XSLTExtension):
    1603              def execute(self, context, self_node, input_node, output_parent):
    1604                  for child in self_node:
    1605                      self.apply_templates(context, child, output_parent)
    1606
    1607          extensions = { ('testns', 'myext') : MyExt() }
    1608
    1609          result = tree.xslt(style, extensions=extensions)
    1610          self.assertEqual(etree.tostring(result),
    1611                            _bytes('<?test TEST?><Y>XYZ</Y><!--TEST-->'))
    1612
    1613 -    def test_extension_element_process_children(self):
    1614          tree = self.parse('<a><b>E</b></a>')
    1615          style = self.parse('''\
    1616  <xsl:stylesheet version="1.0"
    1617      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1618      xmlns:myns="testns"
    1619      extension-element-prefixes="myns">
    1620    <xsl:template match="a">
    1621      <xsl:variable name="testvar">yo</xsl:variable>
    1622      <A>
    1623        <myns:myext>
    1624          <xsl:attribute name="attr">
    1625            <xsl:value-of select="$testvar" />
    1626          </xsl:attribute>
    1627          <B>
    1628            <xsl:choose>
    1629              <xsl:when test="1 = 2"><C/></xsl:when>
    1630              <xsl:otherwise><D><xsl:value-of select="b/text()" /></D></xsl:otherwise>
    1631            </xsl:choose>
    1632          </B>
    1633        </myns:myext>
    1634      </A>
    1635    </xsl:template>
    1636  </xsl:stylesheet>''')
    1637
    1638          class MyExt(etree.XSLTExtension):
    1639              def execute(self, context, self_node, input_node, output_parent):
    1640                  el = etree.Element('MY')
    1641                  self.process_children(context, el)
    1642                  output_parent.append(el)
    1643
    1644          extensions = { ('testns', 'myext') : MyExt() }
    1645
    1646          result = tree.xslt(style, extensions=extensions)
    1647          self.assertEqual(self._rootstring(result),
    1648                            _bytes('<A><MYattr="yo"><B><D>E</D></B></MY></A>'))
    1649
    1650 -    def test_extension_element_process_children_to_append_only(self):
    1651          tree = self.parse('<a/>')
    1652          style = self.parse('''\
    1653  <xsl:stylesheet version="1.0"
    1654      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1655      xmlns:myns="testns"
    1656      extension-element-prefixes="myns">
    1657    <xsl:template match="a">
    1658      <myns:myext>
    1659        <A/>
    1660      </myns:myext>
    1661    </xsl:template>
    1662  </xsl:stylesheet>''')
    1663
    1664          class MyExt(etree.XSLTExtension):
    1665              def execute(self, context, self_node, input_node, output_parent):
    1666                  self.process_children(context, output_parent)
    1667
    1668          extensions = { ('testns', 'myext') : MyExt() }
    1669
    1670          result = tree.xslt(style, extensions=extensions)
    1671          self.assertEqual(self._rootstring(result),
    1672                            _bytes('<A/>'))
    1673
    1674 -    def test_extension_element_process_children_to_read_only_raise(self):
    1675          tree = self.parse('<a/>')
    1676          style = self.parse('''\
    1677  <xsl:stylesheet version="1.0"
    1678      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1679      xmlns:myns="testns"
    1680      extension-element-prefixes="myns">
    1681    <xsl:template match="a">
    1682      <myns:myext>
    1683        <A/>
    1684      </myns:myext>
    1685    </xsl:template>
    1686  </xsl:stylesheet>''')
    1687
    1688          class MyExt(etree.XSLTExtension):
    1689              def execute(self, context, self_node, input_node, output_parent):
    1690                  self.process_children(context, self_node)
    1691
    1692          extensions = { ('testns', 'myext') : MyExt() }
    1693
    1694          self.assertRaises(TypeError, tree.xslt, style, extensions=extensions)
    1695
    1696 -    def test_extension_element_process_children_with_subextension_element(self):
    1697          tree = self.parse('<a/>')
    1698          style = self.parse('''\
    1699  <xsl:stylesheet version="1.0"
    1700      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1701      xmlns:myns="testns"
    1702      extension-element-prefixes="myns">
    1703    <xsl:template match="a">
    1704      <myns:myext>
    1705        <A><myns:myext><B/></myns:myext></A>
    1706      </myns:myext>
    1707    </xsl:template>
    1708  </xsl:stylesheet>''')
    1709
    1710          class MyExt(etree.XSLTExtension):
    1711              callback_call_counter = 0
    1712              def execute(self, context, self_node, input_node, output_parent):
    1713                  self.callback_call_counter += 1
    1714                  el = etree.Element('MY', n=str(self.callback_call_counter))
    1715                  self.process_children(context, el)
    1716                  output_parent.append(el)
    1717
    1718          extensions = { ('testns', 'myext') : MyExt() }
    1719
    1720          result = tree.xslt(style, extensions=extensions)
    1721          self.assertEqual(self._rootstring(result),
    1722                            _bytes('<MYn="1"><A><MYn="2"><B/></MY></A></MY>'))
    1723
    1724 -    def test_extension_element_raise(self):
    1725          tree = self.parse('<a><b>B</b></a>')
    1726          style = self.parse('''\
    1727  <xsl:stylesheet version="1.0"
    1728      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1729      xmlns:myns="testns"
    1730      extension-element-prefixes="myns"
    1731      exclude-result-prefixes="myns">
    1732    <xsl:template match="a">
    1733      <A><myns:myext>b</myns:myext></A>
    1734    </xsl:template>
    1735  </xsl:stylesheet>''')
    1736
    1737          class MyError(Exception):
    1738              pass
    1739
    1740          class MyExt(etree.XSLTExtension):
    1741              def execute(self, context, self_node, input_node, output_parent):
    1742                  raise MyError("expected!")
    1743
    1744          extensions = { ('testns', 'myext') : MyExt() }
    1745          self.assertRaises(MyError, tree.xslt, style, extensions=extensions)
    1746
    1747
    1748 -class Py3XSLTTestCase(HelperTestCase):
    1749      """XSLT tests for etree under Python 3"""
    1750
    1751      pytestmark = skipif('sys.version_info < (3,0)')
    1752
    1753 -    def test_xslt_result_bytes(self):
    1754          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1755          style = self.parse('''\
    1756  <xsl:stylesheet version="1.0"
    1757      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1758    <xsl:template match="*" />
    1759    <xsl:template match="/">
    1760      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1761    </xsl:template>
    1762  </xsl:stylesheet>''')
    1763
    1764          st = etree.XSLT(style)
    1765          res = st(tree)
    1766          self.assertEqual(_bytes('''\
    1767  <?xml version="1.0"?>
    1768  <foo>B</foo>
    1769  '''),
    1770                            bytes(res))
    1771
    1772 -    def test_xslt_result_bytearray(self):
    1773          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1774          style = self.parse('''\
    1775  <xsl:stylesheet version="1.0"
    1776      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1777    <xsl:template match="*" />
    1778    <xsl:template match="/">
    1779      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1780    </xsl:template>
    1781  </xsl:stylesheet>''')
    1782
    1783          st = etree.XSLT(style)
    1784          res = st(tree)
    1785          self.assertEqual(_bytes('''\
    1786  <?xml version="1.0"?>
    1787  <foo>B</foo>
    1788  '''),
    1789                            bytearray(res))
    1790
    1791 -    def test_xslt_result_memoryview(self):
    1792          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1793          style = self.parse('''\
    1794  <xsl:stylesheet version="1.0"
    1795      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1796    <xsl:template match="*" />
    1797    <xsl:template match="/">
    1798      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1799    </xsl:template>
    1800  </xsl:stylesheet>''')
    1801
    1802          st = etree.XSLT(style)
    1803          res = st(tree)
    1804          self.assertEqual(_bytes('''\
    1805  <?xml version="1.0"?>
    1806  <foo>B</foo>
    1807  '''),
    1808                            bytes(memoryview(res)))
    1809
    1810
    1811 -def test_suite():
    1812      suite = unittest.TestSuite()
    1813      suite.addTests([unittest.makeSuite(ETreeXSLTTestCase)])
    1814      suite.addTests([unittest.makeSuite(ETreeEXSLTTestCase)])
    1815      suite.addTests([unittest.makeSuite(ETreeXSLTExtFuncTestCase)])
    1816      suite.addTests([unittest.makeSuite(ETreeXSLTExtElementTestCase)])
    1817      if is_python3:
    1818          suite.addTests([unittest.makeSuite(Py3XSLTTestCase)])
    1819      suite.addTests(
    1820          [make_doctest('../../../doc/extensions.txt')])
    1821      suite.addTests(
    1822          [make_doctest('../../../doc/xpathxslt.txt')])
    1823      return suite
    1824
    1825  if __name__ == '__main__':
    1826      print('to test use test.py %s' % __file__)
    1827