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>
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
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
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
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
111
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
130
141
149
151 tree_valid = self.parse('<a><b></b></a>')
152 tree_invalid = self.parse('<a><c></c></a>')
153 schema = self.parse('''\
154 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
155 <xsd:element name="a" type="AType"/>
156 <xsd:complexType name="AType">
157 <xsd:sequence>
158 <xsd:element name="b" type="xsd:string" />
159 </xsd:sequence>
160 </xsd:complexType>
161 </xsd:schema>
162 ''')
163 self.assert_(tree_valid.xmlschema(schema))
164 self.assert_(not tree_invalid.xmlschema(schema))
165
166
168 resolver_schema_int = BytesIO("""\
169 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
170 xmlns:etype="http://codespeak.net/lxml/test/external"
171 targetNamespace="http://codespeak.net/lxml/test/internal">
172 <xsd:import namespace="http://codespeak.net/lxml/test/external" schemaLocation="XXX.xsd" />
173 <xsd:element name="a" type="etype:AType"/>
174 </xsd:schema>""")
175
176 resolver_schema_int2 = BytesIO("""\
177 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
178 xmlns:etype="http://codespeak.net/lxml/test/external"
179 targetNamespace="http://codespeak.net/lxml/test/internal">
180 <xsd:import namespace="http://codespeak.net/lxml/test/external" schemaLocation="YYY.xsd" />
181 <xsd:element name="a" type="etype:AType"/>
182 </xsd:schema>""")
183
184 resolver_schema_ext = """\
185 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
186 targetNamespace="http://codespeak.net/lxml/test/external">
187 <xsd:complexType name="AType">
188 <xsd:sequence><xsd:element name="b" type="xsd:string" minOccurs="0" maxOccurs="unbounded" /></xsd:sequence>
189 </xsd:complexType>
190 </xsd:schema>"""
191
195
196 - def resolve(self, url, id, context):
197 assert url == 'XXX.xsd'
198 return self.resolve_string(self.schema, context)
199
200
201
208
217
219 """Test that the default resolver will not get called when a more
220 specific resolver is registered."""
221
222 class res_root(etree.Resolver):
223 def resolve(self, url, id, context):
224 assert False
225 return None
226
227 root_resolver = res_root()
228 etree.get_default_parser().resolvers.add(root_resolver)
229
230 parser = etree.XMLParser()
231 parser.resolvers.add(self.simple_resolver(self.resolver_schema_ext))
232
233 schema_doc = etree.parse(self.resolver_schema_int, parser = parser)
234 schema = etree.XMLSchema(schema_doc)
235 etree.get_default_parser().resolvers.remove(root_resolver)
236
238 """Test that resolvers work in a nested fashion."""
239
240 resolver_schema = self.resolver_schema_ext
241
242 class res_nested(etree.Resolver):
243 def __init__(self, ext_schema):
244 self.ext_schema = ext_schema
245
246 def resolve(self, url, id, context):
247 assert url == 'YYY.xsd'
248 return self.resolve_string(self.ext_schema, context)
249
250 class res(etree.Resolver):
251 def __init__(self, ext_schema_1, ext_schema_2):
252 self.ext_schema_1 = ext_schema_1
253 self.ext_schema_2 = ext_schema_2
254
255 def resolve(self, url, id, context):
256 assert url == 'XXX.xsd'
257
258 new_parser = etree.XMLParser()
259 new_parser.resolvers.add(res_nested(self.ext_schema_2))
260 new_schema_doc = etree.parse(self.ext_schema_1, parser = new_parser)
261 new_schema = etree.XMLSchema(new_schema_doc)
262
263 return self.resolve_string(resolver_schema, context)
264
265 parser = etree.XMLParser()
266 parser.resolvers.add(res(self.resolver_schema_int2, self.resolver_schema_ext))
267 schema_doc = etree.parse(self.resolver_schema_int, parser = parser)
268 schema = etree.XMLSchema(schema_doc)
269
277
278 if __name__ == '__main__':
279 print('to test use test.py %s' % __file__)
280