Package lxml :: Package tests :: Module test_relaxng

[hide private]
[frames] | no frames]

# Source Code for Module lxml.tests.test_relaxng

      1  # -*- coding: utf-8 -*-
      2
      3  """
      4  Test cases related to RelaxNG parsing and validation
      5  """
      6
      7  import unittest, 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  from common_imports import etree, BytesIO, _bytes, HelperTestCase, fileInTestDir
     14  from common_imports import doctest, make_doctest, skipif
     15
     16  try:
     17      import rnc2rng
     18  except ImportError:
     19      rnc2rng = None
     20
     21
     22 -class ETreeRelaxNGTestCase(HelperTestCase):
     23 -    def test_relaxng(self):
     24          tree_valid = self.parse('<a><b></b></a>')
     25          tree_invalid = self.parse('<a><c></c></a>')
     26          schema = self.parse('''\
     27  <element name="a" xmlns="http://relaxng.org/ns/structure/1.0">
     28    <zeroOrMore>
     29       <element name="b">
     30         <text />
     31       </element>
     32    </zeroOrMore>
     33  </element>
     34  ''')
     35          schema = etree.RelaxNG(schema)
     36          self.assertTrue(schema.validate(tree_valid))
     37          self.assertFalse(schema.error_log.filter_from_errors())
     38
     39          self.assertFalse(schema.validate(tree_invalid))
     40          self.assertTrue(schema.error_log.filter_from_errors())
     41
     42          self.assertTrue(schema.validate(tree_valid))             # repeat valid
     43          self.assertFalse(schema.error_log.filter_from_errors())  # repeat valid
     44
     45 -    def test_relaxng_stringio(self):
     46          tree_valid = self.parse('<a><b></b></a>')
     47          tree_invalid = self.parse('<a><c></c></a>')
     48          schema_file = BytesIO('''\
     49  <element name="a" xmlns="http://relaxng.org/ns/structure/1.0">
     50    <zeroOrMore>
     51       <element name="b">
     52         <text />
     53       </element>
     54    </zeroOrMore>
     55  </element>
     56  ''')
     57          schema = etree.RelaxNG(file=schema_file)
     58          self.assertTrue(schema.validate(tree_valid))
     59          self.assertFalse(schema.validate(tree_invalid))
     60
     61 -    def test_relaxng_elementtree_error(self):
     62          self.assertRaises(ValueError, etree.RelaxNG, etree.ElementTree())
     63
     64 -    def test_relaxng_error(self):
     65          tree_invalid = self.parse('<a><c></c></a>')
     66          schema = self.parse('''\
     67  <element name="a" xmlns="http://relaxng.org/ns/structure/1.0">
     68    <zeroOrMore>
     69       <element name="b">
     70         <text />
     71       </element>
     72    </zeroOrMore>
     73  </element>
     74  ''')
     75          schema = etree.RelaxNG(schema)
     76          self.assertFalse(schema.validate(tree_invalid))
     77          errors = schema.error_log
     78          self.assertTrue([log for log in errors
     79                           if log.level_name == "ERROR"])
     80          self.assertTrue([log for log in errors
     81                           if "not expect" in log.message])
     82
     83 -    def test_relaxng_generic_error(self):
     84          tree_invalid = self.parse('''\
     85          <test>
     86            <reference id="my-ref">This is my unique ref.</reference>
     87            <data ref="my-ref">Valid data</data>
     88            <data ref="myref">Invalid data</data>
     89          </test>
     90          ''')
     91          schema = self.parse('''\
     92          <grammar datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes"
     93                   xmlns="http://relaxng.org/ns/structure/1.0">
     94            <define name="by-ref">
     95              <data type="IDREF"/>
     96            </define>
     97            <start>
     98              <element name="test">
     99                <zeroOrMore>
    100                  <element name="reference">
    101                    <attribute name="id">
    102                      <data type="ID"/>
    103                    </attribute>
    104                    <text/>
    105                  </element>
    106                </zeroOrMore>
    107                <zeroOrMore>
    108                  <element name="data">
    109                    <attribute name="ref">
    110                      <data type="IDREF"/>
    111                    </attribute>
    112                    <text/>
    113                  </element>
    114                </zeroOrMore>
    115              </element>
    116            </start>
    117          </grammar>
    118          ''')
    119
    120          schema = etree.RelaxNG(schema)
    121          self.assertFalse(schema.validate(tree_invalid))
    122          errors = schema.error_log
    123          self.assertTrue(errors)
    124          self.assertTrue([log for log in errors if "IDREF" in log.message])
    125          self.assertTrue([log for log in errors if "myref" in log.message])
    126
    127 -    def test_relaxng_invalid_schema(self):
    128          schema = self.parse('''\
    129  <element name="a" xmlns="http://relaxng.org/ns/structure/1.0">
    130    <zeroOrMore>
    131       <element name="b" />
    132    </zeroOrMore>
    133  </element>
    134  ''')
    135          self.assertRaises(etree.RelaxNGParseError,
    136                            etree.RelaxNG, schema)
    137
    138 -    def test_relaxng_invalid_schema2(self):
    139          schema = self.parse('''\
    140  <grammar xmlns="http://relaxng.org/ns/structure/1.0" />
    141  ''')
    142          self.assertRaises(etree.RelaxNGParseError,
    143                            etree.RelaxNG, schema)
    144
    145 -    def test_relaxng_invalid_schema3(self):
    146          schema = self.parse('''\
    147  <grammar xmlns="http://relaxng.org/ns/structure/1.0">
    148    <define name="test">
    149      <element name="test"/>
    150    </define>
    151  </grammar>
    152  ''')
    153          self.assertRaises(etree.RelaxNGParseError,
    154                            etree.RelaxNG, schema)
    155
    156 -    def test_relaxng_invalid_schema4(self):
    157          # segfault
    158          schema = self.parse('''\
    159  <element name="a" xmlns="mynamespace" />
    160  ''')
    161          self.assertRaises(etree.RelaxNGParseError,
    162                            etree.RelaxNG, schema)
    163
    164 -    def test_relaxng_include(self):
    165          # this will only work if we access the file through path or
    166          # file object..
    167          f = open(fileInTestDir('test1.rng'), 'rb')
    168          try:
    169              schema = etree.RelaxNG(file=f)
    170          finally:
    171              f.close()
    172
    173 -    def test_relaxng_shortcut(self):
    174          tree_valid = self.parse('<a><b></b></a>')
    175          tree_invalid = self.parse('<a><c></c></a>')
    176          schema = self.parse('''\
    177  <element name="a" xmlns="http://relaxng.org/ns/structure/1.0">
    178    <zeroOrMore>
    179       <element name="b">
    180         <text />
    181       </element>
    182    </zeroOrMore>
    183  </element>
    184  ''')
    185          self.assertTrue(tree_valid.relaxng(schema))
    186          self.assertFalse(tree_invalid.relaxng(schema))
    187
    188 -    def test_multiple_elementrees(self):
    189          tree = self.parse('<a><b>B</b><c>C</c></a>')
    190          schema = etree.RelaxNG( self.parse('''\
    191  <element name="a" xmlns="http://relaxng.org/ns/structure/1.0">
    192    <element name="b">
    193      <text />
    194    </element>
    195    <element name="c">
    196      <text />
    197    </element>
    198  </element>
    199  ''') )
    200          self.assertTrue(schema.validate(tree))
    201          self.assertFalse(schema.error_log.filter_from_errors())
    202
    203          self.assertTrue(schema.validate(tree))                   # repeat valid
    204          self.assertFalse(schema.error_log.filter_from_errors())  # repeat valid
    205
    206          schema = etree.RelaxNG( self.parse('''\
    207  <element name="b" xmlns="http://relaxng.org/ns/structure/1.0">
    208    <text />
    209  </element>
    210  ''') )
    211          c_tree = etree.ElementTree(tree.getroot()[1])
    212          self.assertEqual(self._rootstring(c_tree), _bytes('<c>C</c>'))
    213          self.assertFalse(schema.validate(c_tree))
    214          self.assertTrue(schema.error_log.filter_from_errors())
    215
    216          b_tree = etree.ElementTree(tree.getroot()[0])
    217          self.assertEqual(self._rootstring(b_tree), _bytes('<b>B</b>'))
    218          self.assertTrue(schema.validate(b_tree))
    219          self.assertFalse(schema.error_log.filter_from_errors())
    220
    221 -class RelaxNGCompactTestCase(HelperTestCase):
    222
    223      pytestmark = skipif('rnc2rng is None')
    224
    225 -    def test_relaxng_compact(self):
    226          tree_valid = self.parse('<a><b>B</b><c>C</c></a>')
    227          tree_invalid = self.parse('<a><b></b></a>')
    228          schema = etree.RelaxNG(file=fileInTestDir('test.rnc'))
    229          self.assertTrue(schema.validate(tree_valid))
    230          self.assertFalse(schema.validate(tree_invalid))
    231
    232 -    def test_relaxng_compact_file_obj(self):
    233          f = open(fileInTestDir('test.rnc'), 'rb')
    234          try:
    235              schema = etree.RelaxNG(file=f)
    236          finally:
    237              f.close()
    238
    239 -    def test_relaxng_compact_str(self):
    240          tree_valid = self.parse('<a><b>B</b></a>')
    241          rnc_str = 'element a { element b { "B" } }'
    242          schema = etree.RelaxNG.from_rnc_string(rnc_str)
    243          self.assertTrue(schema.validate(tree_valid))
    244
    245
    246 -def test_suite():
    247      suite = unittest.TestSuite()
    248      suite.addTests([unittest.makeSuite(ETreeRelaxNGTestCase)])
    249      suite.addTests(
    250          [make_doctest('../../../doc/validation.txt')])
    251      if rnc2rng is not None:
    252          suite.addTests([unittest.makeSuite(RelaxNGCompactTestCase)])
    253      return suite
    254
    255  if __name__ == '__main__':
    256      print('to test use test.py %s' % __file__)
    257