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, make_doctest, skipIf 
 15  from common_imports import fileInTestDir, fileUrlInTestDir 
16 17 -class ETreeDtdTestCase(HelperTestCase):
18 - def test_dtd(self):
19 pass
20
21 - def test_dtd_file(self):
22 parse = etree.parse 23 tree = parse(fileInTestDir("test.xml")) 24 root = tree.getroot() 25 26 dtd = etree.DTD(fileInTestDir("test.dtd")) 27 self.assertTrue(dtd.validate(root))
28
29 - def test_dtd_stringio(self):
30 root = etree.XML(_bytes("<b/>")) 31 dtd = etree.DTD(BytesIO("<!ELEMENT b EMPTY>")) 32 self.assertTrue(dtd.validate(root))
33
34 - def test_dtd_parse_invalid(self):
35 fromstring = etree.fromstring 36 parser = etree.XMLParser(dtd_validation=True) 37 xml = _bytes('<!DOCTYPE b SYSTEM "%s"><b><a/></b>' % fileInTestDir("test.dtd")) 38 self.assertRaises(etree.XMLSyntaxError, 39 fromstring, xml, parser=parser)
40
42 fromstring = etree.fromstring 43 dtd_filename = fileInTestDir("__nosuch.dtd") 44 parser = etree.XMLParser(dtd_validation=True) 45 xml = _bytes('<!DOCTYPE b SYSTEM "%s"><b><a/></b>' % dtd_filename) 46 self.assertRaises(etree.XMLSyntaxError, 47 fromstring, xml, parser=parser) 48 errors = None 49 try: 50 fromstring(xml, parser=parser) 51 except etree.XMLSyntaxError: 52 e = sys.exc_info()[1] 53 self.assertTrue(e.error_log) 54 self.assertTrue(parser.error_log) 55 errors = [entry.message for entry in e.error_log 56 if dtd_filename in entry.message] 57 self.assertTrue(errors)
58
59 - def test_dtd_parse_valid(self):
60 parser = etree.XMLParser(dtd_validation=True) 61 xml = '<!DOCTYPE a SYSTEM "%s"><a><b/></a>' % fileInTestDir("test.dtd") 62 root = etree.fromstring(xml, parser=parser)
63
65 parser = etree.XMLParser(dtd_validation=True) 66 xml = ('<!DOCTYPE a SYSTEM "%s"><a><b/></a>' % 67 fileUrlInTestDir("test.dtd")) 68 root = etree.fromstring(xml, parser=parser)
69
71 parser = etree.XMLParser(dtd_validation=True) 72 xml = '<!DOCTYPE a SYSTEM "test.dtd"><a><b/></a>' 73 root = etree.fromstring( 74 xml, parser=parser, base_url=fileInTestDir("test.xml"))
75
77 parser = etree.XMLParser(dtd_validation=True) 78 xml = '<!DOCTYPE a SYSTEM "test.dtd"><a><b/></a>' 79 root = etree.fromstring( 80 xml, parser=parser, base_url=fileUrlInTestDir("test.xml"))
81
82 - def test_dtd_invalid(self):
83 root = etree.XML("<b><a/></b>") 84 dtd = etree.DTD(BytesIO("<!ELEMENT b EMPTY>")) 85 self.assertRaises(etree.DocumentInvalid, dtd.assertValid, root)
86
87 - def test_dtd_assertValid(self):
88 root = etree.XML("<b><a/></b>") 89 dtd = etree.DTD(BytesIO("<!ELEMENT b (a)><!ELEMENT a EMPTY>")) 90 dtd.assertValid(root)
91
92 - def test_dtd_internal(self):
93 root = etree.XML(_bytes(''' 94 <!DOCTYPE b SYSTEM "none" [ 95 <!ELEMENT b (a)> 96 <!ELEMENT a EMPTY> 97 ]> 98 <b><a/></b> 99 ''')) 100 dtd = etree.ElementTree(root).docinfo.internalDTD 101 self.assertTrue(dtd) 102 dtd.assertValid(root)
103
105 root = etree.XML(_bytes(''' 106 <!DOCTYPE b SYSTEM "none" [ 107 <!ELEMENT b (a)> 108 <!ELEMENT a (c)> 109 <!ELEMENT c EMPTY> 110 ]> 111 <b><a/></b> 112 ''')) 113 dtd = etree.ElementTree(root).docinfo.internalDTD 114 self.assertTrue(dtd) 115 self.assertFalse(dtd.validate(root))
116
117 - def test_dtd_api_internal(self):
118 root = etree.XML(_bytes(''' 119 <!DOCTYPE b SYSTEM "none" [ 120 <!ATTLIST a 121 attr1 (x | y | z) "z" 122 attr2 CDATA #FIXED "X" 123 > 124 <!ELEMENT b (a)> 125 <!ELEMENT a EMPTY> 126 ]> 127 <b><a/></b> 128 ''')) 129 dtd = etree.ElementTree(root).docinfo.internalDTD 130 self.assertTrue(dtd) 131 dtd.assertValid(root) 132 133 seen = [] 134 for el in dtd.iterelements(): 135 if el.name == 'a': 136 self.assertEqual(2, len(el.attributes())) 137 for attr in el.iterattributes(): 138 if attr.name == 'attr1': 139 self.assertEqual('enumeration', attr.type) 140 self.assertEqual('none', attr.default) 141 self.assertEqual('z', attr.default_value) 142 values = attr.values() 143 values.sort() 144 self.assertEqual(['x', 'y', 'z'], values) 145 else: 146 self.assertEqual('attr2', attr.name) 147 self.assertEqual('cdata', attr.type) 148 self.assertEqual('fixed', attr.default) 149 self.assertEqual('X', attr.default_value) 150 else: 151 self.assertEqual('b', el.name) 152 self.assertEqual(0, len(el.attributes())) 153 seen.append(el.name) 154 seen.sort() 155 self.assertEqual(['a', 'b'], seen) 156 self.assertEqual(2, len(dtd.elements()))
157
158 - def test_internal_dtds(self):
159 for el_count in range(2, 5): 160 for attr_count in range(4): 161 root = etree.XML(_bytes(''' 162 <!DOCTYPE el0 SYSTEM "none" [ 163 ''' + ''.join([''' 164 <!ATTLIST el%d 165 attr%d (x | y | z) "z" 166 > 167 ''' % (e, a) for a in range(attr_count) for e in range(el_count) 168 ]) + ''.join([''' 169 <!ELEMENT el%d EMPTY> 170 ''' % e for e in range(1, el_count) 171 ]) + ''' 172 ''' + '<!ELEMENT el0 (%s)>' % '|'.join([ 173 'el%d' % e for e in range(1, el_count)]) + ''' 174 ]> 175 <el0><el1 %s /></el0> 176 ''' % ' '.join(['attr%d="x"' % a for a in range(attr_count)]))) 177 dtd = etree.ElementTree(root).docinfo.internalDTD 178 self.assertTrue(dtd) 179 dtd.assertValid(root) 180 181 e = -1 182 for e, el in enumerate(dtd.iterelements()): 183 self.assertEqual(attr_count, len(el.attributes())) 184 a = -1 185 for a, attr in enumerate(el.iterattributes()): 186 self.assertEqual('enumeration', attr.type) 187 self.assertEqual('none', attr.default) 188 self.assertEqual('z', attr.default_value) 189 values = sorted(attr.values()) 190 self.assertEqual(['x', 'y', 'z'], values) 191 self.assertEqual(attr_count - 1, a) 192 self.assertEqual(el_count - 1, e) 193 self.assertEqual(el_count, len(dtd.elements()))
194
195 - def test_dtd_broken(self):
196 self.assertRaises(etree.DTDParseError, etree.DTD, 197 BytesIO("<!ELEMENT b HONKEY>"))
198
199 - def test_parse_file_dtd(self):
200 parser = etree.XMLParser(attribute_defaults=True) 201 202 tree = etree.parse(fileInTestDir('test.xml'), parser) 203 root = tree.getroot() 204 205 self.assertEqual( 206 "valueA", 207 root.get("default")) 208 self.assertEqual( 209 "valueB", 210 root[0].get("default"))
211 212 @skipIf(etree.LIBXML_VERSION == (2, 9, 0), 213 "DTD loading is broken for incremental parsing in libxml2 2.9.0")
215 iterparse = etree.iterparse 216 iterator = iterparse(fileInTestDir("test.xml"), events=('start',), 217 attribute_defaults=True) 218 attributes = [ element.get("default") 219 for event, element in iterator ] 220 self.assertEqual( 221 ["valueA", "valueB"], 222 attributes)
223 224 @skipIf(etree.LIBXML_VERSION == (2, 9, 0), 225 "DTD loading is broken for incremental parsing in libxml2 2.9.0")
227 iterparse = etree.iterparse 228 iterator = iterparse(fileInTestDir("test.xml"), events=('end',), 229 attribute_defaults=True) 230 attributes = [ element.get("default") 231 for event, element in iterator ] 232 self.assertEqual( 233 ["valueB", "valueA"], 234 attributes)
235
236 - def test_dtd_attrs(self):
237 dtd = etree.DTD(fileInTestDir("test.dtd")) 238 239 # Test DTD.system_url attribute 240 self.assertTrue(dtd.system_url.endswith("test.dtd")) 241 242 # Test elements and their attributes 243 a = dtd.elements()[0] 244 self.assertEqual(a.name, "a") 245 self.assertEqual(a.type, "element") 246 self.assertEqual(a.content.name, "b") 247 self.assertEqual(a.content.type, "element") 248 self.assertEqual(a.content.occur, "once") 249 250 aattr = a.attributes()[0] 251 self.assertEqual(aattr.name, "default") 252 self.assertEqual(aattr.type, "enumeration") 253 self.assertEqual(aattr.values(), ["valueA", "valueB"]) 254 self.assertEqual(aattr.default_value, "valueA") 255 256 b = dtd.elements()[1] 257 self.assertEqual(b.name, "b") 258 self.assertEqual(b.type, "empty") 259 self.assertEqual(b.content, None) 260 261 # Test entities and their attributes 262 c = dtd.entities()[0] 263 self.assertEqual(c.name, "c") 264 self.assertEqual(c.orig, "&#42;") 265 self.assertEqual(c.content, "*") 266 267 # Test DTD.name attribute 268 root = etree.XML(_bytes(''' 269 <!DOCTYPE a SYSTEM "none" [ 270 <!ELEMENT a EMPTY> 271 ]> 272 <a/> 273 ''')) 274 dtd = etree.ElementTree(root).docinfo.internalDTD 275 self.assertEqual(dtd.name, "a") 276 277 # Test DTD.name and DTD.systemID attributes 278 parser = etree.XMLParser(dtd_validation=True) 279 xml = '<!DOCTYPE a SYSTEM "test.dtd"><a><b/></a>' 280 root = etree.fromstring(xml, parser=parser, 281 base_url=fileInTestDir("test.xml")) 282 283 dtd = root.getroottree().docinfo.internalDTD 284 self.assertEqual(dtd.name, "a") 285 self.assertEqual(dtd.system_url, "test.dtd")
286
287 288 -def test_suite():
289 suite = unittest.TestSuite() 290 suite.addTests([unittest.makeSuite(ETreeDtdTestCase)]) 291 suite.addTests( 292 [make_doctest('../../../doc/validation.txt')]) 293 return suite
294 295 if __name__ == '__main__': 296 print('to test use test.py %s' % __file__) 297