Package lxml :: Package tests :: Module test_xmlschema

[hide private]
[frames] | no frames]

# Source Code for Module lxml.tests.test_xmlschema

      1  # -*- coding: utf-8 -*-
      2
      3  """
      4  Test cases related to XML Schema 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, HelperTestCase, fileInTestDir
     14  from common_imports import doctest, make_doctest
     15
     16 -class ETreeXMLSchemaTestCase(HelperTestCase):
     17 -    def test_xmlschema(self):
     18          tree_valid = self.parse('<a><b></b></a>')
     19          tree_invalid = self.parse('<a><c></c></a>')
     20          schema = self.parse('''
     21  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
     22    <xsd:element name="a" type="AType"/>
     23    <xsd:complexType name="AType">
     24      <xsd:sequence>
     25        <xsd:element name="b" type="xsd:string" />
     26      </xsd:sequence>
     27    </xsd:complexType>
     28  </xsd:schema>
     29  ''')
     30          schema = etree.XMLSchema(schema)
     31          self.assert_(schema.validate(tree_valid))
     32          self.assert_(not schema.validate(tree_invalid))
     33
     34 -    def test_xmlschema_parse(self):
     35          schema = self.parse('''
     36  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
     37    <xsd:element name="a" type="AType"/>
     38    <xsd:complexType name="AType">
     39      <xsd:sequence>
     40        <xsd:element name="b" type="xsd:string" />
     41      </xsd:sequence>
     42    </xsd:complexType>
     43  </xsd:schema>
     44  ''')
     45          schema = etree.XMLSchema(schema)
     46          parser = etree.XMLParser(schema=schema)
     47
     48          tree_valid = self.parse('<a><b></b></a>', parser=parser)
     49          self.assertEquals('a', tree_valid.getroot().tag)
     50
     51          self.assertRaises(etree.XMLSyntaxError,
     52                            self.parse, '<a><c></c></a>', parser=parser)
     53
     54 -    def test_xmlschema_stringio(self):
     55          schema_file = BytesIO('''
     56  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
     57    <xsd:element name="a" type="AType"/>
     58    <xsd:complexType name="AType">
     59      <xsd:sequence>
     60        <xsd:element name="b" type="xsd:string" />
     61      </xsd:sequence>
     62    </xsd:complexType>
     63  </xsd:schema>
     64  ''')
     65          schema = etree.XMLSchema(file=schema_file)
     66          parser = etree.XMLParser(schema=schema)
     67
     68          tree_valid = self.parse('<a><b></b></a>', parser=parser)
     69          self.assertEquals('a', tree_valid.getroot().tag)
     70
     71          self.assertRaises(etree.XMLSyntaxError,
     72                            self.parse, '<a><c></c></a>', parser=parser)
     73
     74 -    def test_xmlschema_iterparse(self):
     75          schema = self.parse('''
     76  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
     77    <xsd:element name="a" type="AType"/>
     78    <xsd:complexType name="AType">
     79      <xsd:sequence>
     80        <xsd:element name="b" type="xsd:string" />
     81      </xsd:sequence>
     82    </xsd:complexType>
     83  </xsd:schema>
     84  ''')
     85          schema = etree.XMLSchema(schema)
     86          xml = BytesIO('<a><b></b></a>')
     87          events = [ (event, el.tag)
     88                     for (event, el) in etree.iterparse(xml, schema=schema) ]
     89
     90          self.assertEquals([('end', 'b'), ('end', 'a')],
     91                            events)
     92
     93 -    def test_xmlschema_iterparse_fail(self):
     94          schema = self.parse('''
     95  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
     96    <xsd:element name="a" type="AType"/>
     97    <xsd:complexType name="AType">
     98      <xsd:sequence>
     99        <xsd:element name="b" type="xsd:string" />
    100      </xsd:sequence>
    101    </xsd:complexType>
    102  </xsd:schema>
    103  ''')
    104          schema = etree.XMLSchema(schema)
    105          self.assertRaises(
    106              etree.XMLSyntaxError,
    107              list, etree.iterparse(BytesIO('<a><c></c></a>'), schema=schema))
    108
    109 -    def test_xmlschema_elementtree_error(self):
    110          self.assertRaises(ValueError, etree.XMLSchema, etree.ElementTree())
    111
    112 -    def test_xmlschema_invalid_schema1(self):
    113          schema = self.parse('''\
    114  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    115    <element name="a" type="AType"/>
    116    <xsd:complexType name="AType">
    117      <xsd:sequence>
    118        <xsd:element name="b" type="xsd:string" />
    119      </xsd:sequence>
    120    </xsd:complexType>
    121  </xsd:schema>
    122  ''')
    123          self.assertRaises(etree.XMLSchemaParseError,
    124                            etree.XMLSchema, schema)
    125
    126 -    def test_xmlschema_invalid_schema2(self):
    127          schema = self.parse('<test/>')
    128          self.assertRaises(etree.XMLSchemaParseError,
    129                            etree.XMLSchema, schema)
    130
    131 -    def test_xmlschema_file(self):
    132          # this will only work if we access the file through path or
    133          # file object..
    134          f = open(fileInTestDir('test.xsd'), 'rb')
    135          schema = etree.XMLSchema(file=f)
    136          tree_valid = self.parse('<a><b></b></a>')
    137          self.assert_(schema.validate(tree_valid))
    138
    139 -    def test_xmlschema_shortcut(self):
    140          tree_valid = self.parse('<a><b></b></a>')
    141          tree_invalid = self.parse('<a><c></c></a>')
    142          schema = self.parse('''\
    143  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    144    <xsd:element name="a" type="AType"/>
    145    <xsd:complexType name="AType">
    146      <xsd:sequence>
    147        <xsd:element name="b" type="xsd:string" />
    148      </xsd:sequence>
    149    </xsd:complexType>
    150  </xsd:schema>
    151  ''')
    152          self.assert_(tree_valid.xmlschema(schema))
    153          self.assert_(not tree_invalid.xmlschema(schema))
    154
    155      #
    156      # schema + resolvers tests&data:
    157      #
    158
    159      resolver_schema_int = BytesIO("""\
    160  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    161      xmlns:etype="http://codespeak.net/lxml/test/external"
    162      targetNamespace="http://codespeak.net/lxml/test/internal">
    163          <xsd:import namespace="http://codespeak.net/lxml/test/external" schemaLocation="XXX.xsd" />
    164          <xsd:element name="a" type="etype:AType"/>
    165  </xsd:schema>""")
    166
    167      resolver_schema_int2 = BytesIO("""\
    168  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    169      xmlns:etype="http://codespeak.net/lxml/test/external"
    170      targetNamespace="http://codespeak.net/lxml/test/internal">
    171          <xsd:import namespace="http://codespeak.net/lxml/test/external" schemaLocation="YYY.xsd" />
    172          <xsd:element name="a" type="etype:AType"/>
    173  </xsd:schema>""")
    174
    175      resolver_schema_ext = """\
    176  <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    177      targetNamespace="http://codespeak.net/lxml/test/external">
    178      <xsd:complexType name="AType">
    179        <xsd:sequence><xsd:element name="b" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /></xsd:sequence>
    180      </xsd:complexType>
    181  </xsd:schema>"""
    182
    183 -    class simple_resolver(etree.Resolver):
    184 -        def __init__(self, schema):
    185              self.schema = schema
    186
    187 -        def resolve(self, url, id, context):
    188              assert url == 'XXX.xsd'
    189              return self.resolve_string(self.schema, context)
    190
    191 -    def test_xmlschema_resolvers(self):
    192          """Test that resolvers work with schema."""
    193          parser = etree.XMLParser()
    194          parser.resolvers.add(self.simple_resolver(self.resolver_schema_ext))
    195          schema_doc = etree.parse(self.resolver_schema_int, parser = parser)
    196          schema = etree.XMLSchema(schema_doc)
    197
    198 -    def test_xmlschema_resolvers_root(self):
    199          """Test that the default resolver will get called if there's no
    200          specific parser resolver."""
    201          root_resolver = self.simple_resolver(self.resolver_schema_ext)
    202          etree.get_default_parser().resolvers.add(root_resolver)
    203          schema_doc = etree.parse(self.resolver_schema_int)
    204          schema = etree.XMLSchema(schema_doc)
    205          etree.get_default_parser().resolvers.remove(root_resolver)
    206
    207 -    def test_xmlschema_resolvers_noroot(self):
    208          """Test that the default resolver will not get called when a more
    209          specific resolver is registered."""
    210
    211          class res_root(etree.Resolver):
    212              def resolve(self, url, id, context):
    213                  assert False
    214                  return None
    215
    216          root_resolver = res_root()
    217          etree.get_default_parser().resolvers.add(root_resolver)
    218
    219          parser = etree.XMLParser()
    220          parser.resolvers.add(self.simple_resolver(self.resolver_schema_ext))
    221
    222          schema_doc = etree.parse(self.resolver_schema_int, parser = parser)
    223          schema = etree.XMLSchema(schema_doc)
    224          etree.get_default_parser().resolvers.remove(root_resolver)
    225
    226 -    def test_xmlschema_nested_resolvers(self):
    227          """Test that resolvers work in a nested fashion."""
    228
    229          resolver_schema = self.resolver_schema_ext
    230
    231          class res_nested(etree.Resolver):
    232              def __init__(self, ext_schema):
    233                  self.ext_schema = ext_schema
    234
    235              def resolve(self, url, id, context):
    236                  assert url == 'YYY.xsd'
    237                  return self.resolve_string(self.ext_schema, context)
    238
    239          class res(etree.Resolver):
    240              def __init__(self, ext_schema_1, ext_schema_2):
    241                  self.ext_schema_1 = ext_schema_1
    242                  self.ext_schema_2 = ext_schema_2
    243
    244              def resolve(self, url, id, context):
    245                  assert url == 'XXX.xsd'
    246
    247                  new_parser = etree.XMLParser()
    248                  new_parser.resolvers.add(res_nested(self.ext_schema_2))
    249                  new_schema_doc = etree.parse(self.ext_schema_1, parser = new_parser)
    250                  new_schema = etree.XMLSchema(new_schema_doc)
    251
    252                  return self.resolve_string(resolver_schema, context)
    253
    254          parser = etree.XMLParser()
    255          parser.resolvers.add(res(self.resolver_schema_int2, self.resolver_schema_ext))
    256          schema_doc = etree.parse(self.resolver_schema_int, parser = parser)
    257          schema = etree.XMLSchema(schema_doc)
    258
    259 -def test_suite():
    260      suite = unittest.TestSuite()
    261      suite.addTests([unittest.makeSuite(ETreeXMLSchemaTestCase)])
    262      suite.addTests(
    263          [make_doctest('../../../doc/validation.txt')])
    264      return suite
    265
    266  if __name__ == '__main__':
    267      print('to test use test.py %s' % __file__)
    268