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