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 = __builtins__["unicode"]
      17  except (NameError, KeyError): # Python 3
      18      unicode = str
      19
      20  try:
      21      basestring = __builtins__["basestring"]
      22  except (NameError, KeyError): # 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
      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.assertEquals('''\
      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.assertEquals('''\
      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.assertEquals('''\
      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.assertEquals('''\
      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.assertEquals(expected,
     124                                str(bytes(res), 'UTF-8'))
     125          else:
     126              self.assertEquals(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.assertEquals(expected,
     149                                str(bytes(res), 'UTF-16'))
     150          else:
     151              self.assertEquals(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.assertEquals(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.assertEquals(expected,
     199                            unicode(res))
     200
     201 -    def test_exslt_str(self):
     202          tree = self.parse('<a><b>B</b><c>C</c></a>')
     203          style = self.parse('''\
     204  <xsl:stylesheet version="1.0"
     205      xmlns:str="http://exslt.org/strings"
     206      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     207      exclude-result-prefixes="str xsl">
     208    <xsl:template match="text()">
     209      <xsl:value-of select="str:align(string(.), '***', 'center')" />
     210    </xsl:template>
     211    <xsl:template match="*">
     212      <xsl:copy>
     213        <xsl:apply-templates/>
     214      </xsl:copy>
     215    </xsl:template>
     216  </xsl:stylesheet>''')
     217
     218          st = etree.XSLT(style)
     219          res = st(tree)
     220          self.assertEquals('''\
     221  <?xml version="1.0"?>
     222  <a><b>*B*</b><c>*C*</c></a>
     223  ''',
     224                            str(res))
     225
     226      if etree.LIBXSLT_VERSION >= (1,1,21):
     227 -        def test_exslt_str_attribute_replace(self):
     228              tree = self.parse('<a><b>B</b><c>C</c></a>')
     229              style = self.parse('''\
     230        <xsl:stylesheet version = "1.0"
     231            xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
     232            xmlns:str="http://exslt.org/strings"
     233            extension-element-prefixes="str">
     234
     235            <xsl:template match="/">
     236              <h1 class="{str:replace('abc', 'b', 'x')}">test</h1>
     237            </xsl:template>
     238
     239        </xsl:stylesheet>''')
     240
     241              st = etree.XSLT(style)
     242              res = st(tree)
     243              self.assertEquals('''\
     244  <?xml version="1.0"?>
     245  <h1 class="axc">test</h1>
     246  ''',
     247                                str(res))
     248
     249 -    def test_exslt_math(self):
     250          tree = self.parse('<a><b>B</b><c>C</c></a>')
     251          style = self.parse('''\
     252  <xsl:stylesheet version="1.0"
     253      xmlns:math="http://exslt.org/math"
     254      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     255      exclude-result-prefixes="math xsl">
     256    <xsl:template match="*">
     257      <xsl:copy>
     258        <xsl:attribute name="pi">
     259          <xsl:value-of select="math:constant('PI', count(*)+2)"/>
     260        </xsl:attribute>
     261        <xsl:apply-templates/>
     262      </xsl:copy>
     263    </xsl:template>
     264  </xsl:stylesheet>''')
     265
     266          st = etree.XSLT(style)
     267          res = st(tree)
     268          self.assertEquals('''\
     269  <?xml version="1.0"?>
     270  <a pi="3.14"><b pi="3">B</b><c pi="3">C</c></a>
     271  ''',
     272                            str(res))
     273
     274 -    def test_xslt_input(self):
     275          style = self.parse('''\
     276  <xsl:stylesheet version="1.0"
     277      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     278    <xsl:template match="*" />
     279    <xsl:template match="/">
     280      <foo><xsl:value-of select="/a/b/text()" /></foo>
     281    </xsl:template>
     282  </xsl:stylesheet>''')
     283
     284          st = etree.XSLT(style)
     285          st = etree.XSLT(style.getroot())
     286
     287 -    def test_xslt_input_partial_doc(self):
     288          style = self.parse('''\
     289  <otherroot>
     290  <xsl:stylesheet version="1.0"
     291      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     292    <xsl:template match="*" />
     293    <xsl:template match="/">
     294      <foo><xsl:value-of select="/a/b/text()" /></foo>
     295    </xsl:template>
     296  </xsl:stylesheet>
     297  </otherroot>''')
     298
     299          self.assertRaises(etree.XSLTParseError, etree.XSLT, style)
     300          root_node = style.getroot()
     301          self.assertRaises(etree.XSLTParseError, etree.XSLT, root_node)
     302          st = etree.XSLT(root_node[0])
     303
     304 -    def test_xslt_broken(self):
     305          tree = self.parse('<a/>')
     306          style = self.parse('''\
     307  <xsl:stylesheet version="1.0"
     308      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     309      <xsl:foo />
     310  </xsl:stylesheet>''')
     311          self.assertRaises(etree.XSLTParseError,
     312                            etree.XSLT, style)
     313
     314 -    def test_xslt_parameters(self):
     315          tree = self.parse('<a><b>B</b><c>C</c></a>')
     316          style = self.parse('''\
     317  <xsl:stylesheet version="1.0"
     318      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     319    <xsl:template match="/">
     320      <foo><xsl:value-of select="$bar" /></foo>
     321    </xsl:template>
     322  </xsl:stylesheet>''')
     323
     324          st = etree.XSLT(style)
     325          res = st(tree, bar="'Bar'")
     326          self.assertEquals('''\
     327  <?xml version="1.0"?>
     328  <foo>Bar</foo>
     329  ''',
     330                            str(res))
     331
     332 -    def test_xslt_parameter_invalid(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:param name="bar"/>
     338    <xsl:template match="/">
     339      <foo><xsl:value-of select="$bar" /></foo>
     340    </xsl:template>
     341  </xsl:stylesheet>''')
     342
     343          st = etree.XSLT(style)
     344          res = self.assertRaises(etree.XSLTApplyError,
     345                                  st, tree, bar="<test/>")
     346          res = self.assertRaises(etree.XSLTApplyError,
     347                                  st, tree, bar="....")
     348
     349      if etree.LIBXSLT_VERSION < (1,1,18):
     350          # later versions produce no error
     351 -        def test_xslt_parameter_missing(self):
     352              # apply() without needed parameter will lead to XSLTApplyError
     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      <foo><xsl:value-of select="$bar" /></foo>
     359    </xsl:template>
     360  </xsl:stylesheet>''')
     361
     362              st = etree.XSLT(style)
     363              self.assertRaises(etree.XSLTApplyError,
     364                                st.apply, tree)
     365
     366 -    def test_xslt_multiple_parameters(self):
     367          tree = self.parse('<a><b>B</b><c>C</c></a>')
     368          style = self.parse('''\
     369  <xsl:stylesheet version="1.0"
     370      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     371    <xsl:template match="*" />
     372    <xsl:template match="/">
     373      <foo><xsl:value-of select="$bar" /></foo>
     374      <foo><xsl:value-of select="$baz" /></foo>
     375    </xsl:template>
     376  </xsl:stylesheet>''')
     377
     378          st = etree.XSLT(style)
     379          res = st(tree, bar="'Bar'", baz="'Baz'")
     380          self.assertEquals('''\
     381  <?xml version="1.0"?>
     382  <foo>Bar</foo><foo>Baz</foo>
     383  ''',
     384                            str(res))
     385
     386 -    def test_xslt_parameter_xpath(self):
     387          tree = self.parse('<a><b>B</b><c>C</c></a>')
     388          style = self.parse('''\
     389  <xsl:stylesheet version="1.0"
     390      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     391    <xsl:template match="*" />
     392    <xsl:template match="/">
     393      <foo><xsl:value-of select="$bar" /></foo>
     394    </xsl:template>
     395  </xsl:stylesheet>''')
     396
     397          st = etree.XSLT(style)
     398          res = st(tree, bar="/a/b/text()")
     399          self.assertEquals('''\
     400  <?xml version="1.0"?>
     401  <foo>B</foo>
     402  ''',
     403                            str(res))
     404
     405
     406 -    def test_xslt_default_parameters(self):
     407          tree = self.parse('<a><b>B</b><c>C</c></a>')
     408          style = self.parse('''\
     409  <xsl:stylesheet version="1.0"
     410      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     411    <xsl:param name="bar" select="'Default'" />
     412    <xsl:template match="*" />
     413    <xsl:template match="/">
     414      <foo><xsl:value-of select="$bar" /></foo>
     415    </xsl:template>
     416  </xsl:stylesheet>''')
     417
     418          st = etree.XSLT(style)
     419          res = st(tree, bar="'Bar'")
     420          self.assertEquals('''\
     421  <?xml version="1.0"?>
     422  <foo>Bar</foo>
     423  ''',
     424                            str(res))
     425          res = st(tree)
     426          self.assertEquals('''\
     427  <?xml version="1.0"?>
     428  <foo>Default</foo>
     429  ''',
     430                            str(res))
     431
     432 -    def test_xslt_html_output(self):
     433          tree = self.parse('<a><b>B</b><c>C</c></a>')
     434          style = self.parse('''\
     435  <xsl:stylesheet version="1.0"
     436      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     437    <xsl:output method="html"/>
     438    <xsl:strip-space elements="*"/>
     439    <xsl:template match="/">
     440      <html><body><xsl:value-of select="/a/b/text()" /></body></html>
     441    </xsl:template>
     442  </xsl:stylesheet>''')
     443
     444          st = etree.XSLT(style)
     445          res = st(tree)
     446          self.assertEquals('<html><body>B</body></html>',
     447                            str(res).strip())
     448
     449 -    def test_xslt_include(self):
     450          tree = etree.parse(fileInTestDir('test1.xslt'))
     451          st = etree.XSLT(tree)
     452
     453 -    def test_xslt_include_from_filelike(self):
     454          f = open(fileInTestDir('test1.xslt'), 'rb')
     455          tree = etree.parse(f)
     456          f.close()
     457          st = etree.XSLT(tree)
     458
     459 -    def test_xslt_multiple_transforms(self):
     460          xml = '<a/>'
     461          xslt = '''\
     462  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     463      <xsl:template match="/">
     464          <response>Some text</response>
     465      </xsl:template>
     466  </xsl:stylesheet>
     467  '''
     468          source = self.parse(xml)
     469          styledoc = self.parse(xslt)
     470          style = etree.XSLT(styledoc)
     471          result = style(source)
     472
     473          etree.tostring(result.getroot())
     474
     475          source = self.parse(xml)
     476          styledoc = self.parse(xslt)
     477          style = etree.XSLT(styledoc)
     478          result = style(source)
     479
     480          etree.tostring(result.getroot())
     481
     482 -    def test_xslt_repeat_transform(self):
     483          xml = '<a/>'
     484          xslt = '''\
     485  <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     486      <xsl:template match="/">
     487          <response>Some text</response>
     488      </xsl:template>
     489  </xsl:stylesheet>
     490  '''
     491          source = self.parse(xml)
     492          styledoc = self.parse(xslt)
     493          transform = etree.XSLT(styledoc)
     494          result = transform(source)
     495          result = transform(source)
     496          etree.tostring(result.getroot())
     497          result = transform(source)
     498          etree.tostring(result.getroot())
     499          str(result)
     500
     501          result1 = transform(source)
     502          result2 = transform(source)
     503          self.assertEquals(str(result1), str(result2))
     504          result = transform(source)
     505          str(result)
     506
     507 -    def test_xslt_empty(self):
     508          # could segfault if result contains "empty document"
     509          xml = '<blah/>'
     510          xslt = '''
     511          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     512            <xsl:template match="/" />
     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
     522 -    def test_xslt_message(self):
     523          xml = '<blah/>'
     524          xslt = '''
     525          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     526            <xsl:template match="/">
     527              <xsl:message>TEST TEST TEST</xsl:message>
     528            </xsl:template>
     529          </xsl:stylesheet>
     530          '''
     531
     532          source = self.parse(xml)
     533          styledoc = self.parse(xslt)
     534          style = etree.XSLT(styledoc)
     535          result = style(source)
     536          self.assertEqual('', str(result))
     537          self.assert_("TEST TEST TEST" in [entry.message
     538                                            for entry in style.error_log])
     539
     540 -    def test_xslt_message_terminate(self):
     541          xml = '<blah/>'
     542          xslt = '''
     543          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
     544            <xsl:template match="/">
     545              <xsl:message terminate="yes">TEST TEST TEST</xsl:message>
     546            </xsl:template>
     547          </xsl:stylesheet>
     548          '''
     549
     550          source = self.parse(xml)
     551          styledoc = self.parse(xslt)
     552          style = etree.XSLT(styledoc)
     553
     554          self.assertRaises(etree.XSLTApplyError, style, source)
     555          self.assert_("TEST TEST TEST" in [entry.message
     556                                            for entry in style.error_log])
     557
     558 -    def test_xslt_shortcut(self):
     559          tree = self.parse('<a><b>B</b><c>C</c></a>')
     560          style = self.parse('''\
     561  <xsl:stylesheet version="1.0"
     562      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     563    <xsl:template match="*" />
     564    <xsl:template match="/">
     565      <doc>
     566      <foo><xsl:value-of select="$bar" /></foo>
     567      <foo><xsl:value-of select="$baz" /></foo>
     568      </doc>
     569    </xsl:template>
     570  </xsl:stylesheet>''')
     571
     572          result = tree.xslt(style, bar="'Bar'", baz="'Baz'")
     573          self.assertEquals(
     574              _bytes('<doc><foo>Bar</foo><foo>Baz</foo></doc>'),
     575              etree.tostring(result.getroot()))
     576
     577 -    def test_multiple_elementrees(self):
     578          tree = self.parse('<a><b>B</b><c>C</c></a>')
     579          style = self.parse('''\
     580  <xsl:stylesheet version="1.0"
     581      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     582    <xsl:template match="a"><A><xsl:apply-templates/></A></xsl:template>
     583    <xsl:template match="b"><B><xsl:apply-templates/></B></xsl:template>
     584    <xsl:template match="c"><C><xsl:apply-templates/></C></xsl:template>
     585  </xsl:stylesheet>''')
     586
     587          self.assertEquals(self._rootstring(tree),
     588                            _bytes('<a><b>B</b><c>C</c></a>'))
     589          result = tree.xslt(style)
     590          self.assertEquals(self._rootstring(tree),
     591                            _bytes('<a><b>B</b><c>C</c></a>'))
     592          self.assertEquals(self._rootstring(result),
     593                            _bytes('<A><B>B</B><C>C</C></A>'))
     594
     595          b_tree = etree.ElementTree(tree.getroot()[0])
     596          self.assertEquals(self._rootstring(b_tree),
     597                            _bytes('<b>B</b>'))
     598          result = b_tree.xslt(style)
     599          self.assertEquals(self._rootstring(tree),
     600                            _bytes('<a><b>B</b><c>C</c></a>'))
     601          self.assertEquals(self._rootstring(result),
     602                            _bytes('<B>B</B>'))
     603
     604          c_tree = etree.ElementTree(tree.getroot()[1])
     605          self.assertEquals(self._rootstring(c_tree),
     606                            _bytes('<c>C</c>'))
     607          result = c_tree.xslt(style)
     608          self.assertEquals(self._rootstring(tree),
     609                            _bytes('<a><b>B</b><c>C</c></a>'))
     610          self.assertEquals(self._rootstring(result),
     611                            _bytes('<C>C</C>'))
     612
     613 -    def test_extensions1(self):
     614          tree = self.parse('<a><b>B</b></a>')
     615          style = self.parse('''\
     616  <xsl:stylesheet version="1.0"
     617      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     618      xmlns:myns="testns"
     619      exclude-result-prefixes="myns">
     620    <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
     621  </xsl:stylesheet>''')
     622
     623          def mytext(ctxt, values):
     624              return 'X' * len(values)
     625
     626          result = tree.xslt(style, {('testns', 'mytext') : mytext})
     627          self.assertEquals(self._rootstring(result),
     628                            _bytes('<A>X</A>'))
     629
     630 -    def test_extensions2(self):
     631          tree = self.parse('<a><b>B</b></a>')
     632          style = self.parse('''\
     633  <xsl:stylesheet version="1.0"
     634      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     635      xmlns:myns="testns"
     636      exclude-result-prefixes="myns">
     637    <xsl:template match="a"><A><xsl:value-of select="myns:mytext(b)"/></A></xsl:template>
     638  </xsl:stylesheet>''')
     639
     640          def mytext(ctxt, values):
     641              return 'X' * len(values)
     642
     643          namespace = etree.FunctionNamespace('testns')
     644          namespace['mytext'] = mytext
     645
     646          result = tree.xslt(style)
     647          self.assertEquals(self._rootstring(result),
     648                            _bytes('<A>X</A>'))
     649
     650 -    def test_variable_result_tree_fragment(self):
     651          tree = self.parse('<a><b>B</b><b/></a>')
     652          style = self.parse('''\
     653  <xsl:stylesheet version="1.0"
     654      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     655      xmlns:myns="testns"
     656      exclude-result-prefixes="myns">
     657    <xsl:template match="a">
     658      <xsl:variable name="content">
     659         <xsl:apply-templates/>
     660      </xsl:variable>
     661      <A><xsl:value-of select="myns:mytext($content)"/></A>
     662    </xsl:template>
     663    <xsl:template match="b"><xsl:copy>BBB</xsl:copy></xsl:template>
     664  </xsl:stylesheet>''')
     665
     666          def mytext(ctxt, values):
     667              for value in values:
     668                  self.assert_(hasattr(value, 'tag'),
     669                               "%s is not an Element" % type(value))
     670                  self.assertEquals(value.tag, 'b')
     671                  self.assertEquals(value.text, 'BBB')
     672              return 'X'.join([el.tag for el in values])
     673
     674          namespace = etree.FunctionNamespace('testns')
     675          namespace['mytext'] = mytext
     676
     677          result = tree.xslt(style)
     678          self.assertEquals(self._rootstring(result),
     679                            _bytes('<A>bXb</A>'))
     680
     681 -    def test_extension_element(self):
     682          tree = self.parse('<a><b>B</b></a>')
     683          style = self.parse('''\
     684  <xsl:stylesheet version="1.0"
     685      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     686      xmlns:myns="testns"
     687      extension-element-prefixes="myns"
     688      exclude-result-prefixes="myns">
     689    <xsl:template match="a">
     690      <A><myns:myext>b</myns:myext></A>
     691    </xsl:template>
     692  </xsl:stylesheet>''')
     693
     694          class MyExt(etree.XSLTExtension):
     695              def execute(self, context, self_node, input_node, output_parent):
     696                  child = etree.Element(self_node.text)
     697                  child.text = 'X'
     698                  output_parent.append(child)
     699
     700          extensions = { ('testns', 'myext') : MyExt() }
     701
     702          result = tree.xslt(style, extensions=extensions)
     703          self.assertEquals(self._rootstring(result),
     704                            _bytes('<A><b>X</b></A>'))
     705
     706 -    def test_extension_element_content(self):
     707          tree = self.parse('<a><b>B</b></a>')
     708          style = self.parse('''\
     709  <xsl:stylesheet version="1.0"
     710      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     711      xmlns:myns="testns"
     712      extension-element-prefixes="myns">
     713    <xsl:template match="a">
     714      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
     715    </xsl:template>
     716  </xsl:stylesheet>''')
     717
     718          class MyExt(etree.XSLTExtension):
     719              def execute(self, context, self_node, input_node, output_parent):
     720                  output_parent.extend(list(self_node)[1:])
     721
     722          extensions = { ('testns', 'myext') : MyExt() }
     723
     724          result = tree.xslt(style, extensions=extensions)
     725          self.assertEquals(self._rootstring(result),
     726                            _bytes('<A><y>Y</y><z/></A>'))
     727
     728 -    def test_extension_element_apply_templates(self):
     729          tree = self.parse('<a><b>B</b></a>')
     730          style = self.parse('''\
     731  <xsl:stylesheet version="1.0"
     732      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     733      xmlns:myns="testns"
     734      extension-element-prefixes="myns">
     735    <xsl:template match="a">
     736      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
     737    </xsl:template>
     738    <xsl:template match="x" />
     739    <xsl:template match="z">XYZ</xsl:template>
     740  </xsl:stylesheet>''')
     741
     742          class MyExt(etree.XSLTExtension):
     743              def execute(self, context, self_node, input_node, output_parent):
     744                  for child in self_node:
     745                      for result in self.apply_templates(context, child):
     746                          if isinstance(result, basestring):
     747                              el = etree.Element("T")
     748                              el.text = result
     749                          else:
     750                              el = result
     751                          output_parent.append(el)
     752
     753          extensions = { ('testns', 'myext') : MyExt() }
     754
     755          result = tree.xslt(style, extensions=extensions)
     756          self.assertEquals(self._rootstring(result),
     757                            _bytes('<A><T>Y</T><T>XYZ</T></A>'))
     758
     759 -    def test_extension_element_raise(self):
     760          tree = self.parse('<a><b>B</b></a>')
     761          style = self.parse('''\
     762  <xsl:stylesheet version="1.0"
     763      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     764      xmlns:myns="testns"
     765      extension-element-prefixes="myns"
     766      exclude-result-prefixes="myns">
     767    <xsl:template match="a">
     768      <A><myns:myext>b</myns:myext></A>
     769    </xsl:template>
     770  </xsl:stylesheet>''')
     771
     772          class MyError(Exception):
     773              pass
     774
     775          class MyExt(etree.XSLTExtension):
     776              def execute(self, context, self_node, input_node, output_parent):
     777                  raise MyError("expected!")
     778
     779          extensions = { ('testns', 'myext') : MyExt() }
     780          self.assertRaises(MyError, tree.xslt, style, extensions=extensions)
     781
     782 -    def test_xslt_document_XML(self):
     783          # make sure document('') works from parsed strings
     784          xslt = etree.XSLT(etree.XML("""\
     785  <xsl:stylesheet version="1.0"
     786     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     787    <xsl:template match="/">
     788      <test>TEXT<xsl:copy-of select="document('')//test"/></test>
     789    </xsl:template>
     790  </xsl:stylesheet>
     791  """))
     792          result = xslt(etree.XML('<a/>'))
     793          root = result.getroot()
     794          self.assertEquals(root.tag,
     795                            'test')
     796          self.assertEquals(root[0].tag,
     797                            'test')
     798          self.assertEquals(root[0].text,
     799                            'TEXT')
     800          self.assertEquals(root[0][0].tag,
     801                            '{http://www.w3.org/1999/XSL/Transform}copy-of')
     802
     803 -    def test_xslt_document_parse(self):
     804          # make sure document('') works from loaded files
     805          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")))
     806          result = xslt(etree.XML('<a/>'))
     807          root = result.getroot()
     808          self.assertEquals(root.tag,
     809                            'test')
     810          self.assertEquals(root[0].tag,
     811                            '{http://www.w3.org/1999/XSL/Transform}stylesheet')
     812
     813 -    def test_xslt_document_elementtree(self):
     814          # make sure document('') works from loaded files
     815          xslt = etree.XSLT(etree.ElementTree(file=fileInTestDir("test-document.xslt")))
     816          result = xslt(etree.XML('<a/>'))
     817          root = result.getroot()
     818          self.assertEquals(root.tag,
     819                            'test')
     820          self.assertEquals(root[0].tag,
     821                            '{http://www.w3.org/1999/XSL/Transform}stylesheet')
     822
     823 -    def test_xslt_document_error(self):
     824          xslt = etree.XSLT(etree.XML("""\
     825  <xsl:stylesheet version="1.0"
     826     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     827    <xsl:template match="/">
     828      <test>TEXT<xsl:copy-of select="document('uri:__junkfood__is__evil__')//test"/></test>
     829    </xsl:template>
     830  </xsl:stylesheet>
     831  """))
     832          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
     833
     834 -    def test_xslt_document_XML_resolver(self):
     835          # make sure document('') works when custom resolvers are in use
     836          assertEquals = self.assertEquals
     837          called = {'count' : 0}
     838          class TestResolver(etree.Resolver):
     839              def resolve(self, url, id, context):
     840                  assertEquals(url, 'file://ANYTHING')
     841                  called['count'] += 1
     842                  return self.resolve_string('<CALLED/>', context)
     843
     844          parser = etree.XMLParser()
     845          parser.resolvers.add(TestResolver())
     846
     847          xslt = etree.XSLT(etree.XML(_bytes("""\
     848  <xsl:stylesheet version="1.0"
     849     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     850     xmlns:l="local">
     851    <xsl:template match="/">
     852      <test>
     853        <xsl:for-each select="document('')//l:data/l:entry">
     854          <xsl:copy-of select="document('file://ANYTHING')"/>
     855          <xsl:copy>
     856            <xsl:attribute name="value">
     857              <xsl:value-of select="."/>
     858            </xsl:attribute>
     859          </xsl:copy>
     860        </xsl:for-each>
     861      </test>
     862    </xsl:template>
     863    <l:data>
     864      <l:entry>A</l:entry>
     865      <l:entry>B</l:entry>
     866    </l:data>
     867  </xsl:stylesheet>
     868  """), parser))
     869
     870          self.assertEquals(called['count'], 0)
     871          result = xslt(etree.XML('<a/>'))
     872          self.assertEquals(called['count'], 1)
     873
     874          root = result.getroot()
     875          self.assertEquals(root.tag,
     876                            'test')
     877          self.assertEquals(len(root), 4)
     878
     879          self.assertEquals(root[0].tag,
     880                            'CALLED')
     881          self.assertEquals(root[1].tag,
     882                            '{local}entry')
     883          self.assertEquals(root[1].text,
     884                            None)
     885          self.assertEquals(root[1].get("value"),
     886                            'A')
     887          self.assertEquals(root[2].tag,
     888                            'CALLED')
     889          self.assertEquals(root[3].tag,
     890                            '{local}entry')
     891          self.assertEquals(root[3].text,
     892                            None)
     893          self.assertEquals(root[3].get("value"),
     894                            'B')
     895
     896 -    def test_xslt_resolver_url_building(self):
     897          assertEquals = self.assertEquals
     898          called = {'count' : 0}
     899          expected_url = None
     900          class TestResolver(etree.Resolver):
     901              def resolve(self, url, id, context):
     902                  assertEquals(url, expected_url)
     903                  called['count'] += 1
     904                  return self.resolve_string('<CALLED/>', context)
     905
     906          stylesheet_xml = _bytes("""\
     907  <xsl:stylesheet version="1.0"
     908     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     909     xmlns:l="local">
     910    <xsl:template match="/">
     911      <xsl:copy-of select="document('test.xml')"/>
     912    </xsl:template>
     913  </xsl:stylesheet>
     914  """)
     915
     916          parser = etree.XMLParser()
     917          parser.resolvers.add(TestResolver())
     918
     919          # test without base_url => relative path only
     920          expected_url = 'test.xml'
     921          xslt = etree.XSLT(etree.XML(stylesheet_xml, parser))
     922
     923          self.assertEquals(called['count'], 0)
     924          result = xslt(etree.XML('<a/>'))
     925          self.assertEquals(called['count'], 1)
     926
     927          # now the same thing with a stylesheet base URL on the filesystem
     928          called['count'] = 0
     929          expected_url = os.path.join('MY', 'BASE', 'test.xml')
     930          xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
     931                                      base_url=os.path.join('MY', 'BASE', 'FILE')))
     932
     933          self.assertEquals(called['count'], 0)
     934          result = xslt(etree.XML('<a/>'))
     935          self.assertEquals(called['count'], 1)
     936
     937          # now the same thing with a stylesheet base URL
     938          called['count'] = 0
     939          expected_url = 'http://server.com/BASE/DIR/test.xml'
     940          xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
     941                                      base_url='http://server.com/BASE/DIR/FILE'))
     942
     943          self.assertEquals(called['count'], 0)
     944          result = xslt(etree.XML('<a/>'))
     945          self.assertEquals(called['count'], 1)
     946
     947 -    def test_xslt_document_parse_allow(self):
     948          access_control = etree.XSLTAccessControl(read_file=True)
     949          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
     950                            access_control = access_control)
     951          result = xslt(etree.XML('<a/>'))
     952          root = result.getroot()
     953          self.assertEquals(root.tag,
     954                            'test')
     955          self.assertEquals(root[0].tag,
     956                            '{http://www.w3.org/1999/XSL/Transform}stylesheet')
     957
     958 -    def test_xslt_document_parse_deny(self):
     959          access_control = etree.XSLTAccessControl(read_file=False)
     960          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
     961                            access_control = access_control)
     962          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
     963
     964 -    def test_xslt_document_parse_deny_all(self):
     965          access_control = etree.XSLTAccessControl.DENY_ALL
     966          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
     967                            access_control = access_control)
     968          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
     969
     970 -    def test_xslt_move_result(self):
     971          root = etree.XML(_bytes('''\
     972          <transform>
     973            <widget displayType="fieldset"/>
     974          </transform>'''))
     975
     976          xslt = etree.XSLT(etree.XML(_bytes('''\
     977          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     978            <xsl:output method="html" indent="no"/>
     979            <xsl:template match="/">
     980              <html>
     981                <xsl:apply-templates/>
     982              </html>
     983            </xsl:template>
     984
     985            <xsl:template match="widget">
     986              <xsl:element name="{@displayType}"/>
     987            </xsl:template>
     988
     989          </xsl:stylesheet>''')))
     990
     991          result = xslt(root[0])
     992          root[:] = result.getroot()[:]
     993          del root # segfaulted before
     994
     995 -    def test_xslt_pi(self):
     996          tree = self.parse('''\
     997  <?xml version="1.0"?>
     998  <?xml-stylesheet type="text/xsl" href="%s"?>
     999  <a>
    1000    <b>B</b>
    1001    <c>C</c>
    1002  </a>''' % fileInTestDir("test1.xslt"))
    1003
    1004          style_root = tree.getroot().getprevious().parseXSL().getroot()
    1005          self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
    1006                            style_root.tag)
    1007
    1008 -    def test_xslt_pi_embedded_xmlid(self):
    1009          # test xml:id dictionary lookup mechanism
    1010          tree = self.parse('''\
    1011  <?xml version="1.0"?>
    1012  <?xml-stylesheet type="text/xsl" href="#style"?>
    1013  <a>
    1014    <b>B</b>
    1015    <c>C</c>
    1016    <xsl:stylesheet version="1.0" xml:id="style"
    1017        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1018      <xsl:template match="*" />
    1019      <xsl:template match="/">
    1020        <foo><xsl:value-of select="/a/b/text()" /></foo>
    1021      </xsl:template>
    1022    </xsl:stylesheet>
    1023  </a>''')
    1024
    1025          style_root = tree.getroot().getprevious().parseXSL().getroot()
    1026          self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
    1027                            style_root.tag)
    1028
    1029          st = etree.XSLT(style_root)
    1030          res = st(tree)
    1031          self.assertEquals('''\
    1032  <?xml version="1.0"?>
    1033  <foo>B</foo>
    1034  ''',
    1035                            str(res))
    1036
    1037 -    def test_xslt_pi_embedded_id(self):
    1038          # test XPath lookup mechanism
    1039          tree = self.parse('''\
    1040  <?xml version="1.0"?>
    1041  <?xml-stylesheet type="text/xsl" href="#style"?>
    1042  <a>
    1043    <b>B</b>
    1044    <c>C</c>
    1045  </a>''')
    1046
    1047          style = self.parse('''\
    1048  <xsl:stylesheet version="1.0" xml:id="style"
    1049      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1050    <xsl:template match="*" />
    1051    <xsl:template match="/">
    1052      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1053    </xsl:template>
    1054  </xsl:stylesheet>
    1055  ''')
    1056
    1057          tree.getroot().append(style.getroot())
    1058
    1059          style_root = tree.getroot().getprevious().parseXSL().getroot()
    1060          self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
    1061                            style_root.tag)
    1062
    1063          st = etree.XSLT(style_root)
    1064          res = st(tree)
    1065          self.assertEquals('''\
    1066  <?xml version="1.0"?>
    1067  <foo>B</foo>
    1068  ''',
    1069                            str(res))
    1070
    1071 -    def test_xslt_pi_get(self):
    1072          tree = self.parse('''\
    1073  <?xml version="1.0"?>
    1074  <?xml-stylesheet type="text/xsl" href="TEST"?>
    1075  <a>
    1076    <b>B</b>
    1077    <c>C</c>
    1078  </a>''')
    1079
    1080          pi = tree.getroot().getprevious()
    1081          self.assertEquals("TEST", pi.get("href"))
    1082
    1083 -    def test_xslt_pi_get_all(self):
    1084          tree = self.parse('''\
    1085  <?xml version="1.0"?>
    1086  <?xml-stylesheet type="text/xsl" href="TEST"?>
    1087  <a>
    1088    <b>B</b>
    1089    <c>C</c>
    1090  </a>''')
    1091
    1092          pi = tree.getroot().getprevious()
    1093          self.assertEquals("TEST", pi.get("href"))
    1094          self.assertEquals("text/xsl", pi.get("type"))
    1095          self.assertEquals(None, pi.get("motz"))
    1096
    1097 -    def test_xslt_pi_get_all_reversed(self):
    1098          tree = self.parse('''\
    1099  <?xml version="1.0"?>
    1100  <?xml-stylesheet href="TEST" type="text/xsl"?>
    1101  <a>
    1102    <b>B</b>
    1103    <c>C</c>
    1104  </a>''')
    1105
    1106          pi = tree.getroot().getprevious()
    1107          self.assertEquals("TEST", pi.get("href"))
    1108          self.assertEquals("text/xsl", pi.get("type"))
    1109          self.assertEquals(None, pi.get("motz"))
    1110
    1111 -    def test_xslt_pi_get_unknown(self):
    1112          tree = self.parse('''\
    1113  <?xml version="1.0"?>
    1114  <?xml-stylesheet type="text/xsl" href="TEST"?>
    1115  <a>
    1116    <b>B</b>
    1117    <c>C</c>
    1118  </a>''')
    1119
    1120          pi = tree.getroot().getprevious()
    1121          self.assertEquals(None, pi.get("unknownattribute"))
    1122
    1123 -    def test_xslt_pi_set_replace(self):
    1124          tree = self.parse('''\
    1125  <?xml version="1.0"?>
    1126  <?xml-stylesheet type="text/xsl" href="TEST"?>
    1127  <a>
    1128    <b>B</b>
    1129    <c>C</c>
    1130  </a>''')
    1131
    1132          pi = tree.getroot().getprevious()
    1133          self.assertEquals("TEST", pi.get("href"))
    1134
    1135          pi.set("href", "TEST123")
    1136          self.assertEquals("TEST123", pi.get("href"))
    1137
    1138 -    def test_xslt_pi_set_new(self):
    1139          tree = self.parse('''\
    1140  <?xml version="1.0"?>
    1141  <?xml-stylesheet type="text/xsl"?>
    1142  <a>
    1143    <b>B</b>
    1144    <c>C</c>
    1145  </a>''')
    1146
    1147          pi = tree.getroot().getprevious()
    1148          self.assertEquals(None, pi.get("href"))
    1149
    1150          pi.set("href", "TEST")
    1151          self.assertEquals("TEST", pi.get("href"))
    1152
    1153 -    def test_exslt_regexp_test(self):
    1154          xslt = etree.XSLT(etree.XML(_bytes("""\
    1155  <xsl:stylesheet version="1.0"
    1156     xmlns:regexp="http://exslt.org/regular-expressions"
    1157     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1158    <xsl:template match="*">
    1159      <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test>
    1160    </xsl:template>
    1161  </xsl:stylesheet>
    1162  """)))
    1163          result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>')))
    1164          root = result.getroot()
    1165          self.assertEquals(root.tag,
    1166                            'test')
    1167          self.assertEquals(len(root), 1)
    1168          self.assertEquals(root[0].tag,
    1169                            'b')
    1170          self.assertEquals(root[0].text,
    1171                            '987')
    1172
    1173 -    def test_exslt_regexp_replace(self):
    1174          xslt = etree.XSLT(etree.XML("""\
    1175  <xsl:stylesheet version="1.0"
    1176     xmlns:regexp="http://exslt.org/regular-expressions"
    1177     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1178    <xsl:template match="*">
    1179      <test>
    1180        <xsl:copy-of select="regexp:replace(string(.), 'd.', '',   'XX')"/>
    1181        <xsl:text>-</xsl:text>
    1182        <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/>
    1183      </test>
    1184    </xsl:template>
    1185  </xsl:stylesheet>
    1186  """))
    1187          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
    1188          root = result.getroot()
    1189          self.assertEquals(root.tag,
    1190                            'test')
    1191          self.assertEquals(len(root), 0)
    1192          self.assertEquals(root.text, 'abXXdEeDed-abXXXXeXXd')
    1193
    1194 -    def test_exslt_regexp_match(self):
    1195          xslt = etree.XSLT(etree.XML("""\
    1196  <xsl:stylesheet version="1.0"
    1197     xmlns:regexp="http://exslt.org/regular-expressions"
    1198     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1199    <xsl:template match="*">
    1200      <test>
    1201        <test1><xsl:copy-of  select="regexp:match(string(.), 'd.')"/></test1>
    1202        <test2><xsl:copy-of  select="regexp:match(string(.), 'd.', 'g')"/></test2>
    1203        <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i>
    1204      </test>
    1205    </xsl:template>
    1206  </xsl:stylesheet>
    1207  """))
    1208          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
    1209          root = result.getroot()
    1210          self.assertEquals(root.tag,  'test')
    1211          self.assertEquals(len(root), 3)
    1212
    1213          self.assertEquals(len(root[0]), 1)
    1214          self.assertEquals(root[0][0].tag, 'match')
    1215          self.assertEquals(root[0][0].text, 'dC')
    1216
    1217          self.assertEquals(len(root[1]), 2)
    1218          self.assertEquals(root[1][0].tag, 'match')
    1219          self.assertEquals(root[1][0].text, 'dC')
    1220          self.assertEquals(root[1][1].tag, 'match')
    1221          self.assertEquals(root[1][1].text, 'dE')
    1222
    1223          self.assertEquals(len(root[2]), 3)
    1224          self.assertEquals(root[2][0].tag, 'match')
    1225          self.assertEquals(root[2][0].text, 'dC')
    1226          self.assertEquals(root[2][1].tag, 'match')
    1227          self.assertEquals(root[2][1].text, 'dE')
    1228          self.assertEquals(root[2][2].tag, 'match')
    1229          self.assertEquals(root[2][2].text, 'De')
    1230
    1231 -    def test_exslt_regexp_match_groups(self):
    1232          xslt = etree.XSLT(etree.XML(_bytes("""\
    1233  <xsl:stylesheet version="1.0"
    1234     xmlns:regexp="http://exslt.org/regular-expressions"
    1235     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1236    <xsl:template match="/">
    1237      <test>
    1238        <xsl:for-each select="regexp:match(
    1239              '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )">
    1240          <test1><xsl:value-of select="."/></test1>
    1241        </xsl:for-each>
    1242      </test>
    1243    </xsl:template>
    1244  </xsl:stylesheet>
    1245  """)))
    1246          result = xslt(etree.XML(_bytes('<a/>')))
    1247          root = result.getroot()
    1248          self.assertEquals(root.tag,  'test')
    1249          self.assertEquals(len(root), 4)
    1250
    1251          self.assertEquals(root[0].text, "123abc567")
    1252          self.assertEquals(root[1].text, "123")
    1253          self.assertEquals(root[2].text, "abc")
    1254          self.assertEquals(root[3].text, "567")
    1255
    1256 -    def test_exslt_regexp_match1(self):
    1257          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1258          xslt = etree.XSLT(etree.XML(_bytes("""\
    1259  <xsl:stylesheet version="1.0"
    1260     xmlns:regexp="http://exslt.org/regular-expressions"
    1261     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1262    <xsl:template match="/">
    1263      <test>
    1264        <xsl:for-each select="regexp:match(
    1265              'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml',
    1266              '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')">
    1267          <test1><xsl:value-of select="."/></test1>
    1268        </xsl:for-each>
    1269      </test>
    1270    </xsl:template>
    1271  </xsl:stylesheet>
    1272  """)))
    1273          result = xslt(etree.XML(_bytes('<a/>')))
    1274          root = result.getroot()
    1275          self.assertEquals(root.tag,  'test')
    1276          self.assertEquals(len(root), 5)
    1277
    1278          self.assertEquals(
    1279              root[0].text,
    1280              "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml")
    1281          self.assertEquals(
    1282              root[1].text,
    1283              "http")
    1284          self.assertEquals(
    1285              root[2].text,
    1286              "www.bayes.co.uk")
    1287          self.assertFalse(root[3].text)
    1288          self.assertEquals(
    1289              root[4].text,
    1290              "/xml/index.xml?/xml/utils/rechecker.xml")
    1291
    1292 -    def test_exslt_regexp_match2(self):
    1293          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1294          xslt = etree.XSLT(self.parse("""\
    1295  <xsl:stylesheet version="1.0"
    1296     xmlns:regexp="http://exslt.org/regular-expressions"
    1297     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1298    <xsl:template match="/">
    1299      <test>
    1300        <xsl:for-each select="regexp:match(
    1301              'This is a test string', '(\w+)', 'g')">
    1302          <test1><xsl:value-of select="."/></test1>
    1303        </xsl:for-each>
    1304      </test>
    1305    </xsl:template>
    1306  </xsl:stylesheet>
    1307  """))
    1308          result = xslt(etree.XML(_bytes('<a/>')))
    1309          root = result.getroot()
    1310          self.assertEquals(root.tag,  'test')
    1311          self.assertEquals(len(root), 5)
    1312
    1313          self.assertEquals(root[0].text, "This")
    1314          self.assertEquals(root[1].text, "is")
    1315          self.assertEquals(root[2].text, "a")
    1316          self.assertEquals(root[3].text, "test")
    1317          self.assertEquals(root[4].text, "string")
    1318
    1319 -    def _test_exslt_regexp_match3(self):
    1320          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1321          # THIS IS NOT SUPPORTED!
    1322          xslt = etree.XSLT(etree.XML(_bytes("""\
    1323  <xsl:stylesheet version="1.0"
    1324     xmlns:regexp="http://exslt.org/regular-expressions"
    1325     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1326    <xsl:template match="/">
    1327      <test>
    1328        <xsl:for-each select="regexp:match(
    1329              'This is a test string', '([a-z])+ ', 'g')">
    1330          <test1><xsl:value-of select="."/></test1>
    1331        </xsl:for-each>
    1332      </test>
    1333    </xsl:template>
    1334  </xsl:stylesheet>
    1335  """)))
    1336          result = xslt(etree.XML(_bytes('<a/>')))
    1337          root = result.getroot()
    1338          self.assertEquals(root.tag,  'test')
    1339          self.assertEquals(len(root), 4)
    1340
    1341          self.assertEquals(root[0].text, "his")
    1342          self.assertEquals(root[1].text, "is")
    1343          self.assertEquals(root[2].text, "a")
    1344          self.assertEquals(root[3].text, "test")
    1345
    1346 -    def _test_exslt_regexp_match4(self):
    1347          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1348          # THIS IS NOT SUPPORTED!
    1349          xslt = etree.XSLT(etree.XML(_bytes("""\
    1350  <xsl:stylesheet version="1.0"
    1351     xmlns:regexp="http://exslt.org/regular-expressions"
    1352     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1353    <xsl:template match="/">
    1354      <test>
    1355        <xsl:for-each select="regexp:match(
    1356              'This is a test string', '([a-z])+ ', 'gi')">
    1357          <test1><xsl:value-of select="."/></test1>
    1358        </xsl:for-each>
    1359      </test>
    1360    </xsl:template>
    1361  </xsl:stylesheet>
    1362  """)))
    1363          result = xslt(etree.XML(_bytes('<a/>')))
    1364          root = result.getroot()
    1365          self.assertEquals(root.tag,  'test')
    1366          self.assertEquals(len(root), 4)
    1367
    1368          self.assertEquals(root[0].text, "This")
    1369          self.assertEquals(root[1].text, "is")
    1370          self.assertEquals(root[2].text, "a")
    1371          self.assertEquals(root[3].text, "test")
    1372
    1373
    1374 -class Py3XSLTTestCase(HelperTestCase):
    1375      """XSLT tests for etree under Python 3"""
    1376 -    def test_xslt_result_bytes(self):
    1377          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1378          style = self.parse('''\
    1379  <xsl:stylesheet version="1.0"
    1380      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1381    <xsl:template match="*" />
    1382    <xsl:template match="/">
    1383      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1384    </xsl:template>
    1385  </xsl:stylesheet>''')
    1386
    1387          st = etree.XSLT(style)
    1388          res = st(tree)
    1389          self.assertEquals(_bytes('''\
    1390  <?xml version="1.0"?>
    1391  <foo>B</foo>
    1392  '''),
    1393                            bytes(res))
    1394
    1395 -    def test_xslt_result_bytearray(self):
    1396          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1397          style = self.parse('''\
    1398  <xsl:stylesheet version="1.0"
    1399      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1400    <xsl:template match="*" />
    1401    <xsl:template match="/">
    1402      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1403    </xsl:template>
    1404  </xsl:stylesheet>''')
    1405
    1406          st = etree.XSLT(style)
    1407          res = st(tree)
    1408          self.assertEquals(_bytes('''\
    1409  <?xml version="1.0"?>
    1410  <foo>B</foo>
    1411  '''),
    1412                            bytearray(res))
    1413
    1414 -    def test_xslt_result_memoryview(self):
    1415          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1416          style = self.parse('''\
    1417  <xsl:stylesheet version="1.0"
    1418      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1419    <xsl:template match="*" />
    1420    <xsl:template match="/">
    1421      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1422    </xsl:template>
    1423  </xsl:stylesheet>''')
    1424
    1425          st = etree.XSLT(style)
    1426          res = st(tree)
    1427          self.assertEquals(_bytes('''\
    1428  <?xml version="1.0"?>
    1429  <foo>B</foo>
    1430  '''),
    1431                            bytes(memoryview(res)))
    1432
    1433
    1434 -def test_suite():
    1435      suite = unittest.TestSuite()
    1436      suite.addTests([unittest.makeSuite(ETreeXSLTTestCase)])
    1437      if is_python3:
    1438          suite.addTests([unittest.makeSuite(Py3XSLTTestCase)])
    1439      suite.addTests(
    1440          [make_doctest('../../../doc/extensions.txt')])
    1441      suite.addTests(
    1442          [make_doctest('../../../doc/xpathxslt.txt')])
    1443      return suite
    1444
    1445  if __name__ == '__main__':
    1446      print('to test use test.py %s' % __file__)
    1447