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 = 'MY/BASE/test.xml'  # seems to be the same on Windows
     745          xslt = etree.XSLT(etree.XML(
     746              stylesheet_xml, parser,
     747              base_url=os.path.join('MY', 'BASE', 'FILE')))
     748
     749          self.assertEqual(called['count'], 0)
     750          result = xslt(etree.XML('<a/>'))
     751          self.assertEqual(called['count'], 1)
     752
     753          # now the same thing with a stylesheet base URL
     754          called['count'] = 0
     755          expected_url = 'http://server.com/BASE/DIR/test.xml'
     756          xslt = etree.XSLT(etree.XML(
     757              stylesheet_xml, parser,
     758              base_url='http://server.com/BASE/DIR/FILE'))
     759
     760          self.assertEqual(called['count'], 0)
     761          result = xslt(etree.XML('<a/>'))
     762          self.assertEqual(called['count'], 1)
     763
     764          # now the same thing with a stylesheet base file:// URL
     765          called['count'] = 0
     766          expected_url = 'file://BASE/DIR/test.xml'
     767          xslt = etree.XSLT(etree.XML(
     768              stylesheet_xml, parser,
     769              base_url='file://BASE/DIR/FILE'))
     770
     771          self.assertEqual(called['count'], 0)
     772          result = xslt(etree.XML('<a/>'))
     773          self.assertEqual(called['count'], 1)
     774
     775 -    def test_xslt_document_parse_allow(self):
     776          access_control = etree.XSLTAccessControl(read_file=True)
     777          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
     778                            access_control=access_control)
     779          result = xslt(etree.XML('<a/>'))
     780          root = result.getroot()
     781          self.assertEqual(root.tag,
     782                           'test')
     783          self.assertEqual(root[0].tag,
     784                           '{http://www.w3.org/1999/XSL/Transform}stylesheet')
     785
     786 -    def test_xslt_document_parse_deny(self):
     787          access_control = etree.XSLTAccessControl(read_file=False)
     788          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
     789                            access_control=access_control)
     790          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
     791
     792 -    def test_xslt_document_parse_deny_all(self):
     793          access_control = etree.XSLTAccessControl.DENY_ALL
     794          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
     795                            access_control=access_control)
     796          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
     797
     798 -    def test_xslt_access_control_repr(self):
     799          access_control = etree.XSLTAccessControl.DENY_ALL
     800          self.assertTrue(repr(access_control).startswith(type(access_control).__name__))
     801          self.assertEqual(repr(access_control), repr(access_control))
     802          self.assertNotEqual(repr(etree.XSLTAccessControl.DENY_ALL),
     803                              repr(etree.XSLTAccessControl.DENY_WRITE))
     804          self.assertNotEqual(repr(etree.XSLTAccessControl.DENY_ALL),
     805                              repr(etree.XSLTAccessControl()))
     806
     807 -    def test_xslt_move_result(self):
     808          root = etree.XML(_bytes('''\
     809          <transform>
     810            <widget displayType="fieldset"/>
     811          </transform>'''))
     812
     813          xslt = etree.XSLT(etree.XML(_bytes('''\
     814          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     815            <xsl:output method="html" indent="no"/>
     816            <xsl:template match="/">
     817              <html>
     818                <xsl:apply-templates/>
     819              </html>
     820            </xsl:template>
     821
     822            <xsl:template match="widget">
     823              <xsl:element name="{@displayType}"/>
     824            </xsl:template>
     825
     826          </xsl:stylesheet>''')))
     827
     828          result = xslt(root[0])
     829          root[:] = result.getroot()[:]
     830          del root # segfaulted before
     831
     832 -    def test_xslt_pi(self):
     833          tree = self.parse('''\
     834  <?xml version="1.0"?>
     835  <?xml-stylesheet type="text/xsl" href="%s"?>
     836  <a>
     837    <b>B</b>
     838    <c>C</c>
     839  </a>''' % fileInTestDir("test1.xslt"))
     840
     841          style_root = tree.getroot().getprevious().parseXSL().getroot()
     842          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
     843                            style_root.tag)
     844
     845 -    def test_xslt_pi_embedded_xmlid(self):
     846          # test xml:id dictionary lookup mechanism
     847          tree = self.parse('''\
     848  <?xml version="1.0"?>
     849  <?xml-stylesheet type="text/xsl" href="#style"?>
     850  <a>
     851    <b>B</b>
     852    <c>C</c>
     853    <xsl:stylesheet version="1.0" xml:id="style"
     854        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     855      <xsl:template match="*" />
     856      <xsl:template match="/">
     857        <foo><xsl:value-of select="/a/b/text()" /></foo>
     858      </xsl:template>
     859    </xsl:stylesheet>
     860  </a>''')
     861
     862          style_root = tree.getroot().getprevious().parseXSL().getroot()
     863          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
     864                            style_root.tag)
     865
     866          st = etree.XSLT(style_root)
     867          res = st(tree)
     868          self.assertEqual('''\
     869  <?xml version="1.0"?>
     870  <foo>B</foo>
     871  ''',
     872                            str(res))
     873
     874 -    def test_xslt_pi_embedded_id(self):
     875          # test XPath lookup mechanism
     876          tree = self.parse('''\
     877  <?xml version="1.0"?>
     878  <?xml-stylesheet type="text/xsl" href="#style"?>
     879  <a>
     880    <b>B</b>
     881    <c>C</c>
     882  </a>''')
     883
     884          style = self.parse('''\
     885  <xsl:stylesheet version="1.0" xml:id="style"
     886      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     887    <xsl:template match="*" />
     888    <xsl:template match="/">
     889      <foo><xsl:value-of select="/a/b/text()" /></foo>
     890    </xsl:template>
     891  </xsl:stylesheet>
     892  ''')
     893
     894          tree.getroot().append(style.getroot())
     895
     896          style_root = tree.getroot().getprevious().parseXSL().getroot()
     897          self.assertEqual("{http://www.w3.org/1999/XSL/Transform}stylesheet",
     898                            style_root.tag)
     899
     900          st = etree.XSLT(style_root)
     901          res = st(tree)
     902          self.assertEqual('''\
     903  <?xml version="1.0"?>
     904  <foo>B</foo>
     905  ''',
     906                            str(res))
     907
     908 -    def test_xslt_pi_get(self):
     909          tree = self.parse('''\
     910  <?xml version="1.0"?>
     911  <?xml-stylesheet type="text/xsl" href="TEST"?>
     912  <a>
     913    <b>B</b>
     914    <c>C</c>
     915  </a>''')
     916
     917          pi = tree.getroot().getprevious()
     918          self.assertEqual("TEST", pi.get("href"))
     919
     920 -    def test_xslt_pi_get_all(self):
     921          tree = self.parse('''\
     922  <?xml version="1.0"?>
     923  <?xml-stylesheet type="text/xsl" href="TEST"?>
     924  <a>
     925    <b>B</b>
     926    <c>C</c>
     927  </a>''')
     928
     929          pi = tree.getroot().getprevious()
     930          self.assertEqual("TEST", pi.get("href"))
     931          self.assertEqual("text/xsl", pi.get("type"))
     932          self.assertEqual(None, pi.get("motz"))
     933
     934 -    def test_xslt_pi_get_all_reversed(self):
     935          tree = self.parse('''\
     936  <?xml version="1.0"?>
     937  <?xml-stylesheet href="TEST" type="text/xsl"?>
     938  <a>
     939    <b>B</b>
     940    <c>C</c>
     941  </a>''')
     942
     943          pi = tree.getroot().getprevious()
     944          self.assertEqual("TEST", pi.get("href"))
     945          self.assertEqual("text/xsl", pi.get("type"))
     946          self.assertEqual(None, pi.get("motz"))
     947
     948 -    def test_xslt_pi_get_unknown(self):
     949          tree = self.parse('''\
     950  <?xml version="1.0"?>
     951  <?xml-stylesheet type="text/xsl" href="TEST"?>
     952  <a>
     953    <b>B</b>
     954    <c>C</c>
     955  </a>''')
     956
     957          pi = tree.getroot().getprevious()
     958          self.assertEqual(None, pi.get("unknownattribute"))
     959
     960 -    def test_xslt_pi_set_replace(self):
     961          tree = self.parse('''\
     962  <?xml version="1.0"?>
     963  <?xml-stylesheet type="text/xsl" href="TEST"?>
     964  <a>
     965    <b>B</b>
     966    <c>C</c>
     967  </a>''')
     968
     969          pi = tree.getroot().getprevious()
     970          self.assertEqual("TEST", pi.get("href"))
     971
     972          pi.set("href", "TEST123")
     973          self.assertEqual("TEST123", pi.get("href"))
     974
     975 -    def test_xslt_pi_set_new(self):
     976          tree = self.parse('''\
     977  <?xml version="1.0"?>
     978  <?xml-stylesheet type="text/xsl"?>
     979  <a>
     980    <b>B</b>
     981    <c>C</c>
     982  </a>''')
     983
     984          pi = tree.getroot().getprevious()
     985          self.assertEqual(None, pi.get("href"))
     986
     987          pi.set("href", "TEST")
     988          self.assertEqual("TEST", pi.get("href"))
     989
     990 -class ETreeEXSLTTestCase(HelperTestCase):
     991      """EXSLT tests"""
     992
     993 -    def test_exslt_str(self):
     994          tree = self.parse('<a><b>B</b><c>C</c></a>')
     995          style = self.parse('''\
     996  <xsl:stylesheet version="1.0"
     997      xmlns:str="http://exslt.org/strings"
     998      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     999      exclude-result-prefixes="str xsl">
    1000    <xsl:template match="text()">
    1001      <xsl:value-of select="str:align(string(.), '***', 'center')" />
    1002    </xsl:template>
    1003    <xsl:template match="*">
    1004      <xsl:copy>
    1005        <xsl:apply-templates/>
    1006      </xsl:copy>
    1007    </xsl:template>
    1008  </xsl:stylesheet>''')
    1009
    1010          st = etree.XSLT(style)
    1011          res = st(tree)
    1012          self.assertEqual('''\
    1013  <?xml version="1.0"?>
    1014  <a><b>*B*</b><c>*C*</c></a>
    1015  ''',
    1016                            str(res))
    1017
    1018      if etree.LIBXSLT_VERSION >= (1,1,21):
    1019 -        def test_exslt_str_attribute_replace(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:xsl='http://www.w3.org/1999/XSL/Transform'
    1024            xmlns:str="http://exslt.org/strings"
    1025            extension-element-prefixes="str">
    1026
    1027            <xsl:template match="/">
    1028              <h1 class="{str:replace('abc', 'b', 'x')}">test</h1>
    1029            </xsl:template>
    1030
    1031        </xsl:stylesheet>''')
    1032
    1033              st = etree.XSLT(style)
    1034              res = st(tree)
    1035              self.assertEqual('''\
    1036  <?xml version="1.0"?>
    1037  <h1 class="axc">test</h1>
    1038  ''',
    1039                                str(res))
    1040
    1041 -    def test_exslt_math(self):
    1042          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1043          style = self.parse('''\
    1044  <xsl:stylesheet version="1.0"
    1045      xmlns:math="http://exslt.org/math"
    1046      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1047      exclude-result-prefixes="math xsl">
    1048    <xsl:template match="*">
    1049      <xsl:copy>
    1050        <xsl:attribute name="pi">
    1051          <xsl:value-of select="math:constant('PI', count(*)+2)"/>
    1052        </xsl:attribute>
    1053        <xsl:apply-templates/>
    1054      </xsl:copy>
    1055    </xsl:template>
    1056  </xsl:stylesheet>''')
    1057
    1058          st = etree.XSLT(style)
    1059          res = st(tree)
    1060          self.assertEqual('''\
    1061  <?xml version="1.0"?>
    1062  <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a>
    1063  ''',
    1064                            str(res))
    1065
    1066 -    def test_exslt_regexp_test(self):
    1067          xslt = etree.XSLT(etree.XML(_bytes("""\
    1068  <xsl:stylesheet version="1.0"
    1069     xmlns:regexp="http://exslt.org/regular-expressions"
    1070     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1071    <xsl:template match="*">
    1072      <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test>
    1073    </xsl:template>
    1074  </xsl:stylesheet>
    1075  """)))
    1076          result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>')))
    1077          root = result.getroot()
    1078          self.assertEqual(root.tag,
    1079                            'test')
    1080          self.assertEqual(len(root), 1)
    1081          self.assertEqual(root[0].tag,
    1082                            'b')
    1083          self.assertEqual(root[0].text,
    1084                            '987')
    1085
    1086 -    def test_exslt_regexp_replace(self):
    1087          xslt = etree.XSLT(etree.XML("""\
    1088  <xsl:stylesheet version="1.0"
    1089     xmlns:regexp="http://exslt.org/regular-expressions"
    1090     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1091    <xsl:template match="*">
    1092      <test>
    1093        <xsl:copy-of select="regexp:replace(string(.), 'd.', '',   'XX')"/>
    1094        <xsl:text>-</xsl:text>
    1095        <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/>
    1096      </test>
    1097    </xsl:template>
    1098  </xsl:stylesheet>
    1099  """))
    1100          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
    1101          root = result.getroot()
    1102          self.assertEqual(root.tag,
    1103                            'test')
    1104          self.assertEqual(len(root), 0)
    1105          self.assertEqual(root.text, 'abXXdEeDed-abXXXXeXXd')
    1106
    1107 -    def test_exslt_regexp_match(self):
    1108          xslt = etree.XSLT(etree.XML("""\
    1109  <xsl:stylesheet version="1.0"
    1110     xmlns:regexp="http://exslt.org/regular-expressions"
    1111     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1112    <xsl:template match="*">
    1113      <test>
    1114        <test1><xsl:copy-of  select="regexp:match(string(.), 'd.')"/></test1>
    1115        <test2><xsl:copy-of  select="regexp:match(string(.), 'd.', 'g')"/></test2>
    1116        <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i>
    1117      </test>
    1118    </xsl:template>
    1119  </xsl:stylesheet>
    1120  """))
    1121          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
    1122          root = result.getroot()
    1123          self.assertEqual(root.tag,  'test')
    1124          self.assertEqual(len(root), 3)
    1125
    1126          self.assertEqual(len(root[0]), 1)
    1127          self.assertEqual(root[0][0].tag, 'match')
    1128          self.assertEqual(root[0][0].text, 'dC')
    1129
    1130          self.assertEqual(len(root[1]), 2)
    1131          self.assertEqual(root[1][0].tag, 'match')
    1132          self.assertEqual(root[1][0].text, 'dC')
    1133          self.assertEqual(root[1][1].tag, 'match')
    1134          self.assertEqual(root[1][1].text, 'dE')
    1135
    1136          self.assertEqual(len(root[2]), 3)
    1137          self.assertEqual(root[2][0].tag, 'match')
    1138          self.assertEqual(root[2][0].text, 'dC')
    1139          self.assertEqual(root[2][1].tag, 'match')
    1140          self.assertEqual(root[2][1].text, 'dE')
    1141          self.assertEqual(root[2][2].tag, 'match')
    1142          self.assertEqual(root[2][2].text, 'De')
    1143
    1144 -    def test_exslt_regexp_match_groups(self):
    1145          xslt = etree.XSLT(etree.XML(_bytes("""\
    1146  <xsl:stylesheet version="1.0"
    1147     xmlns:regexp="http://exslt.org/regular-expressions"
    1148     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1149    <xsl:template match="/">
    1150      <test>
    1151        <xsl:for-each select="regexp:match(
    1152              '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )">
    1153          <test1><xsl:value-of select="."/></test1>
    1154        </xsl:for-each>
    1155      </test>
    1156    </xsl:template>
    1157  </xsl:stylesheet>
    1158  """)))
    1159          result = xslt(etree.XML(_bytes('<a/>')))
    1160          root = result.getroot()
    1161          self.assertEqual(root.tag,  'test')
    1162          self.assertEqual(len(root), 4)
    1163
    1164          self.assertEqual(root[0].text, "123abc567")
    1165          self.assertEqual(root[1].text, "123")
    1166          self.assertEqual(root[2].text, "abc")
    1167          self.assertEqual(root[3].text, "567")
    1168
    1169 -    def test_exslt_regexp_match1(self):
    1170          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1171          xslt = etree.XSLT(etree.XML(_bytes("""\
    1172  <xsl:stylesheet version="1.0"
    1173     xmlns:regexp="http://exslt.org/regular-expressions"
    1174     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1175    <xsl:template match="/">
    1176      <test>
    1177        <xsl:for-each select="regexp:match(
    1178              'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml',
    1179              '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')">
    1180          <test1><xsl:value-of select="."/></test1>
    1181        </xsl:for-each>
    1182      </test>
    1183    </xsl:template>
    1184  </xsl:stylesheet>
    1185  """)))
    1186          result = xslt(etree.XML(_bytes('<a/>')))
    1187          root = result.getroot()
    1188          self.assertEqual(root.tag,  'test')
    1189          self.assertEqual(len(root), 5)
    1190
    1191          self.assertEqual(
    1192              root[0].text,
    1193              "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml")
    1194          self.assertEqual(
    1195              root[1].text,
    1196              "http")
    1197          self.assertEqual(
    1198              root[2].text,
    1199              "www.bayes.co.uk")
    1200          self.assertFalse(root[3].text)
    1201          self.assertEqual(
    1202              root[4].text,
    1203              "/xml/index.xml?/xml/utils/rechecker.xml")
    1204
    1205 -    def test_exslt_regexp_match2(self):
    1206          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1207          xslt = etree.XSLT(self.parse("""\
    1208  <xsl:stylesheet version="1.0"
    1209     xmlns:regexp="http://exslt.org/regular-expressions"
    1210     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1211    <xsl:template match="/">
    1212      <test>
    1213        <xsl:for-each select="regexp:match(
    1214              'This is a test string', '(\w+)', 'g')">
    1215          <test1><xsl:value-of select="."/></test1>
    1216        </xsl:for-each>
    1217      </test>
    1218    </xsl:template>
    1219  </xsl:stylesheet>
    1220  """))
    1221          result = xslt(etree.XML(_bytes('<a/>')))
    1222          root = result.getroot()
    1223          self.assertEqual(root.tag,  'test')
    1224          self.assertEqual(len(root), 5)
    1225
    1226          self.assertEqual(root[0].text, "This")
    1227          self.assertEqual(root[1].text, "is")
    1228          self.assertEqual(root[2].text, "a")
    1229          self.assertEqual(root[3].text, "test")
    1230          self.assertEqual(root[4].text, "string")
    1231
    1232 -    def _test_exslt_regexp_match3(self):
    1233          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1234          # THIS IS NOT SUPPORTED!
    1235          xslt = etree.XSLT(etree.XML(_bytes("""\
    1236  <xsl:stylesheet version="1.0"
    1237     xmlns:regexp="http://exslt.org/regular-expressions"
    1238     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1239    <xsl:template match="/">
    1240      <test>
    1241        <xsl:for-each select="regexp:match(
    1242              'This is a test string', '([a-z])+ ', 'g')">
    1243          <test1><xsl:value-of select="."/></test1>
    1244        </xsl:for-each>
    1245      </test>
    1246    </xsl:template>
    1247  </xsl:stylesheet>
    1248  """)))
    1249          result = xslt(etree.XML(_bytes('<a/>')))
    1250          root = result.getroot()
    1251          self.assertEqual(root.tag,  'test')
    1252          self.assertEqual(len(root), 4)
    1253
    1254          self.assertEqual(root[0].text, "his")
    1255          self.assertEqual(root[1].text, "is")
    1256          self.assertEqual(root[2].text, "a")
    1257          self.assertEqual(root[3].text, "test")
    1258
    1259 -    def _test_exslt_regexp_match4(self):
    1260          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1261          # THIS IS NOT SUPPORTED!
    1262          xslt = etree.XSLT(etree.XML(_bytes("""\
    1263  <xsl:stylesheet version="1.0"
    1264     xmlns:regexp="http://exslt.org/regular-expressions"
    1265     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1266    <xsl:template match="/">
    1267      <test>
    1268        <xsl:for-each select="regexp:match(
    1269              'This is a test string', '([a-z])+ ', 'gi')">
    1270          <test1><xsl:value-of select="."/></test1>
    1271        </xsl:for-each>
    1272      </test>
    1273    </xsl:template>
    1274  </xsl:stylesheet>
    1275  """)))
    1276          result = xslt(etree.XML(_bytes('<a/>')))
    1277          root = result.getroot()
    1278          self.assertEqual(root.tag,  'test')
    1279          self.assertEqual(len(root), 4)
    1280
    1281          self.assertEqual(root[0].text, "This")
    1282          self.assertEqual(root[1].text, "is")
    1283          self.assertEqual(root[2].text, "a")
    1284          self.assertEqual(root[3].text, "test")
    1285
    1286
    1287 -class ETreeXSLTExtFuncTestCase(HelperTestCase):
    1288      """Tests for XPath extension functions in XSLT."""
    1289
    1290 -    def test_extensions1(self):
    1291          tree = self.parse('<a><b>B</b></a>')
    1292          style = self.parse('''\
    1293  <xsl:stylesheet version="1.0"
    1294      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1295      xmlns:myns="testns"
    1296      exclude-result-prefixes="myns">
    1297    <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
    1298  </xsl:stylesheet>''')
    1299
    1300          def mytext(ctxt, values):
    1301              return 'X' * len(values)
    1302
    1303          result = tree.xslt(style, {('testns', 'mytext') : mytext})
    1304          self.assertEqual(self._rootstring(result),
    1305                            _bytes('<A>X</A>'))
    1306
    1307 -    def test_extensions2(self):
    1308          tree = self.parse('<a><b>B</b></a>')
    1309          style = self.parse('''\
    1310  <xsl:stylesheet version="1.0"
    1311      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1312      xmlns:myns="testns"
    1313      exclude-result-prefixes="myns">
    1314    <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
    1315  </xsl:stylesheet>''')
    1316
    1317          def mytext(ctxt, values):
    1318              return 'X' * len(values)
    1319
    1320          namespace = etree.FunctionNamespace('testns')
    1321          namespace['mytext'] = mytext
    1322
    1323          result = tree.xslt(style)
    1324          self.assertEqual(self._rootstring(result),
    1325                            _bytes('<A>X</A>'))
    1326
    1327 -    def test_variable_result_tree_fragment(self):
    1328          tree = self.parse('<a><b>B</b><b/></a>')
    1329          style = self.parse('''\
    1330  <xsl:stylesheet version="1.0"
    1331      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1332      xmlns:myns="testns"
    1333      exclude-result-prefixes="myns">
    1334    <xsl:template match="a">
    1335      <xsl:variable name="content">
    1336         <xsl:apply-templates/>
    1337      </xsl:variable>
    1338      <A><xsl:value-of select="myns:mytext($content)"/></A>
    1339    </xsl:template>
    1340    <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template>
    1341  </xsl:stylesheet>''')
    1342
    1343          def mytext(ctxt, values):
    1344              for value in values:
    1345                  self.assertTrue(hasattr(value, 'tag'),
    1346                               "%s is not an Element" % type(value))
    1347                  self.assertEqual(value.tag, 'b')
    1348                  self.assertEqual(value.text, 'BBB')
    1349              return 'X'.join([el.tag for el in values])
    1350
    1351          namespace = etree.FunctionNamespace('testns')
    1352          namespace['mytext'] = mytext
    1353
    1354          result = tree.xslt(style)
    1355          self.assertEqual(self._rootstring(result),
    1356                            _bytes('<A>bXb</A>'))
    1357
    1358
    1359 -class ETreeXSLTExtElementTestCase(HelperTestCase):
    1360      """Tests for extension elements in XSLT."""
    1361
    1362 -    def test_extension_element(self):
    1363          tree = self.parse('<a><b>B</b></a>')
    1364          style = self.parse('''\
    1365  <xsl:stylesheet version="1.0"
    1366      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1367      xmlns:myns="testns"
    1368      extension-element-prefixes="myns"
    1369      exclude-result-prefixes="myns">
    1370    <xsl:template match="a">
    1371      <A><myns:myext>b</myns:myext></A>
    1372    </xsl:template>
    1373  </xsl:stylesheet>''')
    1374
    1375          class MyExt(etree.XSLTExtension):
    1376              def execute(self, context, self_node, input_node, output_parent):
    1377                  child = etree.Element(self_node.text)
    1378                  child.text = 'X'
    1379                  output_parent.append(child)
    1380
    1381          extensions = { ('testns', 'myext') : MyExt() }
    1382
    1383          result = tree.xslt(style, extensions=extensions)
    1384          self.assertEqual(self._rootstring(result),
    1385                            _bytes('<A><b>X</b></A>'))
    1386
    1387 -    def test_extension_element_doc_context(self):
    1388          tree = self.parse('<a><b>B</b></a>')
    1389          style = self.parse('''\
    1390  <xsl:stylesheet version="1.0"
    1391      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1392      xmlns:myns="testns"
    1393      extension-element-prefixes="myns"
    1394      exclude-result-prefixes="myns">
    1395    <xsl:template match="/">
    1396      <A><myns:myext>b</myns:myext></A>
    1397    </xsl:template>
    1398  </xsl:stylesheet>''')
    1399
    1400          tags = []
    1401
    1402          class MyExt(etree.XSLTExtension):
    1403              def execute(self, context, self_node, input_node, output_parent):
    1404                  tags.append(input_node.tag)
    1405
    1406          extensions = { ('testns', 'myext') : MyExt() }
    1407
    1408          result = tree.xslt(style, extensions=extensions)
    1409          self.assertEqual(tags, ['a'])
    1410
    1411 -    def test_extension_element_comment_pi_context(self):
    1412          tree = self.parse('<?test toast?><a><!--a comment--><?another pi?></a>')
    1413          style = self.parse('''\
    1414  <xsl:stylesheet version="1.0"
    1415      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1416      xmlns:myns="testns"
    1417      extension-element-prefixes="myns"
    1418      exclude-result-prefixes="myns">
    1419    <xsl:template match="/">
    1420      <ROOT><xsl:apply-templates /></ROOT>
    1421    </xsl:template>
    1422    <xsl:template match="comment()">
    1423      <A><myns:myext>b</myns:myext></A>
    1424    </xsl:template>
    1425    <xsl:template match="processing-instruction()">
    1426      <A><myns:myext>b</myns:myext></A>
    1427    </xsl:template>
    1428  </xsl:stylesheet>''')
    1429
    1430          text = []
    1431
    1432          class MyExt(etree.XSLTExtension):
    1433              def execute(self, context, self_node, input_node, output_parent):
    1434                  text.append(input_node.text)
    1435
    1436          extensions = { ('testns', 'myext') : MyExt() }
    1437
    1438          result = tree.xslt(style, extensions=extensions)
    1439          self.assertEqual(text, ['toast', 'a comment', 'pi'])
    1440
    1441 -    def _test_extension_element_attribute_context(self):
    1442          # currently not supported
    1443          tree = self.parse('<a test="A"><b attr="B"/></a>')
    1444          style = self.parse('''\
    1445  <xsl:stylesheet version="1.0"
    1446      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1447      xmlns:myns="testns"
    1448      extension-element-prefixes="myns"
    1449      exclude-result-prefixes="myns">
    1450    <xsl:template match="@test">
    1451      <A><myns:myext>b</myns:myext></A>
    1452    </xsl:template>
    1453    <xsl:template match="@attr">
    1454      <A><myns:myext>b</myns:myext></A>
    1455    </xsl:template>
    1456  </xsl:stylesheet>''')
    1457
    1458          text = []
    1459
    1460          class MyExt(etree.XSLTExtension):
    1461              def execute(self, context, self_node, attr_value, output_parent):
    1462                  text.append(attr_value)
    1463
    1464          extensions = { ('testns', 'myext') : MyExt() }
    1465
    1466          result = tree.xslt(style, extensions=extensions)
    1467          self.assertEqual(text, ['A', 'B'])
    1468
    1469 -    def test_extension_element_content(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:stylesheet>''')
    1480
    1481          class MyExt(etree.XSLTExtension):
    1482              def execute(self, context, self_node, input_node, output_parent):
    1483                  output_parent.extend(list(self_node)[1:])
    1484
    1485          extensions = { ('testns', 'myext') : MyExt() }
    1486
    1487          result = tree.xslt(style, extensions=extensions)
    1488          self.assertEqual(self._rootstring(result),
    1489                            _bytes('<A><y>Y</y><z/></A>'))
    1490
    1491 -    def test_extension_element_apply_templates(self):
    1492          tree = self.parse('<a><b>B</b></a>')
    1493          style = self.parse('''\
    1494  <xsl:stylesheet version="1.0"
    1495      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1496      xmlns:myns="testns"
    1497      extension-element-prefixes="myns">
    1498    <xsl:template match="a">
    1499      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1500    </xsl:template>
    1501    <xsl:template match="x" />
    1502    <xsl:template match="z">XYZ</xsl:template>
    1503  </xsl:stylesheet>''')
    1504
    1505          class MyExt(etree.XSLTExtension):
    1506              def execute(self, context, self_node, input_node, output_parent):
    1507                  for child in self_node:
    1508                      for result in self.apply_templates(context, child):
    1509                          if isinstance(result, basestring):
    1510                              el = etree.Element("T")
    1511                              el.text = result
    1512                          else:
    1513                              el = result
    1514                          output_parent.append(el)
    1515
    1516          extensions = { ('testns', 'myext') : MyExt() }
    1517
    1518          result = tree.xslt(style, extensions=extensions)
    1519          self.assertEqual(self._rootstring(result),
    1520                            _bytes('<A><T>Y</T><T>XYZ</T></A>'))
    1521
    1522 -    def test_extension_element_apply_templates_elements_only(self):
    1523          tree = self.parse('<a><b>B</b></a>')
    1524          style = self.parse('''\
    1525  <xsl:stylesheet version="1.0"
    1526      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1527      xmlns:myns="testns"
    1528      extension-element-prefixes="myns">
    1529    <xsl:template match="a">
    1530      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1531    </xsl:template>
    1532    <xsl:template match="x"><X/></xsl:template>
    1533    <xsl:template match="z">XYZ</xsl:template>
    1534  </xsl:stylesheet>''')
    1535
    1536          class MyExt(etree.XSLTExtension):
    1537              def execute(self, context, self_node, input_node, output_parent):
    1538                  for child in self_node:
    1539                      for result in self.apply_templates(context, child,
    1540                                                         elements_only=True):
    1541                          assert not isinstance(result, basestring)
    1542                          output_parent.append(result)
    1543
    1544          extensions = { ('testns', 'myext') : MyExt() }
    1545
    1546          result = tree.xslt(style, extensions=extensions)
    1547          self.assertEqual(self._rootstring(result),
    1548                            _bytes('<A><X/></A>'))
    1549
    1550 -    def test_extension_element_apply_templates_remove_blank_text(self):
    1551          tree = self.parse('<a><b>B</b></a>')
    1552          style = self.parse('''\
    1553  <xsl:stylesheet version="1.0"
    1554      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1555      xmlns:myns="testns"
    1556      extension-element-prefixes="myns">
    1557    <xsl:template match="a">
    1558      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1559    </xsl:template>
    1560    <xsl:template match="x"><X/></xsl:template>
    1561    <xsl:template match="y"><xsl:text>   </xsl:text></xsl:template>
    1562    <xsl:template match="z">XYZ</xsl:template>
    1563  </xsl:stylesheet>''')
    1564
    1565          class MyExt(etree.XSLTExtension):
    1566              def execute(self, context, self_node, input_node, output_parent):
    1567                  for child in self_node:
    1568                      for result in self.apply_templates(context, child,
    1569                                                         remove_blank_text=True):
    1570                          if isinstance(result, basestring):
    1571                              assert result.strip()
    1572                              el = etree.Element("T")
    1573                              el.text = result
    1574                          else:
    1575                              el = result
    1576                          output_parent.append(el)
    1577
    1578          extensions = { ('testns', 'myext') : MyExt() }
    1579
    1580          result = tree.xslt(style, extensions=extensions)
    1581          self.assertEqual(self._rootstring(result),
    1582                            _bytes('<A><X/><T>XYZ</T></A>'))
    1583
    1584 -    def test_extension_element_apply_templates_target_node(self):
    1585          tree = self.parse('<a><b>B</b></a>')
    1586          style = self.parse('''\
    1587  <xsl:stylesheet version="1.0"
    1588      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1589      xmlns:myns="testns"
    1590      extension-element-prefixes="myns">
    1591    <xsl:template match="a">
    1592      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1593    </xsl:template>
    1594    <xsl:template match="x" />
    1595    <xsl:template match="z">XYZ</xsl:template>
    1596  </xsl:stylesheet>''')
    1597
    1598          class MyExt(etree.XSLTExtension):
    1599              def execute(self, context, self_node, input_node, output_parent):
    1600                  for child in self_node:
    1601                      self.apply_templates(context, child, output_parent)
    1602
    1603          extensions = { ('testns', 'myext') : MyExt() }
    1604
    1605          result = tree.xslt(style, extensions=extensions)
    1606          self.assertEqual(self._rootstring(result),
    1607                            _bytes('<A>YXYZ</A>'))
    1608
    1609 -    def test_extension_element_apply_templates_target_node_doc(self):
    1610          tree = self.parse('<a><b>B</b></a>')
    1611          style = self.parse('''\
    1612  <xsl:stylesheet version="1.0"
    1613      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1614      xmlns:myns="testns"
    1615      extension-element-prefixes="myns">
    1616    <xsl:template match="a">
    1617      <myns:myext><x>X</x><y>Y</y><z/></myns:myext>
    1618    </xsl:template>
    1619    <xsl:template match="x"><xsl:processing-instruction name="test">TEST</xsl:processing-instruction></xsl:template>
    1620    <xsl:template match="y"><Y>XYZ</Y></xsl:template>
    1621    <xsl:template match="z"><xsl:comment>TEST</xsl:comment></xsl:template>
    1622  </xsl:stylesheet>''')
    1623
    1624          class MyExt(etree.XSLTExtension):
    1625              def execute(self, context, self_node, input_node, output_parent):
    1626                  for child in self_node:
    1627                      self.apply_templates(context, child, output_parent)
    1628
    1629          extensions = { ('testns', 'myext') : MyExt() }
    1630
    1631          result = tree.xslt(style, extensions=extensions)
    1632          self.assertEqual(etree.tostring(result),
    1633                            _bytes('<?test TEST?><Y>XYZ</Y><!--TEST-->'))
    1634
    1635 -    def test_extension_element_process_children(self):
    1636          tree = self.parse('<a><b>E</b></a>')
    1637          style = self.parse('''\
    1638  <xsl:stylesheet version="1.0"
    1639      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1640      xmlns:myns="testns"
    1641      extension-element-prefixes="myns">
    1642    <xsl:template match="a">
    1643      <xsl:variable name="testvar">yo</xsl:variable>
    1644      <A>
    1645        <myns:myext>
    1646          <xsl:attribute name="attr">
    1647            <xsl:value-of select="$testvar" />
    1648          </xsl:attribute>
    1649          <B>
    1650            <xsl:choose>
    1651              <xsl:when test="1 = 2"><C/></xsl:when>
    1652              <xsl:otherwise><D><xsl:value-of select="b/text()" /></D></xsl:otherwise>
    1653            </xsl:choose>
    1654          </B>
    1655        </myns:myext>
    1656      </A>
    1657    </xsl:template>
    1658  </xsl:stylesheet>''')
    1659
    1660          class MyExt(etree.XSLTExtension):
    1661              def execute(self, context, self_node, input_node, output_parent):
    1662                  el = etree.Element('MY')
    1663                  self.process_children(context, el)
    1664                  output_parent.append(el)
    1665
    1666          extensions = { ('testns', 'myext') : MyExt() }
    1667
    1668          result = tree.xslt(style, extensions=extensions)
    1669          self.assertEqual(self._rootstring(result),
    1670                            _bytes('<A><MYattr="yo"><B><D>E</D></B></MY></A>'))
    1671
    1672 -    def test_extension_element_process_children_to_append_only(self):
    1673          tree = self.parse('<a/>')
    1674          style = self.parse('''\
    1675  <xsl:stylesheet version="1.0"
    1676      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1677      xmlns:myns="testns"
    1678      extension-element-prefixes="myns">
    1679    <xsl:template match="a">
    1680      <myns:myext>
    1681        <A/>
    1682      </myns:myext>
    1683    </xsl:template>
    1684  </xsl:stylesheet>''')
    1685
    1686          class MyExt(etree.XSLTExtension):
    1687              def execute(self, context, self_node, input_node, output_parent):
    1688                  self.process_children(context, output_parent)
    1689
    1690          extensions = { ('testns', 'myext') : MyExt() }
    1691
    1692          result = tree.xslt(style, extensions=extensions)
    1693          self.assertEqual(self._rootstring(result),
    1694                            _bytes('<A/>'))
    1695
    1696 -    def test_extension_element_process_children_to_read_only_raise(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/>
    1706      </myns:myext>
    1707    </xsl:template>
    1708  </xsl:stylesheet>''')
    1709
    1710          class MyExt(etree.XSLTExtension):
    1711              def execute(self, context, self_node, input_node, output_parent):
    1712                  self.process_children(context, self_node)
    1713
    1714          extensions = { ('testns', 'myext') : MyExt() }
    1715
    1716          self.assertRaises(TypeError, tree.xslt, style, extensions=extensions)
    1717
    1718 -    def test_extension_element_process_children_with_subextension_element(self):
    1719          tree = self.parse('<a/>')
    1720          style = self.parse('''\
    1721  <xsl:stylesheet version="1.0"
    1722      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1723      xmlns:myns="testns"
    1724      extension-element-prefixes="myns">
    1725    <xsl:template match="a">
    1726      <myns:myext>
    1727        <A><myns:myext><B/></myns:myext></A>
    1728      </myns:myext>
    1729    </xsl:template>
    1730  </xsl:stylesheet>''')
    1731
    1732          class MyExt(etree.XSLTExtension):
    1733              callback_call_counter = 0
    1734              def execute(self, context, self_node, input_node, output_parent):
    1735                  self.callback_call_counter += 1
    1736                  el = etree.Element('MY', n=str(self.callback_call_counter))
    1737                  self.process_children(context, el)
    1738                  output_parent.append(el)
    1739
    1740          extensions = { ('testns', 'myext') : MyExt() }
    1741
    1742          result = tree.xslt(style, extensions=extensions)
    1743          self.assertEqual(self._rootstring(result),
    1744                            _bytes('<MYn="1"><A><MYn="2"><B/></MY></A></MY>'))
    1745
    1746 -    def test_extension_element_raise(self):
    1747          tree = self.parse('<a><b>B</b></a>')
    1748          style = self.parse('''\
    1749  <xsl:stylesheet version="1.0"
    1750      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1751      xmlns:myns="testns"
    1752      extension-element-prefixes="myns"
    1753      exclude-result-prefixes="myns">
    1754    <xsl:template match="a">
    1755      <A><myns:myext>b</myns:myext></A>
    1756    </xsl:template>
    1757  </xsl:stylesheet>''')
    1758
    1759          class MyError(Exception):
    1760              pass
    1761
    1762          class MyExt(etree.XSLTExtension):
    1763              def execute(self, context, self_node, input_node, output_parent):
    1764                  raise MyError("expected!")
    1765
    1766          extensions = { ('testns', 'myext') : MyExt() }
    1767          self.assertRaises(MyError, tree.xslt, style, extensions=extensions)
    1768
    1769
    1770 -class Py3XSLTTestCase(HelperTestCase):
    1771      """XSLT tests for etree under Python 3"""
    1772
    1773      pytestmark = skipif('sys.version_info < (3,0)')
    1774
    1775 -    def test_xslt_result_bytes(self):
    1776          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1777          style = self.parse('''\
    1778  <xsl:stylesheet version="1.0"
    1779      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1780    <xsl:template match="*" />
    1781    <xsl:template match="/">
    1782      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1783    </xsl:template>
    1784  </xsl:stylesheet>''')
    1785
    1786          st = etree.XSLT(style)
    1787          res = st(tree)
    1788          self.assertEqual(_bytes('''\
    1789  <?xml version="1.0"?>
    1790  <foo>B</foo>
    1791  '''),
    1792                            bytes(res))
    1793
    1794 -    def test_xslt_result_bytearray(self):
    1795          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1796          style = self.parse('''\
    1797  <xsl:stylesheet version="1.0"
    1798      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1799    <xsl:template match="*" />
    1800    <xsl:template match="/">
    1801      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1802    </xsl:template>
    1803  </xsl:stylesheet>''')
    1804
    1805          st = etree.XSLT(style)
    1806          res = st(tree)
    1807          self.assertEqual(_bytes('''\
    1808  <?xml version="1.0"?>
    1809  <foo>B</foo>
    1810  '''),
    1811                            bytearray(res))
    1812
    1813 -    def test_xslt_result_memoryview(self):
    1814          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1815          style = self.parse('''\
    1816  <xsl:stylesheet version="1.0"
    1817      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1818    <xsl:template match="*" />
    1819    <xsl:template match="/">
    1820      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1821    </xsl:template>
    1822  </xsl:stylesheet>''')
    1823
    1824          st = etree.XSLT(style)
    1825          res = st(tree)
    1826          self.assertEqual(_bytes('''\
    1827  <?xml version="1.0"?>
    1828  <foo>B</foo>
    1829  '''),
    1830                            bytes(memoryview(res)))
    1831
    1832
    1833 -def test_suite():
    1834      suite = unittest.TestSuite()
    1835      suite.addTests([unittest.makeSuite(ETreeXSLTTestCase)])
    1836      suite.addTests([unittest.makeSuite(ETreeEXSLTTestCase)])
    1837      suite.addTests([unittest.makeSuite(ETreeXSLTExtFuncTestCase)])
    1838      suite.addTests([unittest.makeSuite(ETreeXSLTExtElementTestCase)])
    1839      if is_python3:
    1840          suite.addTests([unittest.makeSuite(Py3XSLTTestCase)])
    1841      suite.addTests(
    1842          [make_doctest('../../../doc/extensions.txt')])
    1843      suite.addTests(
    1844          [make_doctest('../../../doc/xpathxslt.txt')])
    1845      return suite
    1846
    1847  if __name__ == '__main__':
    1848      print('to test use test.py %s' % __file__)
    1849