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