1
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)
12
13 from common_imports import etree, BytesIO, HelperTestCase, fileInTestDir
14 from common_imports import doctest, make_doctest
15
16
19 tree_valid = self.parse('<a><b></b></a>')
20 tree_invalid = self.parse('<a><c></c></a>')
21 schema = self.parse('''
22 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
23 <xsd:element name="a" type="AType"/>
24 <xsd:complexType name="AType">
25 <xsd:sequence>
26 <xsd:element name="b" type="xsd:string" />
27 </xsd:sequence>
28 </xsd:complexType>
29 </xsd:schema>
30 ''')
31 schema = etree.XMLSchema(schema)
32 self.assertTrue(schema.validate(tree_valid))
33 self.assertFalse(schema.validate(tree_invalid))
34 self.assertTrue(schema.validate(tree_valid))
35 self.assertFalse(schema.validate(tree_invalid))
36
66
68 schema = self.parse('''
69 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
70 <xsd:element name="a" type="AType"/>
71 <xsd:complexType name="AType">
72 <xsd:sequence minOccurs="4" maxOccurs="4">
73 <xsd:element name="b" type="BType" />
74 </xsd:sequence>
75 </xsd:complexType>
76 <xsd:complexType name="BType">
77 <xsd:attribute name="hardy" type="xsd:string" default="hey" />
78 </xsd:complexType>
79 </xsd:schema>
80 ''')
81 schema = etree.XMLSchema(schema, attribute_defaults=True)
82
83 tree = self.parse('<a><b hardy="ho"/><b/><b hardy="ho"/><b/></a>')
84
85 root = tree.getroot()
86 self.assertEqual('ho', root[0].get('hardy'))
87 self.assertEqual(None, root[1].get('hardy'))
88 self.assertEqual('ho', root[2].get('hardy'))
89 self.assertEqual(None, root[3].get('hardy'))
90
91 self.assertTrue(schema(tree))
92
93 root = tree.getroot()
94 self.assertEqual('ho', root[0].get('hardy'))
95 self.assertEqual('hey', root[1].get('hardy'))
96 self.assertEqual('ho', root[2].get('hardy'))
97 self.assertEqual('hey', root[3].get('hardy'))
98
100 schema = self.parse('''
101 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
102 <xsd:element name="a" type="AType"/>
103 <xsd:complexType name="AType">
104 <xsd:sequence>
105 <xsd:element name="b" type="xsd:string" />
106 </xsd:sequence>
107 </xsd:complexType>
108 </xsd:schema>
109 ''')
110 schema = etree.XMLSchema(schema)
111 parser = etree.XMLParser(schema=schema)
112
113 tree_valid = self.parse('<a><b></b></a>', parser=parser)
114 self.assertEqual('a', tree_valid.getroot().tag)
115
116 self.assertRaises(etree.XMLSyntaxError,
117 self.parse, '<a><c></c></a>', parser=parser)
118
120
121 schema = self.parse('''
122 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
123 <xsd:element name="a" type="AType"/>
124 <xsd:complexType name="AType">
125 <xsd:sequence minOccurs="4" maxOccurs="4">
126 <xsd:element name="b" type="BType" />
127 </xsd:sequence>
128 </xsd:complexType>
129 <xsd:complexType name="BType">
130 <xsd:attribute name="hardy" type="xsd:string" default="hey" />
131 </xsd:complexType>
132 </xsd:schema>
133 ''')
134 schema = etree.XMLSchema(schema)
135 parser = etree.XMLParser(schema=schema, attribute_defaults=True)
136
137 tree_valid = self.parse('<a><b hardy="ho"/><b/><b hardy="ho"/><b/></a>',
138 parser=parser)
139 root = tree_valid.getroot()
140 self.assertEqual('ho', root[0].get('hardy'))
141 self.assertEqual('hey', root[1].get('hardy'))
142 self.assertEqual('ho', root[2].get('hardy'))
143 self.assertEqual('hey', root[3].get('hardy'))
144
146
147 schema = self.parse('''
148 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
149 <xsd:element name="a" type="AType"/>
150 <xsd:complexType name="AType">
151 <xsd:sequence minOccurs="4" maxOccurs="4">
152 <xsd:element name="b" type="BType" />
153 </xsd:sequence>
154 </xsd:complexType>
155 <xsd:complexType name="BType">
156 <xsd:attribute name="hardy" type="xsd:string" default="hey" />
157 </xsd:complexType>
158 </xsd:schema>
159 ''')
160 schema = etree.XMLSchema(schema, attribute_defaults=True)
161 parser = etree.XMLParser(schema=schema)
162
163 tree_valid = self.parse('<a><b hardy="ho"/><b/><b hardy="ho"/><b/></a>',
164 parser=parser)
165 root = tree_valid.getroot()
166 self.assertEqual('ho', root[0].get('hardy'))
167 self.assertEqual('hey', root[1].get('hardy'))
168 self.assertEqual('ho', root[2].get('hardy'))
169 self.assertEqual('hey', root[3].get('hardy'))
170
172
173 schema = self.parse('''
174 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
175 <xsd:element name="a" type="AType"/>
176 <xsd:complexType name="AType">
177 <xsd:sequence minOccurs="3" maxOccurs="3">
178 <xsd:element name="b" type="BType" />
179 </xsd:sequence>
180 </xsd:complexType>
181 <xsd:complexType name="BType">
182 <xsd:attribute name="hardy" type="xsd:string" fixed="hey" />
183 </xsd:complexType>
184 </xsd:schema>
185 ''')
186 schema = etree.XMLSchema(schema)
187 parser = etree.XMLParser(schema=schema, attribute_defaults=True)
188
189 tree_valid = self.parse('<a><b/><b hardy="hey"/><b/></a>',
190 parser=parser)
191 root = tree_valid.getroot()
192 self.assertEqual('hey', root[0].get('hardy'))
193 self.assertEqual('hey', root[1].get('hardy'))
194 self.assertEqual('hey', root[2].get('hardy'))
195
197 schema_file = BytesIO('''
198 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
199 <xsd:element name="a" type="AType"/>
200 <xsd:complexType name="AType">
201 <xsd:sequence>
202 <xsd:element name="b" type="xsd:string" />
203 </xsd:sequence>
204 </xsd:complexType>
205 </xsd:schema>
206 ''')
207 schema = etree.XMLSchema(file=schema_file)
208 parser = etree.XMLParser(schema=schema)
209
210 tree_valid = self.parse('<a><b></b></a>', parser=parser)
211 self.assertEqual('a', tree_valid.getroot().tag)
212
213 self.assertRaises(etree.XMLSyntaxError,
214 self.parse, '<a><c></c></a>', parser=parser)
215
217 schema = self.parse('''
218 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
219 <xsd:element name="a" type="AType"/>
220 <xsd:complexType name="AType">
221 <xsd:sequence>
222 <xsd:element name="b" type="xsd:string" />
223 </xsd:sequence>
224 </xsd:complexType>
225 </xsd:schema>
226 ''')
227 schema = etree.XMLSchema(schema)
228 xml = BytesIO('<a><b></b></a>')
229 events = [ (event, el.tag)
230 for (event, el) in etree.iterparse(xml, schema=schema) ]
231
232 self.assertEqual([('end', 'b'), ('end', 'a')],
233 events)
234
236 schema = self.parse('''
237 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
238 <xsd:element name="a" type="AType"/>
239 <xsd:complexType name="AType">
240 <xsd:sequence>
241 <xsd:element name="b" type="xsd:string" />
242 </xsd:sequence>
243 </xsd:complexType>
244 </xsd:schema>
245 ''')
246 schema = etree.XMLSchema(schema)
247 self.assertRaises(
248 etree.XMLSyntaxError,
249 list, etree.iterparse(BytesIO('<a><c></c></a>'), schema=schema))
250
253
256
258 schema = self.parse('''
259 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
260 <xsd:element name="a" type="xsd:string"/>
261 </xsd:schema>
262 ''')
263 schema = etree.XMLSchema(schema)
264
265 root = etree.Element('a')
266 root.text = 'TEST'
267 self.assertTrue(schema(root))
268
269 self.assertRaises(ValueError, schema, etree.Comment('TEST'))
270 self.assertRaises(ValueError, schema, etree.PI('a', 'text'))
271 self.assertRaises(ValueError, schema, etree.Entity('text'))
272
274 schema = self.parse('''\
275 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
276 <element name="a" type="AType"/>
277 <xsd:complexType name="AType">
278 <xsd:sequence>
279 <xsd:element name="b" type="xsd:string" />
280 </xsd:sequence>
281 </xsd:complexType>
282 </xsd:schema>
283 ''')
284 self.assertRaises(etree.XMLSchemaParseError,
285 etree.XMLSchema, schema)
286
291
302
304
305
306 schema = etree.XMLSchema(file=fileInTestDir('test_import.xsd'))
307 tree_valid = self.parse(
308 '<a:x xmlns:a="http://codespeak.net/lxml/schema/ns1"><b></b></a:x>')
309 self.assertTrue(schema.validate(tree_valid))
310
312 tree_valid = self.parse('<a><b></b></a>')
313 tree_invalid = self.parse('<a><c></c></a>')
314 schema = self.parse('''\
315 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
316 <xsd:element name="a" type="AType"/>
317 <xsd:complexType name="AType">
318 <xsd:sequence>
319 <xsd:element name="b" type="xsd:string" />
320 </xsd:sequence>
321 </xsd:complexType>
322 </xsd:schema>
323 ''')
324 self.assertTrue(tree_valid.xmlschema(schema))
325 self.assertFalse(tree_invalid.xmlschema(schema))
326
328
329 wsdl = self.parse('''\
330 <wsdl:definitions
331 xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
332 xmlns:xs="http://www.w3.org/2001/XMLSchema">
333 <wsdl:types>
334 <xs:schema>
335 </xs:schema>
336 </wsdl:types>
337 </wsdl:definitions>
338 ''')
339 schema_element = wsdl.find(
340 "{http://schemas.xmlsoap.org/wsdl/}types/"
341 "{http://www.w3.org/2001/XMLSchema}schema"
342 )
343 etree.XMLSchema(schema_element)
344 etree.XMLSchema(schema_element)
345 etree.XMLSchema(schema_element)
346
347
349 resolver_schema_int = BytesIO("""\
350 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
351 xmlns:etype="http://codespeak.net/lxml/test/external"
352 targetNamespace="http://codespeak.net/lxml/test/internal">
353 <xsd:import namespace="http://codespeak.net/lxml/test/external" schemaLocation="XXX.xsd" />
354 <xsd:element name="a" type="etype:AType"/>
355 </xsd:schema>""")
356
357 resolver_schema_int2 = BytesIO("""\
358 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
359 xmlns:etype="http://codespeak.net/lxml/test/external"
360 targetNamespace="http://codespeak.net/lxml/test/internal">
361 <xsd:import namespace="http://codespeak.net/lxml/test/external" schemaLocation="YYY.xsd" />
362 <xsd:element name="a" type="etype:AType"/>
363 </xsd:schema>""")
364
365 resolver_schema_ext = """\
366 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
367 targetNamespace="http://codespeak.net/lxml/test/external">
368 <xsd:complexType name="AType">
369 <xsd:sequence><xsd:element name="b" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /></xsd:sequence>
370 </xsd:complexType>
371 </xsd:schema>"""
372
376
377 - def resolve(self, url, id, context):
378 assert url == 'XXX.xsd'
379 return self.resolve_string(self.schema, context)
380
381
382
389
398
400
401
402
403 class res_root(etree.Resolver):
404 def resolve(self, url, id, context):
405 assert False
406 return None
407
408 root_resolver = res_root()
409 etree.get_default_parser().resolvers.add(root_resolver)
410
411 parser = etree.XMLParser()
412 parser.resolvers.add(self.simple_resolver(self.resolver_schema_ext))
413
414 schema_doc = etree.parse(self.resolver_schema_int, parser = parser)
415 schema = etree.XMLSchema(schema_doc)
416 etree.get_default_parser().resolvers.remove(root_resolver)
417
419
420
421 resolver_schema = self.resolver_schema_ext
422
423 class res_nested(etree.Resolver):
424 def __init__(self, ext_schema):
425 self.ext_schema = ext_schema
426
427 def resolve(self, url, id, context):
428 assert url == 'YYY.xsd'
429 return self.resolve_string(self.ext_schema, context)
430
431 class res(etree.Resolver):
432 def __init__(self, ext_schema_1, ext_schema_2):
433 self.ext_schema_1 = ext_schema_1
434 self.ext_schema_2 = ext_schema_2
435
436 def resolve(self, url, id, context):
437 assert url == 'XXX.xsd'
438
439 new_parser = etree.XMLParser()
440 new_parser.resolvers.add(res_nested(self.ext_schema_2))
441 new_schema_doc = etree.parse(self.ext_schema_1, parser = new_parser)
442 new_schema = etree.XMLSchema(new_schema_doc)
443
444 return self.resolve_string(resolver_schema, context)
445
446 parser = etree.XMLParser()
447 parser.resolvers.add(res(self.resolver_schema_int2, self.resolver_schema_ext))
448 schema_doc = etree.parse(self.resolver_schema_int, parser = parser)
449 schema = etree.XMLSchema(schema_doc)
450
451
459
460
461 if __name__ == '__main__':
462 print('to test use test.py %s' % __file__)
463