lxml.tests.test_xslt

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 -    def test_xpath_on_context_node(self):
    1359          tree = self.parse('<a><b>B<c/>C</b><b/></a>')
    1360          style = self.parse('''\
    1361  <xsl:stylesheet version="1.0"
    1362      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1363      xmlns:myns="testns"
    1364      exclude-result-prefixes="myns">
    1365    <xsl:template match="b">
    1366      <A><xsl:value-of select="myns:myext()"/></A>
    1367    </xsl:template>
    1368  </xsl:stylesheet>''')
    1369
    1370          def extfunc(ctxt):
    1371              text_content = ctxt.context_node.xpath('text()')
    1372              return 'x'.join(text_content)
    1373
    1374          namespace = etree.FunctionNamespace('testns')
    1375          namespace['myext'] = extfunc
    1376
    1377          result = tree.xslt(style)
    1378          self.assertEqual(self._rootstring(result),
    1379                           _bytes('<A>BxC</A>'))
    1380
    1381 -    def test_xpath_on_foreign_context_node(self):
    1382          # LP ticket 1354652
    1383          class Resolver(etree.Resolver):
    1384              def resolve(self, system_url, public_id, context):
    1385                  assert system_url == 'extdoc.xml'
    1386                  return self.resolve_string(b'<a><b>B<c/>C</b><b/></a>', context)
    1387
    1388          parser = etree.XMLParser()
    1389          parser.resolvers.add(Resolver())
    1390
    1391          tree = self.parse(b'<a><b/><b/></a>')
    1392          transform = etree.XSLT(self.parse(b'''\
    1393  <xsl:stylesheet version="1.0"
    1394      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1395      xmlns:mypre="testns"
    1396      exclude-result-prefixes="mypre">
    1397    <xsl:template match="b">
    1398      <B><xsl:value-of select="mypre:myext()"/></B>
    1399    </xsl:template>
    1400    <xsl:template match="a">
    1401      <A><xsl:apply-templates select="document('extdoc.xml')//b" /></A>
    1402    </xsl:template>
    1403  </xsl:stylesheet>''', parser=parser))
    1404
    1405          def extfunc(ctxt):
    1406              text_content = ctxt.context_node.xpath('text()')
    1407              return 'x'.join(text_content)
    1408
    1409          namespace = etree.FunctionNamespace('testns')
    1410          namespace['myext'] = extfunc
    1411
    1412          result = transform(tree)
    1413          self.assertEqual(self._rootstring(result),
    1414                           _bytes('<A><B>BxC</B><B/></A>'))
    1415
    1416
    1417 -class ETreeXSLTExtElementTestCase(HelperTestCase):
    1418      """Tests for extension elements in XSLT."""
    1419
    1420 -    def test_extension_element(self):
    1421          tree = self.parse('<a><b>B</b></a>')
    1422          style = self.parse('''\
    1423  <xsl:stylesheet version="1.0"
    1424      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1425      xmlns:myns="testns"
    1426      extension-element-prefixes="myns"
    1427      exclude-result-prefixes="myns">
    1428    <xsl:template match="a">
    1429      <A><myns:myext>b</myns:myext></A>
    1430    </xsl:template>
    1431  </xsl:stylesheet>''')
    1432
    1433          class MyExt(etree.XSLTExtension):
    1434              def execute(self, context, self_node, input_node, output_parent):
    1435                  child = etree.Element(self_node.text)
    1436                  child.text = 'X'
    1437                  output_parent.append(child)
    1438
    1439          extensions = { ('testns', 'myext') : MyExt() }
    1440
    1441          result = tree.xslt(style, extensions=extensions)
    1442          self.assertEqual(self._rootstring(result),
    1443                            _bytes('<A><b>X</b></A>'))
    1444
    1445 -    def test_extension_element_doc_context(self):
    1446          tree = self.parse('<a><b>B</b></a>')
    1447          style = self.parse('''\
    1448  <xsl:stylesheet version="1.0"
    1449      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1450      xmlns:myns="testns"
    1451      extension-element-prefixes="myns"
    1452      exclude-result-prefixes="myns">
    1453    <xsl:template match="/">
    1454      <A><myns:myext>b</myns:myext></A>
    1455    </xsl:template>
    1456  </xsl:stylesheet>''')
    1457
    1458          tags = []
    1459
    1460          class MyExt(etree.XSLTExtension):
    1461              def execute(self, context, self_node, input_node, output_parent):
    1462                  tags.append(input_node.tag)
    1463
    1464          extensions = { ('testns', 'myext') : MyExt() }
    1465
    1466          result = tree.xslt(style, extensions=extensions)
    1467          self.assertEqual(tags, ['a'])
    1468
    1469 -    def test_extension_element_comment_pi_context(self):
    1470          tree = self.parse('<?test toast?><a><!--a comment--><?another pi?></a>')
    1471          style = self.parse('''\
    1472  <xsl:stylesheet version="1.0"
    1473      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1474      xmlns:myns="testns"
    1475      extension-element-prefixes="myns"
    1476      exclude-result-prefixes="myns">
    1477    <xsl:template match="/">
    1478      <ROOT><xsl:apply-templates /></ROOT>
    1479    </xsl:template>
    1480    <xsl:template match="comment()">
    1481      <A><myns:myext>b</myns:myext></A>
    1482    </xsl:template>
    1483    <xsl:template match="processing-instruction()">
    1484      <A><myns:myext>b</myns:myext></A>
    1485    </xsl:template>
    1486  </xsl:stylesheet>''')
    1487
    1488          text = []
    1489
    1490          class MyExt(etree.XSLTExtension):
    1491              def execute(self, context, self_node, input_node, output_parent):
    1492                  text.append(input_node.text)
    1493
    1494          extensions = { ('testns', 'myext') : MyExt() }
    1495
    1496          result = tree.xslt(style, extensions=extensions)
    1497          self.assertEqual(text, ['toast', 'a comment', 'pi'])
    1498
    1499 -    def _test_extension_element_attribute_context(self):
    1500          # currently not supported
    1501          tree = self.parse('<a test="A"><b attr="B"/></a>')
    1502          style = self.parse('''\
    1503  <xsl:stylesheet version="1.0"
    1504      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1505      xmlns:myns="testns"
    1506      extension-element-prefixes="myns"
    1507      exclude-result-prefixes="myns">
    1508    <xsl:template match="@test">
    1509      <A><myns:myext>b</myns:myext></A>
    1510    </xsl:template>
    1511    <xsl:template match="@attr">
    1512      <A><myns:myext>b</myns:myext></A>
    1513    </xsl:template>
    1514  </xsl:stylesheet>''')
    1515
    1516          text = []
    1517
    1518          class MyExt(etree.XSLTExtension):
    1519              def execute(self, context, self_node, attr_value, output_parent):
    1520                  text.append(attr_value)
    1521
    1522          extensions = { ('testns', 'myext') : MyExt() }
    1523
    1524          result = tree.xslt(style, extensions=extensions)
    1525          self.assertEqual(text, ['A', 'B'])
    1526
    1527 -    def test_extension_element_content(self):
    1528          tree = self.parse('<a><b>B</b></a>')
    1529          style = self.parse('''\
    1530  <xsl:stylesheet version="1.0"
    1531      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1532      xmlns:myns="testns"
    1533      extension-element-prefixes="myns">
    1534    <xsl:template match="a">
    1535      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1536    </xsl:template>
    1537  </xsl:stylesheet>''')
    1538
    1539          class MyExt(etree.XSLTExtension):
    1540              def execute(self, context, self_node, input_node, output_parent):
    1541                  output_parent.extend(list(self_node)[1:])
    1542
    1543          extensions = { ('testns', 'myext') : MyExt() }
    1544
    1545          result = tree.xslt(style, extensions=extensions)
    1546          self.assertEqual(self._rootstring(result),
    1547                            _bytes('<A><y>Y</y><z/></A>'))
    1548
    1549 -    def test_extension_element_apply_templates(self):
    1550          tree = self.parse('<a><b>B</b></a>')
    1551          style = self.parse('''\
    1552  <xsl:stylesheet version="1.0"
    1553      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1554      xmlns:myns="testns"
    1555      extension-element-prefixes="myns">
    1556    <xsl:template match="a">
    1557      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1558    </xsl:template>
    1559    <xsl:template match="x" />
    1560    <xsl:template match="z">XYZ</xsl:template>
    1561  </xsl:stylesheet>''')
    1562
    1563          class MyExt(etree.XSLTExtension):
    1564              def execute(self, context, self_node, input_node, output_parent):
    1565                  for child in self_node:
    1566                      for result in self.apply_templates(context, child):
    1567                          if isinstance(result, basestring):
    1568                              el = etree.Element("T")
    1569                              el.text = result
    1570                          else:
    1571                              el = result
    1572                          output_parent.append(el)
    1573
    1574          extensions = { ('testns', 'myext') : MyExt() }
    1575
    1576          result = tree.xslt(style, extensions=extensions)
    1577          self.assertEqual(self._rootstring(result),
    1578                            _bytes('<A><T>Y</T><T>XYZ</T></A>'))
    1579
    1580 -    def test_extension_element_apply_templates_elements_only(self):
    1581          tree = self.parse('<a><b>B</b></a>')
    1582          style = self.parse('''\
    1583  <xsl:stylesheet version="1.0"
    1584      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1585      xmlns:myns="testns"
    1586      extension-element-prefixes="myns">
    1587    <xsl:template match="a">
    1588      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1589    </xsl:template>
    1590    <xsl:template match="x"><X/></xsl:template>
    1591    <xsl:template match="z">XYZ</xsl:template>
    1592  </xsl:stylesheet>''')
    1593
    1594          class MyExt(etree.XSLTExtension):
    1595              def execute(self, context, self_node, input_node, output_parent):
    1596                  for child in self_node:
    1597                      for result in self.apply_templates(context, child,
    1598                                                         elements_only=True):
    1599                          assert not isinstance(result, basestring)
    1600                          output_parent.append(result)
    1601
    1602          extensions = { ('testns', 'myext') : MyExt() }
    1603
    1604          result = tree.xslt(style, extensions=extensions)
    1605          self.assertEqual(self._rootstring(result),
    1606                            _bytes('<A><X/></A>'))
    1607
    1608 -    def test_extension_element_apply_templates_remove_blank_text(self):
    1609          tree = self.parse('<a><b>B</b></a>')
    1610          style = self.parse('''\
    1611  <xsl:stylesheet version="1.0"
    1612      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1613      xmlns:myns="testns"
    1614      extension-element-prefixes="myns">
    1615    <xsl:template match="a">
    1616      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1617    </xsl:template>
    1618    <xsl:template match="x"><X/></xsl:template>
    1619    <xsl:template match="y"><xsl:text>   </xsl:text></xsl:template>
    1620    <xsl:template match="z">XYZ</xsl:template>
    1621  </xsl:stylesheet>''')
    1622
    1623          class MyExt(etree.XSLTExtension):
    1624              def execute(self, context, self_node, input_node, output_parent):
    1625                  for child in self_node:
    1626                      for result in self.apply_templates(context, child,
    1627                                                         remove_blank_text=True):
    1628                          if isinstance(result, basestring):
    1629                              assert result.strip()
    1630                              el = etree.Element("T")
    1631                              el.text = result
    1632                          else:
    1633                              el = result
    1634                          output_parent.append(el)
    1635
    1636          extensions = { ('testns', 'myext') : MyExt() }
    1637
    1638          result = tree.xslt(style, extensions=extensions)
    1639          self.assertEqual(self._rootstring(result),
    1640                            _bytes('<A><X/><T>XYZ</T></A>'))
    1641
    1642 -    def test_extension_element_apply_templates_target_node(self):
    1643          tree = self.parse('<a><b>B</b></a>')
    1644          style = self.parse('''\
    1645  <xsl:stylesheet version="1.0"
    1646      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1647      xmlns:myns="testns"
    1648      extension-element-prefixes="myns">
    1649    <xsl:template match="a">
    1650      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
    1651    </xsl:template>
    1652    <xsl:template match="x" />
    1653    <xsl:template match="z">XYZ</xsl:template>
    1654  </xsl:stylesheet>''')
    1655
    1656          class MyExt(etree.XSLTExtension):
    1657              def execute(self, context, self_node, input_node, output_parent):
    1658                  for child in self_node:
    1659                      self.apply_templates(context, child, output_parent)
    1660
    1661          extensions = { ('testns', 'myext') : MyExt() }
    1662
    1663          result = tree.xslt(style, extensions=extensions)
    1664          self.assertEqual(self._rootstring(result),
    1665                            _bytes('<A>YXYZ</A>'))
    1666
    1667 -    def test_extension_element_apply_templates_target_node_doc(self):
    1668          tree = self.parse('<a><b>B</b></a>')
    1669          style = self.parse('''\
    1670  <xsl:stylesheet version="1.0"
    1671      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1672      xmlns:myns="testns"
    1673      extension-element-prefixes="myns">
    1674    <xsl:template match="a">
    1675      <myns:myext><x>X</x><y>Y</y><z/></myns:myext>
    1676    </xsl:template>
    1677    <xsl:template match="x"><xsl:processing-instruction name="test">TEST</xsl:processing-instruction></xsl:template>
    1678    <xsl:template match="y"><Y>XYZ</Y></xsl:template>
    1679    <xsl:template match="z"><xsl:comment>TEST</xsl:comment></xsl:template>
    1680  </xsl:stylesheet>''')
    1681
    1682          class MyExt(etree.XSLTExtension):
    1683              def execute(self, context, self_node, input_node, output_parent):
    1684                  for child in self_node:
    1685                      self.apply_templates(context, child, output_parent)
    1686
    1687          extensions = { ('testns', 'myext') : MyExt() }
    1688
    1689          result = tree.xslt(style, extensions=extensions)
    1690          self.assertEqual(etree.tostring(result),
    1691                            _bytes('<?test TEST?><Y>XYZ</Y><!--TEST-->'))
    1692
    1693 -    def test_extension_element_process_children(self):
    1694          tree = self.parse('<a><b>E</b></a>')
    1695          style = self.parse('''\
    1696  <xsl:stylesheet version="1.0"
    1697      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1698      xmlns:myns="testns"
    1699      extension-element-prefixes="myns">
    1700    <xsl:template match="a">
    1701      <xsl:variable name="testvar">yo</xsl:variable>
    1702      <A>
    1703        <myns:myext>
    1704          <xsl:attribute name="attr">
    1705            <xsl:value-of select="$testvar" />
    1706          </xsl:attribute>
    1707          <B>
    1708            <xsl:choose>
    1709              <xsl:when test="1 = 2"><C/></xsl:when>
    1710              <xsl:otherwise><D><xsl:value-of select="b/text()" /></D></xsl:otherwise>
    1711            </xsl:choose>
    1712          </B>
    1713        </myns:myext>
    1714      </A>
    1715    </xsl:template>
    1716  </xsl:stylesheet>''')
    1717
    1718          class MyExt(etree.XSLTExtension):
    1719              def execute(self, context, self_node, input_node, output_parent):
    1720                  el = etree.Element('MY')
    1721                  self.process_children(context, el)
    1722                  output_parent.append(el)
    1723
    1724          extensions = { ('testns', 'myext') : MyExt() }
    1725
    1726          result = tree.xslt(style, extensions=extensions)
    1727          self.assertEqual(self._rootstring(result),
    1728                            _bytes('<A><MYattr="yo"><B><D>E</D></B></MY></A>'))
    1729
    1730 -    def test_extension_element_process_children_to_append_only(self):
    1731          tree = self.parse('<a/>')
    1732          style = self.parse('''\
    1733  <xsl:stylesheet version="1.0"
    1734      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1735      xmlns:myns="testns"
    1736      extension-element-prefixes="myns">
    1737    <xsl:template match="a">
    1738      <myns:myext>
    1739        <A/>
    1740      </myns:myext>
    1741    </xsl:template>
    1742  </xsl:stylesheet>''')
    1743
    1744          class MyExt(etree.XSLTExtension):
    1745              def execute(self, context, self_node, input_node, output_parent):
    1746                  self.process_children(context, output_parent)
    1747
    1748          extensions = { ('testns', 'myext') : MyExt() }
    1749
    1750          result = tree.xslt(style, extensions=extensions)
    1751          self.assertEqual(self._rootstring(result),
    1752                            _bytes('<A/>'))
    1753
    1754 -    def test_extension_element_process_children_to_read_only_raise(self):
    1755          tree = self.parse('<a/>')
    1756          style = self.parse('''\
    1757  <xsl:stylesheet version="1.0"
    1758      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1759      xmlns:myns="testns"
    1760      extension-element-prefixes="myns">
    1761    <xsl:template match="a">
    1762      <myns:myext>
    1763        <A/>
    1764      </myns:myext>
    1765    </xsl:template>
    1766  </xsl:stylesheet>''')
    1767
    1768          class MyExt(etree.XSLTExtension):
    1769              def execute(self, context, self_node, input_node, output_parent):
    1770                  self.process_children(context, self_node)
    1771
    1772          extensions = { ('testns', 'myext') : MyExt() }
    1773
    1774          self.assertRaises(TypeError, tree.xslt, style, extensions=extensions)
    1775
    1776 -    def test_extension_element_process_children_with_subextension_element(self):
    1777          tree = self.parse('<a/>')
    1778          style = self.parse('''\
    1779  <xsl:stylesheet version="1.0"
    1780      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1781      xmlns:myns="testns"
    1782      extension-element-prefixes="myns">
    1783    <xsl:template match="a">
    1784      <myns:myext>
    1785        <A><myns:myext><B/></myns:myext></A>
    1786      </myns:myext>
    1787    </xsl:template>
    1788  </xsl:stylesheet>''')
    1789
    1790          class MyExt(etree.XSLTExtension):
    1791              callback_call_counter = 0
    1792              def execute(self, context, self_node, input_node, output_parent):
    1793                  self.callback_call_counter += 1
    1794                  el = etree.Element('MY', n=str(self.callback_call_counter))
    1795                  self.process_children(context, el)
    1796                  output_parent.append(el)
    1797
    1798          extensions = { ('testns', 'myext') : MyExt() }
    1799
    1800          result = tree.xslt(style, extensions=extensions)
    1801          self.assertEqual(self._rootstring(result),
    1802                            _bytes('<MYn="1"><A><MYn="2"><B/></MY></A></MY>'))
    1803
    1804 -    def test_extension_element_raise(self):
    1805          tree = self.parse('<a><b>B</b></a>')
    1806          style = self.parse('''\
    1807  <xsl:stylesheet version="1.0"
    1808      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    1809      xmlns:myns="testns"
    1810      extension-element-prefixes="myns"
    1811      exclude-result-prefixes="myns">
    1812    <xsl:template match="a">
    1813      <A><myns:myext>b</myns:myext></A>
    1814    </xsl:template>
    1815  </xsl:stylesheet>''')
    1816
    1817          class MyError(Exception):
    1818              pass
    1819
    1820          class MyExt(etree.XSLTExtension):
    1821              def execute(self, context, self_node, input_node, output_parent):
    1822                  raise MyError("expected!")
    1823
    1824          extensions = { ('testns', 'myext') : MyExt() }
    1825          self.assertRaises(MyError, tree.xslt, style, extensions=extensions)
    1826
    1827      # FIXME: DISABLED - implementation seems to be broken
    1828      # if someone cares enough about this feature, I take pull requests that fix it.
    1829 -    def _test_multiple_extension_elements_with_output_parent(self):
    1830          tree = self.parse("""\
    1831  <text>
    1832    <par>This is <format>arbitrary</format> text in a paragraph</par>
    1833  </text>""")
    1834          style = self.parse("""\
    1835  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="my" extension-element-prefixes="my" version="1.0">
    1836    <xsl:template match="par">
    1837      <my:par><xsl:apply-templates /></my:par>
    1838    </xsl:template>
    1839    <xsl:template match="format">
    1840      <my:format><xsl:apply-templates /></my:format>
    1841    </xsl:template>
    1842  </xsl:stylesheet>
    1843  """)
    1844          test = self
    1845          calls = []
    1846
    1847          class ExtMyPar(etree.XSLTExtension):
    1848              def execute(self, context, self_node, input_node, output_parent):
    1849                  calls.append('par')
    1850                  p = etree.Element("p")
    1851                  p.attrib["style"] = "color:red"
    1852                  self.process_children(context, p)
    1853                  output_parent.append(p)
    1854
    1855          class ExtMyFormat(etree.XSLTExtension):
    1856              def execute(self, context, self_node, input_node, output_parent):
    1857                  calls.append('format')
    1858                  content = self.process_children(context)
    1859                  test.assertEqual(1, len(content))
    1860                  test.assertEqual('arbitrary', content[0])
    1861                  test.assertEqual('This is ', output_parent.text)
    1862                  output_parent.text += '*-%s-*' % content[0]
    1863
    1864          extensions = {("my", "par"): ExtMyPar(), ("my", "format"): ExtMyFormat()}
    1865          transform = etree.XSLT(style, extensions=extensions)
    1866          result = transform(tree)
    1867          self.assertEqual(['par', 'format'], calls)
    1868          self.assertEqual(
    1869              b'<p style="color:red">This is *-arbitrary-* text in a paragraph</p>\n',
    1870              etree.tostring(result))
    1871
    1872
    1873 -class Py3XSLTTestCase(HelperTestCase):
    1874      """XSLT tests for etree under Python 3"""
    1875
    1876      pytestmark = skipif('sys.version_info < (3,0)')
    1877
    1878 -    def test_xslt_result_bytes(self):
    1879          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1880          style = self.parse('''\
    1881  <xsl:stylesheet version="1.0"
    1882      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1883    <xsl:template match="*" />
    1884    <xsl:template match="/">
    1885      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1886    </xsl:template>
    1887  </xsl:stylesheet>''')
    1888
    1889          st = etree.XSLT(style)
    1890          res = st(tree)
    1891          self.assertEqual(_bytes('''\
    1892  <?xml version="1.0"?>
    1893  <foo>B</foo>
    1894  '''),
    1895                            bytes(res))
    1896
    1897 -    def test_xslt_result_bytearray(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                            bytearray(res))
    1915
    1916 -    def test_xslt_result_memoryview(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                            bytes(memoryview(res)))
    1934
    1935
    1936 -def test_suite():
    1937      suite = unittest.TestSuite()
    1938      suite.addTests([unittest.makeSuite(ETreeXSLTTestCase)])
    1939      suite.addTests([unittest.makeSuite(ETreeEXSLTTestCase)])
    1940      suite.addTests([unittest.makeSuite(ETreeXSLTExtFuncTestCase)])
    1941      suite.addTests([unittest.makeSuite(ETreeXSLTExtElementTestCase)])
    1942      if is_python3:
    1943          suite.addTests([unittest.makeSuite(Py3XSLTTestCase)])
    1944      suite.addTests(
    1945          [make_doctest('../../../doc/extensions.txt')])
    1946      suite.addTests(
    1947          [make_doctest('../../../doc/xpathxslt.txt')])
    1948      return suite
    1949
    1950  if __name__ == '__main__':
    1951      print('to test use test.py %s' % __file__)
    1952