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
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
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 minOccurs="4" maxOccurs="4">
40 <xsd:element name="b" type="BType" />
41 </xsd:sequence>
42 </xsd:complexType>
43 <xsd:complexType name="BType">
44 <xsd:attribute name="hardy" type="xsd:string" default="hey" />
45 </xsd:complexType>
46 </xsd:schema>
47 ''')
48 schema = etree.XMLSchema(schema, attribute_defaults=True)
49
50 tree = self.parse('<a><b hardy="ho"/><b/><b hardy="ho"/><b/></a>')
51
52 root = tree.getroot()
53 self.assertEquals('ho', root[0].get('hardy'))
54 self.assertEquals(None, root[1].get('hardy'))
55 self.assertEquals('ho', root[2].get('hardy'))
56 self.assertEquals(None, root[3].get('hardy'))
57
58 self.assert_(schema(tree))
59
60 root = tree.getroot()
61 self.assertEquals('ho', root[0].get('hardy'))
62 self.assertEquals('hey', root[1].get('hardy'))
63 self.assertEquals('ho', root[2].get('hardy'))
64 self.assertEquals('hey', root[3].get('hardy'))
65
67 schema = self.parse('''
68 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
69 <xsd:element name="a" type="AType"/>
70 <xsd:complexType name="AType">
71 <xsd:sequence>
72 <xsd:element name="b" type="xsd:string" />
73 </xsd:sequence>
74 </xsd:complexType>
75 </xsd:schema>
76 ''')
77 schema = etree.XMLSchema(schema)
78 parser = etree.XMLParser(schema=schema)
79
80 tree_valid = self.parse('<a><b></b></a>', parser=parser)
81 self.assertEquals('a', tree_valid.getroot().tag)
82
83 self.assertRaises(etree.XMLSyntaxError,
84 self.parse, '<a><c></c></a>', parser=parser)
85
87
88 schema = self.parse('''
89 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
90 <xsd:element name="a" type="AType"/>
91 <xsd:complexType name="AType">
92 <xsd:sequence minOccurs="4" maxOccurs="4">
93 <xsd:element name="b" type="BType" />
94 </xsd:sequence>
95 </xsd:complexType>
96 <xsd:complexType name="BType">
97 <xsd:attribute name="hardy" type="xsd:string" default="hey" />
98 </xsd:complexType>
99 </xsd:schema>
100 ''')
101 schema = etree.XMLSchema(schema)
102 parser = etree.XMLParser(schema=schema, attribute_defaults=True)
103
104 tree_valid = self.parse('<a><b hardy="ho"/><b/><b hardy="ho"/><b/></a>',
105 parser=parser)
106 root = tree_valid.getroot()
107 self.assertEquals('ho', root[0].get('hardy'))
108 self.assertEquals('hey', root[1].get('hardy'))
109 self.assertEquals('ho', root[2].get('hardy'))
110 self.assertEquals('hey', root[3].get('hardy'))
111
113
114 schema = self.parse('''
115 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
116 <xsd:element name="a" type="AType"/>
117 <xsd:complexType name="AType">
118 <xsd:sequence minOccurs="4" maxOccurs="4">
119 <xsd:element name="b" type="BType" />
120 </xsd:sequence>
121 </xsd:complexType>
122 <xsd:complexType name="BType">
123 <xsd:attribute name="hardy" type="xsd:string" default="hey" />
124 </xsd:complexType>
125 </xsd:schema>
126 ''')
127 schema = etree.XMLSchema(schema, attribute_defaults=True)
128 parser = etree.XMLParser(schema=schema)
129
130 tree_valid = self.parse('<a><b hardy="ho"/><b/><b hardy="ho"/><b/></a>',
131 parser=parser)
132 root = tree_valid.getroot()
133 self.assertEquals('ho', root[0].get('hardy'))
134 self.assertEquals('hey', root[1].get('hardy'))
135 self.assertEquals('ho', root[2].get('hardy'))
136 self.assertEquals('hey', root[3].get('hardy'))
137
139
140 schema = self.parse('''
141 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
142 <xsd:element name="a" type="AType"/>
143 <xsd:complexType name="AType">
144 <xsd:sequence minOccurs="3" maxOccurs="3">
145 <xsd:element name="b" type="BType" />
146 </xsd:sequence>
147 </xsd:complexType>
148 <xsd:complexType name="BType">
149 <xsd:attribute name="hardy" type="xsd:string" fixed="hey" />
150 </xsd:complexType>
151 </xsd:schema>
152 ''')
153 schema = etree.XMLSchema(schema)
154 parser = etree.XMLParser(schema=schema, attribute_defaults=True)
155
156 tree_valid = self.parse('<a><b/><b hardy="hey"/><b/></a>',
157 parser=parser)
158 root = tree_valid.getroot()
159 self.assertEquals('hey', root[0].get('hardy'))
160 self.assertEquals('hey', root[1].get('hardy'))
161 self.assertEquals('hey', root[2].get('hardy'))
162
164 schema_file = BytesIO('''
165 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
166 <xsd:element name="a" type="AType"/>
167 <xsd:complexType name="AType">
168 <xsd:sequence>
169 <xsd:element name="b" type="xsd:string" />
170 </xsd:sequence>
171 </xsd:complexType>
172 </xsd:schema>
173 ''')
174 schema = etree.XMLSchema(file=schema_file)
175 parser = etree.XMLParser(schema=schema)
176
177 tree_valid = self.parse('<a><b></b></a>', parser=parser)
178 self.assertEquals('a', tree_valid.getroot().tag)
179
180 self.assertRaises(etree.XMLSyntaxError,
181 self.parse, '<a><c></c></a>', parser=parser)
182
184 schema = self.parse('''
185 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
186 <xsd:element name="a" type="AType"/>
187 <xsd:complexType name="AType">
188 <xsd:sequence>
189 <xsd:element name="b" type="xsd:string" />
190 </xsd:sequence>
191 </xsd:complexType>
192 </xsd:schema>
193 ''')
194 schema = etree.XMLSchema(schema)
195 xml = BytesIO('<a><b></b></a>')
196 events = [ (event, el.tag)
197 for (event, el) in etree.iterparse(xml, schema=schema) ]
198
199 self.assertEquals([('end', 'b'), ('end', 'a')],
200 events)
201
203 schema = self.parse('''
204 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
205 <xsd:element name="a" type="AType"/>
206 <xsd:complexType name="AType">
207 <xsd:sequence>
208 <xsd:element name="b" type="xsd:string" />
209 </xsd:sequence>
210 </xsd:complexType>
211 </xsd:schema>
212 ''')
213 schema = etree.XMLSchema(schema)
214 self.assertRaises(
215 etree.XMLSyntaxError,
216 list, etree.iterparse(BytesIO('<a><c></c></a>'), schema=schema))
217
220
222 schema = self.parse('''\
223 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
224 <element name="a" type="AType"/>
225 <xsd:complexType name="AType">
226 <xsd:sequence>
227 <xsd:element name="b" type="xsd:string" />
228 </xsd:sequence>
229 </xsd:complexType>
230 </xsd:schema>
231 ''')
232 self.assertRaises(etree.XMLSchemaParseError,
233 etree.XMLSchema, schema)
234
239
250
258
260 tree_valid = self.parse('<a><b></b></a>')
261 tree_invalid = self.parse('<a><c></c></a>')
262 schema = self.parse('''\
263 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
264 <xsd:element name="a" type="AType"/>
265 <xsd:complexType name="AType">
266 <xsd:sequence>
267 <xsd:element name="b" type="xsd:string" />
268 </xsd:sequence>
269 </xsd:complexType>
270 </xsd:schema>
271 ''')
272 self.assert_(tree_valid.xmlschema(schema))
273 self.assert_(not tree_invalid.xmlschema(schema))
274
275
277 resolver_schema_int = BytesIO("""\
278 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
279 xmlns:etype="http://codespeak.net/lxml/test/external"
280 targetNamespace="http://codespeak.net/lxml/test/internal">
281 <xsd:import namespace="http://codespeak.net/lxml/test/external" schemaLocation="XXX.xsd" />
282 <xsd:element name="a" type="etype:AType"/>
283 </xsd:schema>""")
284
285 resolver_schema_int2 = BytesIO("""\
286 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
287 xmlns:etype="http://codespeak.net/lxml/test/external"
288 targetNamespace="http://codespeak.net/lxml/test/internal">
289 <xsd:import namespace="http://codespeak.net/lxml/test/external" schemaLocation="YYY.xsd" />
290 <xsd:element name="a" type="etype:AType"/>
291 </xsd:schema>""")
292
293 resolver_schema_ext = """\
294 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
295 targetNamespace="http://codespeak.net/lxml/test/external">
296 <xsd:complexType name="AType">
297 <xsd:sequence><xsd:element name="b" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /></xsd:sequence>
298 </xsd:complexType>
299 </xsd:schema>"""
300
304
305 - def resolve(self, url, id, context):
306 assert url == 'XXX.xsd'
307 return self.resolve_string(self.schema, context)
308
309
310
317
326
328
329
330
331 class res_root(etree.Resolver):
332 def resolve(self, url, id, context):
333 assert False
334 return None
335
336 root_resolver = res_root()
337 etree.get_default_parser().resolvers.add(root_resolver)
338
339 parser = etree.XMLParser()
340 parser.resolvers.add(self.simple_resolver(self.resolver_schema_ext))
341
342 schema_doc = etree.parse(self.resolver_schema_int, parser = parser)
343 schema = etree.XMLSchema(schema_doc)
344 etree.get_default_parser().resolvers.remove(root_resolver)
345
347
348
349 resolver_schema = self.resolver_schema_ext
350
351 class res_nested(etree.Resolver):
352 def __init__(self, ext_schema):
353 self.ext_schema = ext_schema
354
355 def resolve(self, url, id, context):
356 assert url == 'YYY.xsd'
357 return self.resolve_string(self.ext_schema, context)
358
359 class res(etree.Resolver):
360 def __init__(self, ext_schema_1, ext_schema_2):
361 self.ext_schema_1 = ext_schema_1
362 self.ext_schema_2 = ext_schema_2
363
364 def resolve(self, url, id, context):
365 assert url == 'XXX.xsd'
366
367 new_parser = etree.XMLParser()
368 new_parser.resolvers.add(res_nested(self.ext_schema_2))
369 new_schema_doc = etree.parse(self.ext_schema_1, parser = new_parser)
370 new_schema = etree.XMLSchema(new_schema_doc)
371
372 return self.resolve_string(resolver_schema, context)
373
374 parser = etree.XMLParser()
375 parser.resolvers.add(res(self.resolver_schema_int2, self.resolver_schema_ext))
376 schema_doc = etree.parse(self.resolver_schema_int, parser = parser)
377 schema = etree.XMLSchema(schema_doc)
378
386
387 if __name__ == '__main__':
388 print('to test use test.py %s' % __file__)
389