Package lxml :: Package tests :: Module test_dtd

[hide private]
[frames] | no frames]

# Source Code for Module lxml.tests.test_dtd

      1  # -*- coding: utf-8 -*-
      2
      3  """
      4  Test cases related to DTD 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, StringIO, BytesIO, _bytes, doctest
     14  from common_imports import HelperTestCase, fileInTestDir, make_doctest, skipIf
     15
     16 -class ETreeDtdTestCase(HelperTestCase):
     17 -    def test_dtd(self):
     18          pass
     19
     20 -    def test_dtd_file(self):
     21          parse = etree.parse
     22          tree = parse(fileInTestDir("test.xml"))
     23          root = tree.getroot()
     24
     25          dtd = etree.DTD(fileInTestDir("test.dtd"))
     26          self.assertTrue(dtd.validate(root))
     27
     28 -    def test_dtd_stringio(self):
     29          root = etree.XML(_bytes("<b/>"))
     30          dtd = etree.DTD(BytesIO("<!ELEMENT b EMPTY>"))
     31          self.assertTrue(dtd.validate(root))
     32
     33 -    def test_dtd_parse_invalid(self):
     34          fromstring = etree.fromstring
     35          parser = etree.XMLParser(dtd_validation=True)
     36          xml = _bytes('<!DOCTYPE b SYSTEM "%s"><b><a/></b>' % fileInTestDir("test.dtd"))
     37          self.assertRaises(etree.XMLSyntaxError,
     38                            fromstring, xml, parser=parser)
     39
     40 -    def test_dtd_parse_file_not_found(self):
     41          fromstring = etree.fromstring
     42          dtd_filename = fileInTestDir("__nosuch.dtd")
     43          parser = etree.XMLParser(dtd_validation=True)
     44          xml = _bytes('<!DOCTYPE b SYSTEM "%s"><b><a/></b>' % dtd_filename)
     45          self.assertRaises(etree.XMLSyntaxError,
     46                            fromstring, xml, parser=parser)
     47          errors = None
     48          try:
     49              fromstring(xml, parser=parser)
     50          except etree.XMLSyntaxError:
     51              e = sys.exc_info()[1]
     52              errors = [ entry.message for entry in e.error_log
     53                         if dtd_filename in entry.message ]
     54          self.assertTrue(errors)
     55
     56 -    def test_dtd_parse_valid(self):
     57          parser = etree.XMLParser(dtd_validation=True)
     58          xml = '<!DOCTYPE a SYSTEM "%s"><a><b/></a>' % fileInTestDir("test.dtd")
     59          root = etree.fromstring(xml, parser=parser)
     60
     61 -    def test_dtd_parse_valid_relative(self):
     62          parser = etree.XMLParser(dtd_validation=True)
     63          xml = '<!DOCTYPE a SYSTEM "test.dtd"><a><b/></a>'
     64          root = etree.fromstring(xml, parser=parser,
     65                                  base_url=fileInTestDir("test.xml"))
     66
     67 -    def test_dtd_invalid(self):
     68          root = etree.XML("<b><a/></b>")
     69          dtd = etree.DTD(BytesIO("<!ELEMENT b EMPTY>"))
     70          self.assertRaises(etree.DocumentInvalid, dtd.assertValid, root)
     71
     72 -    def test_dtd_assertValid(self):
     73          root = etree.XML("<b><a/></b>")
     74          dtd = etree.DTD(BytesIO("<!ELEMENT b (a)><!ELEMENT a EMPTY>"))
     75          dtd.assertValid(root)
     76
     77 -    def test_dtd_internal(self):
     78          root = etree.XML(_bytes('''
     79          <!DOCTYPE b SYSTEM "none" [
     80          <!ELEMENT b (a)>
     81          <!ELEMENT a EMPTY>
     82          ]>
     83          <b><a/></b>
     84          '''))
     85          dtd = etree.ElementTree(root).docinfo.internalDTD
     86          self.assertTrue(dtd)
     87          dtd.assertValid(root)
     88
     89 -    def test_dtd_internal_invalid(self):
     90          root = etree.XML(_bytes('''
     91          <!DOCTYPE b SYSTEM "none" [
     92          <!ELEMENT b (a)>
     93          <!ELEMENT a (c)>
     94          <!ELEMENT c EMPTY>
     95          ]>
     96          <b><a/></b>
     97          '''))
     98          dtd = etree.ElementTree(root).docinfo.internalDTD
     99          self.assertTrue(dtd)
    100          self.assertFalse(dtd.validate(root))
    101
    102 -    def test_dtd_broken(self):
    103          self.assertRaises(etree.DTDParseError, etree.DTD,
    104                            BytesIO("<!ELEMENT b HONKEY>"))
    105
    106 -    def test_parse_file_dtd(self):
    107          parser = etree.XMLParser(attribute_defaults=True)
    108
    109          tree = etree.parse(fileInTestDir('test.xml'), parser)
    110          root = tree.getroot()
    111
    112          self.assertEqual(
    113              "valueA",
    114              root.get("default"))
    115          self.assertEqual(
    116              "valueB",
    117              root[0].get("default"))
    118
    119      @skipIf(etree.LIBXML_VERSION == (2,9,0),
    120              "DTD loading is broken for incremental parsing in libxml2 2.9.0")
    121 -    def test_iterparse_file_dtd(self):
    122          iterparse = etree.iterparse
    123          iterator = iterparse(fileInTestDir("test.xml"), events=("start",),
    124                               attribute_defaults=True)
    125          attributes = [ element.get("default")
    126                         for event, element in iterator ]
    127          self.assertEqual(
    128              ["valueA", "valueB"],
    129              attributes)
    130
    131 -    def test_dtd_attrs(self):
    132          dtd = etree.DTD(fileInTestDir("test.dtd"))
    133
    134          # Test DTD.system_url attribute
    135          self.assertTrue(dtd.system_url.endswith("test.dtd"))
    136
    137          # Test elements and their attributes
    138          a = dtd.elements()[0]
    139          self.assertEqual(a.name, "a")
    140          self.assertEqual(a.type, "element")
    141          self.assertEqual(a.content.name, "b")
    142          self.assertEqual(a.content.type, "element")
    143          self.assertEqual(a.content.occur, "once")
    144
    145          aattr = a.attributes()[0]
    146          self.assertEqual(aattr.name, "default")
    147          self.assertEqual(aattr.type, "enumeration")
    148          self.assertEqual(aattr.values(), ["valueA", "valueB"])
    149          self.assertEqual(aattr.default_value, "valueA")
    150
    151          b = dtd.elements()[1]
    152          self.assertEqual(b.name, "b")
    153          self.assertEqual(b.type, "empty")
    154          self.assertEqual(b.content, None)
    155
    156          # Test entities and their attributes
    157          c = dtd.entities()[0]
    158          self.assertEqual(c.name, "c")
    159          self.assertEqual(c.orig, "&#42;")
    160          self.assertEqual(c.content, "*")
    161
    162          # Test DTD.name attribute
    163          root = etree.XML(_bytes('''
    164          <!DOCTYPE a SYSTEM "none" [
    165          <!ELEMENT a EMPTY>
    166          ]>
    167          <a/>
    168          '''))
    169          dtd = etree.ElementTree(root).docinfo.internalDTD
    170          self.assertEqual(dtd.name, "a")
    171
    172          # Test DTD.name and DTD.systemID attributes
    173          parser = etree.XMLParser(dtd_validation=True)
    174          xml = '<!DOCTYPE a SYSTEM "test.dtd"><a><b/></a>'
    175          root = etree.fromstring(xml, parser=parser,
    176                                  base_url=fileInTestDir("test.xml"))
    177
    178          dtd = root.getroottree().docinfo.internalDTD
    179          self.assertEqual(dtd.name, "a")
    180          self.assertEqual(dtd.system_url, "test.dtd")
    181
    182
    183 -def test_suite():
    184      suite = unittest.TestSuite()
    185      suite.addTests([unittest.makeSuite(ETreeDtdTestCase)])
    186      suite.addTests(
    187          [make_doctest('../../../doc/validation.txt')])
    188      return suite
    189
    190  if __name__ == '__main__':
    191      print('to test use test.py %s' % __file__)
    192