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_doc_context(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      exclude-result-prefixes="myns">
     732    <xsl:template match="/">
     733      <A><myns:myext>b</myns:myext></A>
     734    </xsl:template>
     735  </xsl:stylesheet>''')
     736
     737          tags = []
     738
     739          class MyExt(etree.XSLTExtension):
     740              def execute(self, context, self_node, input_node, output_parent):
     741                  tags.append(input_node.tag)
     742
     743          extensions = { ('testns', 'myext') : MyExt() }
     744
     745          result = tree.xslt(style, extensions=extensions)
     746          self.assertEquals(tags, ['a'])
     747
     748 -    def test_extension_element_unsupported_context(self):
     749          tree = self.parse('<a><!--a comment--></a>')
     750          style = self.parse('''\
     751  <xsl:stylesheet version="1.0"
     752      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     753      xmlns:myns="testns"
     754      extension-element-prefixes="myns"
     755      exclude-result-prefixes="myns">
     756    <xsl:template match="comment()">
     757      <A><myns:myext>b</myns:myext></A>
     758    </xsl:template>
     759  </xsl:stylesheet>''')
     760
     761          tags = []
     762
     763          class MyExt(etree.XSLTExtension):
     764              def execute(self, context, self_node, input_node, output_parent):
     765                  tags.append(input_node.tag)
     766
     767          extensions = { ('testns', 'myext') : MyExt() }
     768
     769          self.assertRaises(TypeError, tree.xslt, style, extensions=extensions)
     770          self.assertEquals(tags, [])
     771
     772 -    def test_extension_element_content(self):
     773          tree = self.parse('<a><b>B</b></a>')
     774          style = self.parse('''\
     775  <xsl:stylesheet version="1.0"
     776      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     777      xmlns:myns="testns"
     778      extension-element-prefixes="myns">
     779    <xsl:template match="a">
     780      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
     781    </xsl:template>
     782  </xsl:stylesheet>''')
     783
     784          class MyExt(etree.XSLTExtension):
     785              def execute(self, context, self_node, input_node, output_parent):
     786                  output_parent.extend(list(self_node)[1:])
     787
     788          extensions = { ('testns', 'myext') : MyExt() }
     789
     790          result = tree.xslt(style, extensions=extensions)
     791          self.assertEquals(self._rootstring(result),
     792                            _bytes('<A><y>Y</y><z/></A>'))
     793
     794 -    def test_extension_element_apply_templates(self):
     795          tree = self.parse('<a><b>B</b></a>')
     796          style = self.parse('''\
     797  <xsl:stylesheet version="1.0"
     798      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     799      xmlns:myns="testns"
     800      extension-element-prefixes="myns">
     801    <xsl:template match="a">
     802      <A><myns:myext><x>X</x><y>Y</y><z/></myns:myext></A>
     803    </xsl:template>
     804    <xsl:template match="x" />
     805    <xsl:template match="z">XYZ</xsl:template>
     806  </xsl:stylesheet>''')
     807
     808          class MyExt(etree.XSLTExtension):
     809              def execute(self, context, self_node, input_node, output_parent):
     810                  for child in self_node:
     811                      for result in self.apply_templates(context, child):
     812                          if isinstance(result, basestring):
     813                              el = etree.Element("T")
     814                              el.text = result
     815                          else:
     816                              el = result
     817                          output_parent.append(el)
     818
     819          extensions = { ('testns', 'myext') : MyExt() }
     820
     821          result = tree.xslt(style, extensions=extensions)
     822          self.assertEquals(self._rootstring(result),
     823                            _bytes('<A><T>Y</T><T>XYZ</T></A>'))
     824
     825 -    def test_extension_element_raise(self):
     826          tree = self.parse('<a><b>B</b></a>')
     827          style = self.parse('''\
     828  <xsl:stylesheet version="1.0"
     829      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     830      xmlns:myns="testns"
     831      extension-element-prefixes="myns"
     832      exclude-result-prefixes="myns">
     833    <xsl:template match="a">
     834      <A><myns:myext>b</myns:myext></A>
     835    </xsl:template>
     836  </xsl:stylesheet>''')
     837
     838          class MyError(Exception):
     839              pass
     840
     841          class MyExt(etree.XSLTExtension):
     842              def execute(self, context, self_node, input_node, output_parent):
     843                  raise MyError("expected!")
     844
     845          extensions = { ('testns', 'myext') : MyExt() }
     846          self.assertRaises(MyError, tree.xslt, style, extensions=extensions)
     847
     848 -    def test_xslt_document_XML(self):
     849          # make sure document('') works from parsed strings
     850          xslt = etree.XSLT(etree.XML("""\
     851  <xsl:stylesheet version="1.0"
     852     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     853    <xsl:template match="/">
     854      <test>TEXT<xsl:copy-of select="document('')//test"/></test>
     855    </xsl:template>
     856  </xsl:stylesheet>
     857  """))
     858          result = xslt(etree.XML('<a/>'))
     859          root = result.getroot()
     860          self.assertEquals(root.tag,
     861                            'test')
     862          self.assertEquals(root[0].tag,
     863                            'test')
     864          self.assertEquals(root[0].text,
     865                            'TEXT')
     866          self.assertEquals(root[0][0].tag,
     867                            '{http://www.w3.org/1999/XSL/Transform}copy-of')
     868
     869 -    def test_xslt_document_parse(self):
     870          # make sure document('') works from loaded files
     871          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")))
     872          result = xslt(etree.XML('<a/>'))
     873          root = result.getroot()
     874          self.assertEquals(root.tag,
     875                            'test')
     876          self.assertEquals(root[0].tag,
     877                            '{http://www.w3.org/1999/XSL/Transform}stylesheet')
     878
     879 -    def test_xslt_document_elementtree(self):
     880          # make sure document('') works from loaded files
     881          xslt = etree.XSLT(etree.ElementTree(file=fileInTestDir("test-document.xslt")))
     882          result = xslt(etree.XML('<a/>'))
     883          root = result.getroot()
     884          self.assertEquals(root.tag,
     885                            'test')
     886          self.assertEquals(root[0].tag,
     887                            '{http://www.w3.org/1999/XSL/Transform}stylesheet')
     888
     889 -    def test_xslt_document_error(self):
     890          xslt = etree.XSLT(etree.XML("""\
     891  <xsl:stylesheet version="1.0"
     892     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     893    <xsl:template match="/">
     894      <test>TEXT<xsl:copy-of select="document('uri:__junkfood__is__evil__')//test"/></test>
     895    </xsl:template>
     896  </xsl:stylesheet>
     897  """))
     898          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
     899
     900 -    def test_xslt_document_XML_resolver(self):
     901          # make sure document('') works when custom resolvers are in use
     902          assertEquals = self.assertEquals
     903          called = {'count' : 0}
     904          class TestResolver(etree.Resolver):
     905              def resolve(self, url, id, context):
     906                  assertEquals(url, 'file://ANYTHING')
     907                  called['count'] += 1
     908                  return self.resolve_string('<CALLED/>', context)
     909
     910          parser = etree.XMLParser()
     911          parser.resolvers.add(TestResolver())
     912
     913          xslt = etree.XSLT(etree.XML(_bytes("""\
     914  <xsl:stylesheet version="1.0"
     915     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     916     xmlns:l="local">
     917    <xsl:template match="/">
     918      <test>
     919        <xsl:for-each select="document('')//l:data/l:entry">
     920          <xsl:copy-of select="document('file://ANYTHING')"/>
     921          <xsl:copy>
     922            <xsl:attribute name="value">
     923              <xsl:value-of select="."/>
     924            </xsl:attribute>
     925          </xsl:copy>
     926        </xsl:for-each>
     927      </test>
     928    </xsl:template>
     929    <l:data>
     930      <l:entry>A</l:entry>
     931      <l:entry>B</l:entry>
     932    </l:data>
     933  </xsl:stylesheet>
     934  """), parser))
     935
     936          self.assertEquals(called['count'], 0)
     937          result = xslt(etree.XML('<a/>'))
     938          self.assertEquals(called['count'], 1)
     939
     940          root = result.getroot()
     941          self.assertEquals(root.tag,
     942                            'test')
     943          self.assertEquals(len(root), 4)
     944
     945          self.assertEquals(root[0].tag,
     946                            'CALLED')
     947          self.assertEquals(root[1].tag,
     948                            '{local}entry')
     949          self.assertEquals(root[1].text,
     950                            None)
     951          self.assertEquals(root[1].get("value"),
     952                            'A')
     953          self.assertEquals(root[2].tag,
     954                            'CALLED')
     955          self.assertEquals(root[3].tag,
     956                            '{local}entry')
     957          self.assertEquals(root[3].text,
     958                            None)
     959          self.assertEquals(root[3].get("value"),
     960                            'B')
     961
     962 -    def test_xslt_resolver_url_building(self):
     963          assertEquals = self.assertEquals
     964          called = {'count' : 0}
     965          expected_url = None
     966          class TestResolver(etree.Resolver):
     967              def resolve(self, url, id, context):
     968                  assertEquals(url, expected_url)
     969                  called['count'] += 1
     970                  return self.resolve_string('<CALLED/>', context)
     971
     972          stylesheet_xml = _bytes("""\
     973  <xsl:stylesheet version="1.0"
     974     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     975     xmlns:l="local">
     976    <xsl:template match="/">
     977      <xsl:copy-of select="document('test.xml')"/>
     978    </xsl:template>
     979  </xsl:stylesheet>
     980  """)
     981
     982          parser = etree.XMLParser()
     983          parser.resolvers.add(TestResolver())
     984
     985          # test without base_url => relative path only
     986          expected_url = 'test.xml'
     987          xslt = etree.XSLT(etree.XML(stylesheet_xml, parser))
     988
     989          self.assertEquals(called['count'], 0)
     990          result = xslt(etree.XML('<a/>'))
     991          self.assertEquals(called['count'], 1)
     992
     993          # now the same thing with a stylesheet base URL on the filesystem
     994          called['count'] = 0
     995          expected_url = os.path.join('MY', 'BASE', 'test.xml')
     996          xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
     997                                      base_url=os.path.join('MY', 'BASE', 'FILE')))
     998
     999          self.assertEquals(called['count'], 0)
    1000          result = xslt(etree.XML('<a/>'))
    1001          self.assertEquals(called['count'], 1)
    1002
    1003          # now the same thing with a stylesheet base URL
    1004          called['count'] = 0
    1005          expected_url = 'http://server.com/BASE/DIR/test.xml'
    1006          xslt = etree.XSLT(etree.XML(stylesheet_xml, parser,
    1007                                      base_url='http://server.com/BASE/DIR/FILE'))
    1008
    1009          self.assertEquals(called['count'], 0)
    1010          result = xslt(etree.XML('<a/>'))
    1011          self.assertEquals(called['count'], 1)
    1012
    1013 -    def test_xslt_document_parse_allow(self):
    1014          access_control = etree.XSLTAccessControl(read_file=True)
    1015          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
    1016                            access_control = access_control)
    1017          result = xslt(etree.XML('<a/>'))
    1018          root = result.getroot()
    1019          self.assertEquals(root.tag,
    1020                            'test')
    1021          self.assertEquals(root[0].tag,
    1022                            '{http://www.w3.org/1999/XSL/Transform}stylesheet')
    1023
    1024 -    def test_xslt_document_parse_deny(self):
    1025          access_control = etree.XSLTAccessControl(read_file=False)
    1026          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
    1027                            access_control = access_control)
    1028          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
    1029
    1030 -    def test_xslt_document_parse_deny_all(self):
    1031          access_control = etree.XSLTAccessControl.DENY_ALL
    1032          xslt = etree.XSLT(etree.parse(fileInTestDir("test-document.xslt")),
    1033                            access_control = access_control)
    1034          self.assertRaises(etree.XSLTApplyError, xslt, etree.XML('<a/>'))
    1035
    1036 -    def test_xslt_move_result(self):
    1037          root = etree.XML(_bytes('''\
    1038          <transform>
    1039            <widget displayType="fieldset"/>
    1040          </transform>'''))
    1041
    1042          xslt = etree.XSLT(etree.XML(_bytes('''\
    1043          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1044            <xsl:output method="html" indent="no"/>
    1045            <xsl:template match="/">
    1046              <html>
    1047                <xsl:apply-templates/>
    1048              </html>
    1049            </xsl:template>
    1050
    1051            <xsl:template match="widget">
    1052              <xsl:element name="{@displayType}"/>
    1053            </xsl:template>
    1054
    1055          </xsl:stylesheet>''')))
    1056
    1057          result = xslt(root[0])
    1058          root[:] = result.getroot()[:]
    1059          del root # segfaulted before
    1060
    1061 -    def test_xslt_pi(self):
    1062          tree = self.parse('''\
    1063  <?xml version="1.0"?>
    1064  <?xml-stylesheet type="text/xsl" href="%s"?>
    1065  <a>
    1066    <b>B</b>
    1067    <c>C</c>
    1068  </a>''' % fileInTestDir("test1.xslt"))
    1069
    1070          style_root = tree.getroot().getprevious().parseXSL().getroot()
    1071          self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
    1072                            style_root.tag)
    1073
    1074 -    def test_xslt_pi_embedded_xmlid(self):
    1075          # test xml:id dictionary lookup mechanism
    1076          tree = self.parse('''\
    1077  <?xml version="1.0"?>
    1078  <?xml-stylesheet type="text/xsl" href="#style"?>
    1079  <a>
    1080    <b>B</b>
    1081    <c>C</c>
    1082    <xsl:stylesheet version="1.0" xml:id="style"
    1083        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1084      <xsl:template match="*" />
    1085      <xsl:template match="/">
    1086        <foo><xsl:value-of select="/a/b/text()" /></foo>
    1087      </xsl:template>
    1088    </xsl:stylesheet>
    1089  </a>''')
    1090
    1091          style_root = tree.getroot().getprevious().parseXSL().getroot()
    1092          self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
    1093                            style_root.tag)
    1094
    1095          st = etree.XSLT(style_root)
    1096          res = st(tree)
    1097          self.assertEquals('''\
    1098  <?xml version="1.0"?>
    1099  <foo>B</foo>
    1100  ''',
    1101                            str(res))
    1102
    1103 -    def test_xslt_pi_embedded_id(self):
    1104          # test XPath lookup mechanism
    1105          tree = self.parse('''\
    1106  <?xml version="1.0"?>
    1107  <?xml-stylesheet type="text/xsl" href="#style"?>
    1108  <a>
    1109    <b>B</b>
    1110    <c>C</c>
    1111  </a>''')
    1112
    1113          style = self.parse('''\
    1114  <xsl:stylesheet version="1.0" xml:id="style"
    1115      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1116    <xsl:template match="*" />
    1117    <xsl:template match="/">
    1118      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1119    </xsl:template>
    1120  </xsl:stylesheet>
    1121  ''')
    1122
    1123          tree.getroot().append(style.getroot())
    1124
    1125          style_root = tree.getroot().getprevious().parseXSL().getroot()
    1126          self.assertEquals("{http://www.w3.org/1999/XSL/Transform}stylesheet",
    1127                            style_root.tag)
    1128
    1129          st = etree.XSLT(style_root)
    1130          res = st(tree)
    1131          self.assertEquals('''\
    1132  <?xml version="1.0"?>
    1133  <foo>B</foo>
    1134  ''',
    1135                            str(res))
    1136
    1137 -    def test_xslt_pi_get(self):
    1138          tree = self.parse('''\
    1139  <?xml version="1.0"?>
    1140  <?xml-stylesheet type="text/xsl" href="TEST"?>
    1141  <a>
    1142    <b>B</b>
    1143    <c>C</c>
    1144  </a>''')
    1145
    1146          pi = tree.getroot().getprevious()
    1147          self.assertEquals("TEST", pi.get("href"))
    1148
    1149 -    def test_xslt_pi_get_all(self):
    1150          tree = self.parse('''\
    1151  <?xml version="1.0"?>
    1152  <?xml-stylesheet type="text/xsl" href="TEST"?>
    1153  <a>
    1154    <b>B</b>
    1155    <c>C</c>
    1156  </a>''')
    1157
    1158          pi = tree.getroot().getprevious()
    1159          self.assertEquals("TEST", pi.get("href"))
    1160          self.assertEquals("text/xsl", pi.get("type"))
    1161          self.assertEquals(None, pi.get("motz"))
    1162
    1163 -    def test_xslt_pi_get_all_reversed(self):
    1164          tree = self.parse('''\
    1165  <?xml version="1.0"?>
    1166  <?xml-stylesheet href="TEST" type="text/xsl"?>
    1167  <a>
    1168    <b>B</b>
    1169    <c>C</c>
    1170  </a>''')
    1171
    1172          pi = tree.getroot().getprevious()
    1173          self.assertEquals("TEST", pi.get("href"))
    1174          self.assertEquals("text/xsl", pi.get("type"))
    1175          self.assertEquals(None, pi.get("motz"))
    1176
    1177 -    def test_xslt_pi_get_unknown(self):
    1178          tree = self.parse('''\
    1179  <?xml version="1.0"?>
    1180  <?xml-stylesheet type="text/xsl" href="TEST"?>
    1181  <a>
    1182    <b>B</b>
    1183    <c>C</c>
    1184  </a>''')
    1185
    1186          pi = tree.getroot().getprevious()
    1187          self.assertEquals(None, pi.get("unknownattribute"))
    1188
    1189 -    def test_xslt_pi_set_replace(self):
    1190          tree = self.parse('''\
    1191  <?xml version="1.0"?>
    1192  <?xml-stylesheet type="text/xsl" href="TEST"?>
    1193  <a>
    1194    <b>B</b>
    1195    <c>C</c>
    1196  </a>''')
    1197
    1198          pi = tree.getroot().getprevious()
    1199          self.assertEquals("TEST", pi.get("href"))
    1200
    1201          pi.set("href", "TEST123")
    1202          self.assertEquals("TEST123", pi.get("href"))
    1203
    1204 -    def test_xslt_pi_set_new(self):
    1205          tree = self.parse('''\
    1206  <?xml version="1.0"?>
    1207  <?xml-stylesheet type="text/xsl"?>
    1208  <a>
    1209    <b>B</b>
    1210    <c>C</c>
    1211  </a>''')
    1212
    1213          pi = tree.getroot().getprevious()
    1214          self.assertEquals(None, pi.get("href"))
    1215
    1216          pi.set("href", "TEST")
    1217          self.assertEquals("TEST", pi.get("href"))
    1218
    1219 -    def test_exslt_regexp_test(self):
    1220          xslt = etree.XSLT(etree.XML(_bytes("""\
    1221  <xsl:stylesheet version="1.0"
    1222     xmlns:regexp="http://exslt.org/regular-expressions"
    1223     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1224    <xsl:template match="*">
    1225      <test><xsl:copy-of select="*[regexp:test(string(.), '8.')]"/></test>
    1226    </xsl:template>
    1227  </xsl:stylesheet>
    1228  """)))
    1229          result = xslt(etree.XML(_bytes('<a><b>123</b><b>098</b><b>987</b></a>')))
    1230          root = result.getroot()
    1231          self.assertEquals(root.tag,
    1232                            'test')
    1233          self.assertEquals(len(root), 1)
    1234          self.assertEquals(root[0].tag,
    1235                            'b')
    1236          self.assertEquals(root[0].text,
    1237                            '987')
    1238
    1239 -    def test_exslt_regexp_replace(self):
    1240          xslt = etree.XSLT(etree.XML("""\
    1241  <xsl:stylesheet version="1.0"
    1242     xmlns:regexp="http://exslt.org/regular-expressions"
    1243     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1244    <xsl:template match="*">
    1245      <test>
    1246        <xsl:copy-of select="regexp:replace(string(.), 'd.', '',   'XX')"/>
    1247        <xsl:text>-</xsl:text>
    1248        <xsl:copy-of select="regexp:replace(string(.), 'd.', 'gi', 'XX')"/>
    1249      </test>
    1250    </xsl:template>
    1251  </xsl:stylesheet>
    1252  """))
    1253          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
    1254          root = result.getroot()
    1255          self.assertEquals(root.tag,
    1256                            'test')
    1257          self.assertEquals(len(root), 0)
    1258          self.assertEquals(root.text, 'abXXdEeDed-abXXXXeXXd')
    1259
    1260 -    def test_exslt_regexp_match(self):
    1261          xslt = etree.XSLT(etree.XML("""\
    1262  <xsl:stylesheet version="1.0"
    1263     xmlns:regexp="http://exslt.org/regular-expressions"
    1264     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1265    <xsl:template match="*">
    1266      <test>
    1267        <test1><xsl:copy-of  select="regexp:match(string(.), 'd.')"/></test1>
    1268        <test2><xsl:copy-of  select="regexp:match(string(.), 'd.', 'g')"/></test2>
    1269        <test2i><xsl:copy-of select="regexp:match(string(.), 'd.', 'gi')"/></test2i>
    1270      </test>
    1271    </xsl:template>
    1272  </xsl:stylesheet>
    1273  """))
    1274          result = xslt(etree.XML(_bytes('<a>abdCdEeDed</a>')))
    1275          root = result.getroot()
    1276          self.assertEquals(root.tag,  'test')
    1277          self.assertEquals(len(root), 3)
    1278
    1279          self.assertEquals(len(root[0]), 1)
    1280          self.assertEquals(root[0][0].tag, 'match')
    1281          self.assertEquals(root[0][0].text, 'dC')
    1282
    1283          self.assertEquals(len(root[1]), 2)
    1284          self.assertEquals(root[1][0].tag, 'match')
    1285          self.assertEquals(root[1][0].text, 'dC')
    1286          self.assertEquals(root[1][1].tag, 'match')
    1287          self.assertEquals(root[1][1].text, 'dE')
    1288
    1289          self.assertEquals(len(root[2]), 3)
    1290          self.assertEquals(root[2][0].tag, 'match')
    1291          self.assertEquals(root[2][0].text, 'dC')
    1292          self.assertEquals(root[2][1].tag, 'match')
    1293          self.assertEquals(root[2][1].text, 'dE')
    1294          self.assertEquals(root[2][2].tag, 'match')
    1295          self.assertEquals(root[2][2].text, 'De')
    1296
    1297 -    def test_exslt_regexp_match_groups(self):
    1298          xslt = etree.XSLT(etree.XML(_bytes("""\
    1299  <xsl:stylesheet version="1.0"
    1300     xmlns:regexp="http://exslt.org/regular-expressions"
    1301     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1302    <xsl:template match="/">
    1303      <test>
    1304        <xsl:for-each select="regexp:match(
    1305              '123abc567', '([0-9]+)([a-z]+)([0-9]+)' )">
    1306          <test1><xsl:value-of select="."/></test1>
    1307        </xsl:for-each>
    1308      </test>
    1309    </xsl:template>
    1310  </xsl:stylesheet>
    1311  """)))
    1312          result = xslt(etree.XML(_bytes('<a/>')))
    1313          root = result.getroot()
    1314          self.assertEquals(root.tag,  'test')
    1315          self.assertEquals(len(root), 4)
    1316
    1317          self.assertEquals(root[0].text, "123abc567")
    1318          self.assertEquals(root[1].text, "123")
    1319          self.assertEquals(root[2].text, "abc")
    1320          self.assertEquals(root[3].text, "567")
    1321
    1322 -    def test_exslt_regexp_match1(self):
    1323          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1324          xslt = etree.XSLT(etree.XML(_bytes("""\
    1325  <xsl:stylesheet version="1.0"
    1326     xmlns:regexp="http://exslt.org/regular-expressions"
    1327     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1328    <xsl:template match="/">
    1329      <test>
    1330        <xsl:for-each select="regexp:match(
    1331              'http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml',
    1332              '(\w+):\/\/([^/:]+)(:\d*)?([^# ]*)')">
    1333          <test1><xsl:value-of select="."/></test1>
    1334        </xsl:for-each>
    1335      </test>
    1336    </xsl:template>
    1337  </xsl:stylesheet>
    1338  """)))
    1339          result = xslt(etree.XML(_bytes('<a/>')))
    1340          root = result.getroot()
    1341          self.assertEquals(root.tag,  'test')
    1342          self.assertEquals(len(root), 5)
    1343
    1344          self.assertEquals(
    1345              root[0].text,
    1346              "http://www.bayes.co.uk/xml/index.xml?/xml/utils/rechecker.xml")
    1347          self.assertEquals(
    1348              root[1].text,
    1349              "http")
    1350          self.assertEquals(
    1351              root[2].text,
    1352              "www.bayes.co.uk")
    1353          self.assertFalse(root[3].text)
    1354          self.assertEquals(
    1355              root[4].text,
    1356              "/xml/index.xml?/xml/utils/rechecker.xml")
    1357
    1358 -    def test_exslt_regexp_match2(self):
    1359          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1360          xslt = etree.XSLT(self.parse("""\
    1361  <xsl:stylesheet version="1.0"
    1362     xmlns:regexp="http://exslt.org/regular-expressions"
    1363     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1364    <xsl:template match="/">
    1365      <test>
    1366        <xsl:for-each select="regexp:match(
    1367              'This is a test string', '(\w+)', 'g')">
    1368          <test1><xsl:value-of select="."/></test1>
    1369        </xsl:for-each>
    1370      </test>
    1371    </xsl:template>
    1372  </xsl:stylesheet>
    1373  """))
    1374          result = xslt(etree.XML(_bytes('<a/>')))
    1375          root = result.getroot()
    1376          self.assertEquals(root.tag,  'test')
    1377          self.assertEquals(len(root), 5)
    1378
    1379          self.assertEquals(root[0].text, "This")
    1380          self.assertEquals(root[1].text, "is")
    1381          self.assertEquals(root[2].text, "a")
    1382          self.assertEquals(root[3].text, "test")
    1383          self.assertEquals(root[4].text, "string")
    1384
    1385 -    def _test_exslt_regexp_match3(self):
    1386          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1387          # THIS IS NOT SUPPORTED!
    1388          xslt = etree.XSLT(etree.XML(_bytes("""\
    1389  <xsl:stylesheet version="1.0"
    1390     xmlns:regexp="http://exslt.org/regular-expressions"
    1391     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1392    <xsl:template match="/">
    1393      <test>
    1394        <xsl:for-each select="regexp:match(
    1395              'This is a test string', '([a-z])+ ', 'g')">
    1396          <test1><xsl:value-of select="."/></test1>
    1397        </xsl:for-each>
    1398      </test>
    1399    </xsl:template>
    1400  </xsl:stylesheet>
    1401  """)))
    1402          result = xslt(etree.XML(_bytes('<a/>')))
    1403          root = result.getroot()
    1404          self.assertEquals(root.tag,  'test')
    1405          self.assertEquals(len(root), 4)
    1406
    1407          self.assertEquals(root[0].text, "his")
    1408          self.assertEquals(root[1].text, "is")
    1409          self.assertEquals(root[2].text, "a")
    1410          self.assertEquals(root[3].text, "test")
    1411
    1412 -    def _test_exslt_regexp_match4(self):
    1413          # taken from http://www.exslt.org/regexp/functions/match/index.html
    1414          # THIS IS NOT SUPPORTED!
    1415          xslt = etree.XSLT(etree.XML(_bytes("""\
    1416  <xsl:stylesheet version="1.0"
    1417     xmlns:regexp="http://exslt.org/regular-expressions"
    1418     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1419    <xsl:template match="/">
    1420      <test>
    1421        <xsl:for-each select="regexp:match(
    1422              'This is a test string', '([a-z])+ ', 'gi')">
    1423          <test1><xsl:value-of select="."/></test1>
    1424        </xsl:for-each>
    1425      </test>
    1426    </xsl:template>
    1427  </xsl:stylesheet>
    1428  """)))
    1429          result = xslt(etree.XML(_bytes('<a/>')))
    1430          root = result.getroot()
    1431          self.assertEquals(root.tag,  'test')
    1432          self.assertEquals(len(root), 4)
    1433
    1434          self.assertEquals(root[0].text, "This")
    1435          self.assertEquals(root[1].text, "is")
    1436          self.assertEquals(root[2].text, "a")
    1437          self.assertEquals(root[3].text, "test")
    1438
    1439
    1440 -class Py3XSLTTestCase(HelperTestCase):
    1441      """XSLT tests for etree under Python 3"""
    1442 -    def test_xslt_result_bytes(self):
    1443          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1444          style = self.parse('''\
    1445  <xsl:stylesheet version="1.0"
    1446      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1447    <xsl:template match="*" />
    1448    <xsl:template match="/">
    1449      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1450    </xsl:template>
    1451  </xsl:stylesheet>''')
    1452
    1453          st = etree.XSLT(style)
    1454          res = st(tree)
    1455          self.assertEquals(_bytes('''\
    1456  <?xml version="1.0"?>
    1457  <foo>B</foo>
    1458  '''),
    1459                            bytes(res))
    1460
    1461 -    def test_xslt_result_bytearray(self):
    1462          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1463          style = self.parse('''\
    1464  <xsl:stylesheet version="1.0"
    1465      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1466    <xsl:template match="*" />
    1467    <xsl:template match="/">
    1468      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1469    </xsl:template>
    1470  </xsl:stylesheet>''')
    1471
    1472          st = etree.XSLT(style)
    1473          res = st(tree)
    1474          self.assertEquals(_bytes('''\
    1475  <?xml version="1.0"?>
    1476  <foo>B</foo>
    1477  '''),
    1478                            bytearray(res))
    1479
    1480 -    def test_xslt_result_memoryview(self):
    1481          tree = self.parse('<a><b>B</b><c>C</c></a>')
    1482          style = self.parse('''\
    1483  <xsl:stylesheet version="1.0"
    1484      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    1485    <xsl:template match="*" />
    1486    <xsl:template match="/">
    1487      <foo><xsl:value-of select="/a/b/text()" /></foo>
    1488    </xsl:template>
    1489  </xsl:stylesheet>''')
    1490
    1491          st = etree.XSLT(style)
    1492          res = st(tree)
    1493          self.assertEquals(_bytes('''\
    1494  <?xml version="1.0"?>
    1495  <foo>B</foo>
    1496  '''),
    1497                            bytes(memoryview(res)))
    1498
    1499
    1500 -def test_suite():
    1501      suite = unittest.TestSuite()
    1502      suite.addTests([unittest.makeSuite(ETreeXSLTTestCase)])
    1503      if is_python3:
    1504          suite.addTests([unittest.makeSuite(Py3XSLTTestCase)])
    1505      suite.addTests(
    1506          [make_doctest('../../../doc/extensions.txt')])
    1507      suite.addTests(
    1508          [make_doctest('../../../doc/xpathxslt.txt')])
    1509      return suite
    1510
    1511  if __name__ == '__main__':
    1512      print('to test use test.py %s' % __file__)
    1513