Package xmlschema_acue ::
Package validators ::
Module complex_types
1
2
3
4
5
6
7
8
9
10
11 from __future__ import unicode_literals
12
13 from xmlschema_acue.exceptions import XMLSchemaValueError
14 from xmlschema_acue.qnames import XSD_GROUP, XSD_ATTRIBUTE_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE, \
15 XSD_ANY_ATTRIBUTE, XSD_ATTRIBUTE, XSD_COMPLEX_CONTENT, XSD_RESTRICTION, XSD_COMPLEX_TYPE, \
16 XSD_EXTENSION, XSD_ANY_TYPE, XSD_SIMPLE_CONTENT, XSD_ANY_SIMPLE_TYPE, XSD_OPEN_CONTENT, XSD_ASSERT
17 from xmlschema_acue.helpers import get_qname, local_name, get_xml_bool_attribute, get_xsd_derivation_attribute
18 from xmlschema_acue.etree import etree_element
19
20 from xmlschema_acue.validators.exceptions import XMLSchemaValidationError, XMLSchemaDecodeError
21 from xmlschema_acue.validators.xsdbase import XsdType, ValidationMixin
22 from xmlschema_acue.validators.assertions import XsdAssert
23 from xmlschema_acue.validators.attributes import XsdAttributeGroup
24 from xmlschema_acue.validators.simple_types import XsdSimpleType
25 from xmlschema_acue.validators.groups import XsdGroup
26
27 XSD_MODEL_GROUP_TAGS = {XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE}
28
29 SEQUENCE_ELEMENT = etree_element(XSD_SEQUENCE)
33 """
34 Class for XSD 1.0 'complexType' definitions.
35
36 <complexType
37 abstract = boolean : false
38 block = (#all | List of (extension | restriction))
39 final = (#all | List of (extension | restriction))
40 id = ID
41 mixed = boolean : false
42 name = NCName
43 {any attributes with non-schema namespace . . .}>
44 Content: (annotation?, (simpleContent | complexContent |
45 ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
46 </complexType>
47 """
48 _admitted_tags = {XSD_COMPLEX_TYPE, XSD_RESTRICTION}
49 assertions = ()
50 mixed = False
51 _block = None
52 _derivation = None
53
54 @staticmethod
57
58 - def __init__(self, elem, schema, parent, name=None, **kwargs):
59 if kwargs:
60 if 'content_type' in kwargs:
61 self.content_type = kwargs['content_type']
62 if 'attributes' in kwargs:
63 self.attributes = kwargs['attributes']
64 if 'mixed' in kwargs:
65 self.mixed = kwargs['mixed']
66 if 'block' in kwargs:
67 self._block = kwargs['block']
68 if 'final' in kwargs:
69 self._final = kwargs['final']
70 super(XsdComplexType, self).__init__(elem, schema, parent, name)
71
73 if self.name is not None:
74 return '%s(name=%r)' % (self.__class__.__name__, self.prefixed_name)
75 elif not hasattr(self, 'content_type'):
76 return '%s(id=%r)' % (self.__class__.__name__, id(self))
77 else:
78 return '%s(content=%r, attributes=%r)' % (
79 self.__class__.__name__, self.content_type_label,
80 [a if a.name is None else a.prefixed_name for a in self.attributes.values()]
81 )
82
91
93 super(XsdComplexType, self)._parse()
94 elem = self.elem
95 if elem.tag == XSD_RESTRICTION:
96 return
97
98 if 'abstract' in elem.attrib:
99 try:
100 self.abstract = get_xml_bool_attribute(elem, 'abstract')
101 except ValueError as err:
102 self.parse_error(err, elem)
103
104 if 'block' in elem.attrib:
105 try:
106 self._block = get_xsd_derivation_attribute(elem, 'block', ('extension', 'restriction'))
107 except ValueError as err:
108 self.parse_error(err, elem)
109
110 if 'final' in elem.attrib:
111 try:
112 self._final = get_xsd_derivation_attribute(elem, 'final', ('extension', 'restriction'))
113 except ValueError as err:
114 self.parse_error(err, elem)
115
116 if 'mixed' in elem.attrib:
117 try:
118 self.mixed = get_xml_bool_attribute(elem, 'mixed')
119 except ValueError as err:
120 self.parse_error(err, elem)
121
122 try:
123 self.name = get_qname(self.target_namespace, elem.attrib['name'])
124 except KeyError:
125 self.name = None
126 else:
127 if self.parent is not None:
128 self.parse_error("attribute 'name' not allowed for a local complexType", elem)
129
130 content_elem = self._parse_component(elem, required=False, strict=False)
131 if content_elem is None or content_elem.tag in \
132 {XSD_ATTRIBUTE, XSD_ATTRIBUTE_GROUP, XSD_ANY_ATTRIBUTE}:
133
134
135 self.content_type = self.schema.BUILDERS.group_class(SEQUENCE_ELEMENT, self.schema, self)
136 self._parse_content_tail(elem)
137
138 elif content_elem.tag in {XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE}:
139
140
141 self.content_type = self.schema.BUILDERS.group_class(content_elem, self.schema, self)
142 self._parse_content_tail(elem)
143
144 elif content_elem.tag == XSD_SIMPLE_CONTENT:
145 if 'mixed' in content_elem.attrib:
146 self.parse_error("'mixed' attribute not allowed with simpleContent", content_elem)
147
148 derivation_elem = self._parse_derivation_elem(content_elem)
149 if derivation_elem is None:
150 return
151
152 self.base_type = self._parse_base_type(derivation_elem)
153 if derivation_elem.tag == XSD_RESTRICTION:
154 self._parse_simple_content_restriction(derivation_elem, self.base_type)
155 else:
156 self._parse_simple_content_extension(derivation_elem, self.base_type)
157
158 if content_elem is not elem[-1]:
159 k = 2 if content_elem is not elem[0] else 1
160 self.parse_error("unexpected tag %r after simpleContent declaration:" % elem[k].tag, elem)
161
162 elif content_elem.tag == XSD_COMPLEX_CONTENT:
163
164
165 if 'mixed' in content_elem.attrib:
166 self.mixed = content_elem.attrib['mixed'] in ('true', '1')
167
168 derivation_elem = self._parse_derivation_elem(content_elem)
169 if derivation_elem is None:
170 return
171
172 base_type = self._parse_base_type(derivation_elem, complex_content=True)
173 if derivation_elem.tag == XSD_RESTRICTION:
174 self._parse_complex_content_restriction(derivation_elem, base_type)
175 else:
176 self._parse_complex_content_extension(derivation_elem, base_type)
177
178 if content_elem is not elem[-1]:
179 k = 2 if content_elem is not elem[0] else 1
180 self.parse_error("unexpected tag %r after complexContent declaration:" % elem[k].tag, elem)
181 if self.redefine or base_type is not self:
182 self.base_type = base_type
183
184 elif content_elem.tag == XSD_OPEN_CONTENT and self.schema.XSD_VERSION != '1.0':
185 self.open_content = None
186
187 if content_elem is elem[-1]:
188 self.content_type = self.schema.BUILDERS.group_class(SEQUENCE_ELEMENT, self.schema, self)
189 else:
190 for child, index in enumerate(elem):
191 if content_elem is not child:
192 continue
193 elif elem[index + 1].tag in {XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE}:
194 self.content_type = self.schema.BUILDERS.group_class(elem[index + 1], self.schema, self)
195 else:
196 self.content_type = self.schema.BUILDERS.group_class(SEQUENCE_ELEMENT, self.schema, self)
197 break
198 self._parse_content_tail(elem)
199
200 else:
201 if self.schema.validation == 'skip':
202
203 self.parse_error("unexpected tag %r for complexType content:" % content_elem.tag, elem)
204 self.content_type = self.schema.create_any_content_group(self)
205 self.attributes = self.schema.create_any_attribute_group(self)
206
207 if self.redefine is None:
208 if self.base_type is not None and self.base_type.name == self.name:
209 self.parse_error("wrong definition with self-reference", elem)
210 elif self.base_type is None or self.base_type.name != self.name:
211 self.parse_error("wrong redefinition without self-reference", elem)
212
213 - def _parse_content_tail(self, elem, **kwargs):
214 self.attributes = self.schema.BUILDERS.attribute_group_class(elem, self.schema, self, **kwargs)
215
233
260
262
263
264 if base_type.is_simple():
265 self.parse_error("a complexType ancestor required: %r" % base_type, elem)
266 self.content_type = self.schema.create_any_content_group(self)
267 self._parse_content_tail(elem)
268 else:
269 if base_type.has_simple_content():
270 self.content_type = self.schema.BUILDERS.restriction_class(elem, self.schema, self)
271 if not self.content_type.is_derived(base_type.content_type, 'restriction'):
272 self.parse_error("Content type is not a restriction of base content type", elem)
273
274 elif base_type.mixed and base_type.is_emptiable():
275 self.content_type = self.schema.BUILDERS.restriction_class(elem, self.schema, self)
276 else:
277 self.parse_error("with simple content cannot restrict an empty or "
278 "an element-only content type ", base_type.elem)
279 self.content_type = self.schema.create_any_content_group(self)
280
281 self._parse_content_tail(elem, derivation='restriction', base_attributes=base_type.attributes)
282
283 - def _parse_simple_content_extension(self, elem, base_type):
284
285
286 child = self._parse_component(elem, required=False, strict=False)
287 if child is not None and child.tag not in \
288 {XSD_ATTRIBUTE_GROUP, XSD_ATTRIBUTE, XSD_ANY_ATTRIBUTE}:
289 self.parse_error("unexpected tag %r." % child.tag, child)
290
291 if base_type.is_simple():
292 self.content_type = base_type
293 self._parse_content_tail(elem)
294 else:
295 if base_type.has_simple_content():
296 self.content_type = base_type.content_type
297 else:
298 self.parse_error("base type %r has not simple content." % base_type, elem)
299 self.content_type = self.schema.create_any_content_group(self)
300
301 self._parse_content_tail(elem, derivation='extension', base_attributes=base_type.attributes)
302
304 if 'restriction' in base_type.final:
305 self.parse_error("the base type is not derivable by restriction")
306 if base_type.is_simple() or base_type.has_simple_content():
307 self.parse_error("base %r is simple or has a simple content." % base_type, elem)
308 base_type = self.maps.types[XSD_ANY_TYPE]
309
310
311 group_elem = self._parse_component(elem, required=False, strict=False)
312 if group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
313 content_type = self.schema.BUILDERS.group_class(group_elem, self.schema, self)
314 else:
315
316 content_type = self.schema.BUILDERS.group_class(elem, self.schema, self)
317
318 if base_type.is_element_only() and content_type.mixed:
319 self.parse_error(
320 "derived a mixed content from a base type that has element-only content.", elem
321 )
322 elif base_type.is_empty() and not content_type.is_empty():
323 self.parse_error(
324 "derived an empty content from base type that has not empty content.", elem
325 )
326
327 if base_type.name != XSD_ANY_TYPE and not base_type.is_empty() and False:
328 if not content_type.has_occurs_restriction(base_type.content_type):
329 self.parse_error("The derived group %r is not a restriction of the base group." % elem, elem)
330
331 self.content_type = content_type
332 self._parse_content_tail(elem, derivation='restriction', base_attributes=base_type.attributes)
333
334 - def _parse_complex_content_extension(self, elem, base_type):
335 if 'extension' in base_type.final:
336 self.parse_error("the base type is not derivable by extension")
337
338 group_elem = self._parse_component(elem, required=False, strict=False)
339 if base_type.is_empty():
340
341 if group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
342 self.content_type = self.schema.BUILDERS.group_class(group_elem, self.schema, self)
343 else:
344
345 self.content_type = self.schema.BUILDERS.group_class(elem, self.schema, self)
346 else:
347
348 sequence_elem = etree_element(XSD_SEQUENCE)
349 sequence_elem.text = '\n '
350 content_type = self.schema.BUILDERS.group_class(sequence_elem, self.schema, self)
351
352 if group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
353
354
355
356 if base_type.is_simple() or base_type.has_simple_content():
357 self.parse_error("base %r is simple or has a simple content." % base_type, elem)
358 base_type = self.maps.types[XSD_ANY_TYPE]
359
360 group = self.schema.BUILDERS.group_class(group_elem, self.schema, self)
361 if group.model == 'all':
362 self.parse_error("Cannot extend a complex content with an all model")
363
364 content_type.append(base_type.content_type)
365 content_type.append(group)
366 sequence_elem.append(base_type.content_type.elem)
367 sequence_elem.append(group.elem)
368
369
370
371 if base_type.content_type.model == 'all' and base_type.content_type and group \
372 and self.schema.XSD_VERSION == '1.0':
373 self.parse_error("XSD 1.0 does not allow extension of a not empty 'ALL' model group.", elem)
374
375 if base_type.mixed != self.mixed and base_type.name != XSD_ANY_TYPE:
376 self.parse_error("base has a different content type (mixed=%r) and the "
377 "extension group is not empty." % base_type.mixed, elem)
378
379 elif not base_type.is_simple() and not base_type.has_simple_content():
380 content_type.append(base_type.content_type)
381 sequence_elem.append(base_type.content_type.elem)
382 if base_type.mixed != self.mixed and base_type.name != XSD_ANY_TYPE and self.mixed:
383 self.parse_error("extended type has a mixed content but the base is element-only", elem)
384
385 self.content_type = content_type
386
387 self._parse_content_tail(elem, derivation='extension', base_attributes=base_type.attributes)
388
389 @property
391 try:
392 return self.content_type.built and self.attributes.built and self.mixed in (False, True)
393 except AttributeError:
394 return False
395
396 @property
406
407 @property
410
411 @staticmethod
414
415 @staticmethod
418
423
426
428 try:
429 return self.content_type.is_simple()
430 except AttributeError:
431 if self.content_type or self.content_type.mixed or self.base_type is None:
432 return False
433 else:
434 return self.base_type.is_simple() or self.base_type.has_simple_content()
435
437 try:
438 return self.content_type.mixed
439 except AttributeError:
440 return False
441
443 if self.name == XSD_ANY_TYPE:
444 return False
445 try:
446 return not self.content_type.mixed
447 except AttributeError:
448 return False
449
452
453 - def is_valid(self, source, use_defaults=True):
460
480
482 if xsd_classes is None or isinstance(self, xsd_classes):
483 yield self
484 if self.attributes.parent is not None:
485 for obj in self.attributes.iter_components(xsd_classes):
486 yield obj
487 if self.content_type.parent is not None:
488 for obj in self.content_type.iter_components(xsd_classes):
489 yield obj
490
491 for obj in self.assertions:
492 if xsd_classes is None or isinstance(obj, xsd_classes):
493 yield obj
494
495 @staticmethod
498
504
505 @property
508
511
514
515 - def decode(self, data, *args, **kwargs):
522
523 - def iter_decode(self, elem, validation='lax', converter=None, **kwargs):
524 """
525 Decode an Element instance.
526
527 :param elem: the Element that has to be decoded.
528 :param validation: the validation mode. Can be 'lax', 'strict' or 'skip.
529 :param converter: an :class:`XMLSchemaConverter` subclass or instance.
530 :param kwargs: keyword arguments for the decoding process.
531 :return: yields a 3-tuple (simple content, complex content, attributes) containing \
532 the decoded parts, eventually preceded by a sequence of validation or decoding errors.
533 """
534
535 for assertion in self.assertions:
536 for error in assertion(elem):
537 yield self.validation_error(validation, error, **kwargs)
538
539 for result in self.attributes.iter_decode(elem.attrib, validation, **kwargs):
540 if isinstance(result, XMLSchemaValidationError):
541 yield result
542 else:
543 attributes = result
544 break
545 else:
546 attributes = None
547
548 if self.has_simple_content():
549 if len(elem) and validation != 'skip':
550 reason = "a simple content element can't has child elements."
551 yield self.validation_error(validation, reason, elem, **kwargs)
552
553 if elem.text is not None:
554 text = elem.text or kwargs.pop('default', '')
555 for result in self.content_type.iter_decode(text, validation, **kwargs):
556 if isinstance(result, XMLSchemaValidationError):
557 yield result
558 else:
559 yield result, None, attributes
560 else:
561 yield None, None, attributes
562 else:
563 for result in self.content_type.iter_decode(elem, validation, converter, **kwargs):
564 if isinstance(result, XMLSchemaValidationError):
565 yield result
566 else:
567 yield None, result, attributes
568
569 - def iter_encode(self, element_data, validation='lax', converter=None, **kwargs):
570 """
571 Encode an element data instance.
572
573 :param element_data: an ElementData instance with unencoded data.
574 :param validation: the validation mode: can be 'lax', 'strict' or 'skip'.
575 :param converter: an :class:`XMLSchemaConverter` subclass or instance.
576 :param kwargs: keyword arguments for the encoding process.
577 :return: yields a 3-tuple (text, content, attributes) containing the encoded parts, \
578 eventually preceded by a sequence of validation or decoding errors.
579 """
580 for result in self.attributes.iter_encode(element_data.attributes, validation, **kwargs):
581 if isinstance(result, XMLSchemaValidationError):
582 yield result
583 else:
584 attributes = result
585 break
586 else:
587 attributes = ()
588
589 if self.has_simple_content():
590 if element_data.text is None:
591 yield None, element_data.content, attributes
592 else:
593 for result in self.content_type.iter_encode(element_data.text, validation, **kwargs):
594 if isinstance(result, XMLSchemaValidationError):
595 yield result
596 else:
597 yield result, element_data.content, attributes
598 else:
599 for result in self.content_type.iter_encode(element_data, validation, converter, **kwargs):
600 if isinstance(result, XMLSchemaValidationError):
601 yield result
602 elif result:
603 yield result[0], result[1], attributes
604 else:
605 yield None, None, attributes
606
609 """
610 Class for XSD 1.1 'complexType' definitions.
611
612 <complexType
613 abstract = boolean : false
614 block = (#all | List of (extension | restriction))
615 final = (#all | List of (extension | restriction))
616 id = ID
617 mixed = boolean
618 name = NCName
619 defaultAttributesApply = boolean : true
620 {any attributes with non-schema namespace . . .}>
621 Content: (annotation?, (simpleContent | complexContent | (openContent?,
622 (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?), assert*)))
623 </complexType>
624 """
642
643 - def _parse_content_tail(self, elem, **kwargs):
644 self.attributes = self.schema.BUILDERS.attribute_group_class(elem, self.schema, self, **kwargs)
645 self.assertions = []
646 for child in self._iterparse_components(elem):
647 if child.tag == XSD_ASSERT:
648 self.assertions.append(XsdAssert(child, self.schema, self, self))
649
650 @property
653