Package xmlschema_acue ::
Package validators ::
Module wildcards
1
2
3
4
5
6
7
8
9
10
11 """
12 This module contains classes for XML Schema wildcards.
13 """
14 from __future__ import unicode_literals
15
16 from xmlschema_acue.exceptions import XMLSchemaValueError
17 from xmlschema_acue.qnames import XSD_ANY, XSD_ANY_ATTRIBUTE, XSD_OPEN_CONTENT, XSD_DEFAULT_OPEN_CONTENT
18 from xmlschema_acue.helpers import get_namespace
19 from xmlschema_acue.namespaces import XSI_NAMESPACE
20 from xmlschema_acue.xpath import ElementPathMixin
21
22 from xmlschema_acue.validators.exceptions import XMLSchemaNotBuiltError
23 from xmlschema_acue.validators.xsdbase import ValidationMixin, XsdComponent, ParticleMixin
27 names = {}
28
29 - def __init__(self, elem, schema, parent):
33
35 return '%s(namespace=%r, process_contents=%r)' % (
36 self.__class__.__name__, self.namespace, self.process_contents
37 )
38
40 super(XsdWildcard, self)._parse()
41
42
43 namespace = self.elem.get('namespace', '##any')
44 items = namespace.strip().split()
45 if len(items) == 1 and items[0] in ('##any', '##other', '##local', '##targetNamespace'):
46 self.namespace = namespace.strip()
47 elif not all(not s.startswith('##') or s in {'##local', '##targetNamespace'} for s in items):
48 self.parse_error("wrong value %r for 'namespace' attribute." % namespace)
49 self.namespace = '##any'
50 else:
51 self.namespace = namespace.strip()
52
53 self.process_contents = self.elem.get('processContents', 'strict')
54 if self.process_contents not in {'lax', 'skip', 'strict'}:
55 self.parse_error("wrong value %r for 'processContents' attribute." % self.process_contents)
56
75
76 @property
79
81 if self.namespace in ('##any', '##other'):
82 return
83 for ns in self.namespace.split():
84 if ns == '##local':
85 yield ''
86 elif ns == '##targetNamespace':
87 yield self.target_namespace
88 else:
89 yield ns
90
100
117
119 if check_occurs and isinstance(self, ParticleMixin) and not self.has_occurs_restriction(other):
120 return False
121 elif not isinstance(other, type(self)):
122 return False
123 elif other.process_contents == 'strict' and self.process_contents != 'strict':
124 return False
125 elif other.process_contents == 'lax' and self.process_contents == 'skip':
126 return False
127 elif self.namespace == other.namespace:
128 return True
129 elif other.namespace == '##any':
130 return True
131 elif self.namespace == '##any':
132 return False
133
134 other_namespaces = other.namespace.split()
135 for ns in self.namespace.split():
136 if ns in other_namespaces:
137 continue
138 elif ns == self.target_namespace:
139 if '##targetNamespace' in other_namespaces:
140 continue
141 elif not ns.startswith('##') and '##other' in other_namespaces:
142 continue
143 return False
144 return True
145
146 - def iter_decode(self, source, validation='lax', *args, **kwargs):
147 raise NotImplementedError
148
149 - def iter_encode(self, obj, validation='lax', *args, **kwargs):
150 raise NotImplementedError
151
152
153 -class XsdAnyElement(XsdWildcard, ParticleMixin, ElementPathMixin):
154 """
155 Class for XSD 1.0 'any' wildcards.
156
157 <any
158 id = ID
159 maxOccurs = (nonNegativeInteger | unbounded) : 1
160 minOccurs = nonNegativeInteger : 1
161 namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) ) : ##any
162 processContents = (lax | skip | strict) : strict
163 {any attributes with non-schema namespace . . .}>
164 Content: (annotation?)
165 </any>
166 """
167 _admitted_tags = {XSD_ANY}
168
170 return '%s(namespace=%r, process_contents=%r, occurs=%r)' % (
171 self.__class__.__name__, self.namespace, self.process_contents, self.occurs
172 )
173
175 super(XsdAnyElement, self)._parse()
176 self._parse_particle(self.elem)
177
179 return self.min_occurs == 0 or self.process_contents != 'strict'
180
181 - def match(self, name, default_namespace=None):
190
193
194 - def iter(self, tag=None):
196
199
200 @staticmethod
203
204 - def iter_decode(self, elem, validation='lax', converter=None, **kwargs):
205 if self.process_contents == 'skip':
206 return
207
208 namespace = get_namespace(elem.tag)
209 if self.is_namespace_allowed(namespace):
210 self._load_namespace(namespace)
211 try:
212 xsd_element = self.maps.lookup_element(elem.tag)
213 except LookupError:
214 if self.process_contents == 'strict' and validation != 'skip':
215 reason = "element %r not found." % elem.tag
216 yield self.validation_error(validation, reason, elem, **kwargs)
217 else:
218 for result in xsd_element.iter_decode(elem, validation, converter, **kwargs):
219 yield result
220 elif validation != 'skip':
221 reason = "element %r not allowed here." % elem.tag
222 yield self.validation_error(validation, reason, elem, **kwargs)
223
224 - def iter_encode(self, obj, validation='lax', converter=None, **kwargs):
225 if self.process_contents == 'skip':
226 return
227
228 name, value = obj
229 namespace = get_namespace(name)
230 if self.is_namespace_allowed(namespace):
231 self._load_namespace(namespace)
232 try:
233 xsd_element = self.maps.lookup_element(name)
234 except LookupError:
235 if self.process_contents == 'strict' and validation != 'skip':
236 reason = "element %r not found." % name
237 yield self.validation_error(validation, reason, **kwargs)
238 else:
239 for result in xsd_element.iter_encode(value, validation, converter, **kwargs):
240 yield result
241 elif validation != 'skip':
242 reason = "element %r not allowed here." % name
243 yield self.validation_error(validation, reason, value, **kwargs)
244
259
262 """
263 Class for XSD 1.0 'anyAttribute' wildcards.
264
265 <anyAttribute
266 id = ID
267 namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )
268 processContents = (lax | skip | strict) : strict
269 {any attributes with non-schema namespace . . .}>
270 Content: (annotation?)
271 </anyAttribute>
272 """
273 _admitted_tags = {XSD_ANY_ATTRIBUTE}
274
300
301 - def match(self, name, default_namespace=None):
310
311 - def iter_decode(self, attribute, validation='lax', **kwargs):
312 if self.process_contents == 'skip':
313 return
314
315 name, value = attribute
316 namespace = get_namespace(name)
317 if self.is_namespace_allowed(namespace):
318 self._load_namespace(namespace)
319 try:
320 xsd_attribute = self.maps.lookup_attribute(name)
321 except LookupError:
322 if self.process_contents == 'strict' and validation != 'skip':
323 reason = "attribute %r not found." % name
324 yield self.validation_error(validation, reason, attribute, **kwargs)
325 else:
326 for result in xsd_attribute.iter_decode(value, validation, **kwargs):
327 yield result
328 elif validation != 'skip':
329 reason = "attribute %r not allowed." % name
330 yield self.validation_error(validation, reason, attribute, **kwargs)
331
332 - def iter_encode(self, attribute, validation='lax', **kwargs):
333 if self.process_contents == 'skip':
334 return
335
336 name, value = attribute
337 namespace = get_namespace(name)
338 if self.is_namespace_allowed(namespace):
339 self._load_namespace(namespace)
340 try:
341 xsd_attribute = self.maps.lookup_attribute(name)
342 except LookupError:
343 if self.process_contents == 'strict' and validation != 'skip':
344 reason = "attribute %r not found." % name
345 yield self.validation_error(validation, reason, attribute, **kwargs)
346 else:
347 for result in xsd_attribute.iter_encode(value, validation, **kwargs):
348 yield result
349 elif validation != 'skip':
350 reason = "attribute %r not allowed." % name
351 yield self.validation_error(validation, reason, attribute, **kwargs)
352
355
357 super(Xsd11Wildcard, self)._parse()
358
359
360 try:
361 not_namespace = self.elem.attrib['notNamespace'].strip()
362 except KeyError:
363 self.not_namespace = None
364 else:
365 if 'namespace' in self.elem.attrib:
366 self.not_namespace = None
367 self.parse_error("'namespace' and 'notNamespace' attributes are mutually exclusive.")
368 elif not_namespace in ('##local', '##targetNamespace'):
369 self.not_namespace = not_namespace
370 else:
371 self.not_namespace = not_namespace.split()
372
373
374 try:
375 not_qname = self.elem.attrib['notQName'].strip()
376 except KeyError:
377 self.not_qname = None
378 else:
379 if not_qname in ('##defined', '##definedSibling'):
380 self.not_qname = not_qname
381 else:
382 self.not_qname = not_qname.split()
383
400
403 """
404 Class for XSD 1.1 'any' declarations.
405
406 <any
407 id = ID
408 maxOccurs = (nonNegativeInteger | unbounded) : 1
409 minOccurs = nonNegativeInteger : 1
410 namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )
411 notNamespace = List of (anyURI | (##targetNamespace | ##local))
412 notQName = List of (QName | (##defined | ##definedSibling))
413 processContents = (lax | skip | strict) : strict
414 {any attributes with non-schema namespace . . .}>
415 Content: (annotation?)
416 </any>
417 """
418 pass
419
422 """
423 Class for XSD 1.1 'anyAttribute' declarations.
424
425 <anyAttribute
426 id = ID
427 namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local)) )
428 notNamespace = List of (anyURI | (##targetNamespace | ##local))
429 notQName = List of (QName | ##defined)
430 processContents = (lax | skip | strict) : strict
431 {any attributes with non-schema namespace . . .}>
432 Content: (annotation?)
433 </anyAttribute>
434 """
435 pass
436
437
438 -class XsdOpenContent(XsdComponent):
439 """
440 Class for XSD 1.1 'openContent' model definitions.
441
442 <openContent
443 id = ID
444 mode = (none | interleave | suffix) : interleave
445 {any attributes with non-schema namespace . . .}>
446 Content: (annotation?), (any?)
447 </openContent>
448 """
449 _admitted_tags = {XSD_OPEN_CONTENT, XSD_DEFAULT_OPEN_CONTENT}
450
451 - def __init__(self, elem, schema, parent):
452 super(XsdOpenContent, self).__init__(elem, schema, parent)
453 self.mode = self.elem.get('mode', 'interleave')
454 if self.mode not in ('none', 'interleave', 'suffix'):
455 self.parse_error("wrong value %r for 'mode' attribute." % self.mode)
456
458 super(XsdOpenContent, self)._parse()
459 child = self._parse_component(self.elem)
460 if child is None:
461 if self.elem.tag == XSD_DEFAULT_OPEN_CONTENT:
462 self.parse_error("a %r declaration cannot be empty:" % self.elem.tag, self.elem)
463 self.any_element = None
464 elif child.tag == XSD_ANY:
465 self.any_element = Xsd11AnyElement(child, self.schema, self)
466 else:
467 self.any_element = None
468 if self.schema.validation == 'skip':
469
470 self.parse_error("unexpected tag %r for openContent child:" % child.tag, self.elem)
471