1#
2# Copyright (c), 2016-2020, SISSA (International School for Advanced Studies).
3# All rights reserved.
4# This file is distributed under the terms of the MIT License.
5# See the file 'LICENSE' in the root directory of the present
6# distribution, or http://opensource.org/licenses/MIT.
7#
8# @author Davide Brunato <brunato@sissa.it>
9#
10from collections.abc import MutableSequence
11from typing import cast, Any, Callable, Iterator, List, Optional, Tuple, Union
12
13from ..exceptions import XMLSchemaValueError
14from ..names import XSD_GROUP, XSD_ATTRIBUTE_GROUP, XSD_SEQUENCE, XSD_OVERRIDE, \
15    XSD_ALL, XSD_CHOICE, XSD_ANY_ATTRIBUTE, XSD_ATTRIBUTE, XSD_COMPLEX_CONTENT, \
16    XSD_RESTRICTION, XSD_COMPLEX_TYPE, XSD_EXTENSION, XSD_ANY_TYPE, XSD_ASSERT, \
17    XSD_UNTYPED_ATOMIC, XSD_SIMPLE_CONTENT, XSD_OPEN_CONTENT, XSD_ANNOTATION
18from ..aliases import ElementType, NamespacesType, SchemaType, ComponentClassType, \
19    DecodeType, IterDecodeType, IterEncodeType, BaseXsdType, AtomicValueType, \
20    ExtraValidatorType
21from ..helpers import get_prefixed_qname, get_qname, local_name
22from .. import dataobjects
23
24from .exceptions import XMLSchemaDecodeError
25from .helpers import get_xsd_derivation_attribute
26from .xsdbase import XSD_TYPE_DERIVATIONS, XsdComponent, XsdType, ValidationMixin
27from .attributes import XsdAttributeGroup
28from .assertions import XsdAssert
29from .simple_types import FacetsValueType, XsdSimpleType, XsdUnion
30from .groups import XsdGroup
31from .wildcards import XsdOpenContent, XsdDefaultOpenContent
32
33XSD_MODEL_GROUP_TAGS = {XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE}
34
35
36class XsdComplexType(XsdType, ValidationMixin[Union[ElementType, str, bytes], Any]):
37    """
38    Class for XSD 1.0 *complexType* definitions.
39
40    :var attributes: the attribute group related with the complexType.
41    :var content: the content of the complexType can be a model group or a simple type.
42    :var mixed: if `True` the complex type has mixed content.
43
44    ..  <complexType
45          abstract = boolean : false
46          block = (#all | List of (extension | restriction))
47          final = (#all | List of (extension | restriction))
48          id = ID
49          mixed = boolean : false
50          name = NCName
51          {any attributes with non-schema namespace . . .}>
52          Content: (annotation?, (simpleContent | complexContent |
53          ((group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?))))
54        </complexType>
55    """
56    attributes: XsdAttributeGroup
57    copy: Callable[['XsdComplexType'], 'XsdComplexType']
58    content: Union[XsdGroup, XsdSimpleType] = None  # type: ignore[assignment]
59
60    abstract: bool = False
61    mixed: bool = False
62    assertions: Union[Tuple[()], List[XsdAssert]] = ()
63    open_content: Optional[XsdOpenContent] = None
64    _block: Optional[str] = None
65
66    _ADMITTED_TAGS = {XSD_COMPLEX_TYPE, XSD_RESTRICTION}
67    _CONTENT_TAIL_TAGS = {XSD_ATTRIBUTE, XSD_ATTRIBUTE_GROUP, XSD_ANY_ATTRIBUTE}
68
69    @staticmethod
70    def normalize(text: Union[str, bytes]) -> str:
71        return text.decode('utf-8') if isinstance(text, bytes) else text
72
73    def __init__(self, elem: ElementType,
74                 schema: SchemaType,
75                 parent: Optional[XsdComponent] = None,
76                 name: Optional[str] = None,
77                 **kwargs: Any) -> None:
78
79        if kwargs:
80            if 'content' in kwargs:
81                self.content = kwargs['content']
82            if 'attributes' in kwargs:
83                self.attributes = kwargs['attributes']
84            if 'mixed' in kwargs:
85                self.mixed = kwargs['mixed']
86            if 'block' in kwargs:
87                self._block = kwargs['block']
88            if 'final' in kwargs:
89                self._final = kwargs['final']
90        super(XsdComplexType, self).__init__(elem, schema, parent, name)
91        assert self.content is not None
92
93    def __repr__(self) -> str:
94        if self.name is not None:
95            return '%s(name=%r)' % (self.__class__.__name__, self.prefixed_name)
96        elif not hasattr(self, 'content') or not hasattr(self, 'attributes'):
97            return '%s(id=%r)' % (self.__class__.__name__, id(self))
98        else:
99            return '%s(content=%r, attributes=%r)' % (
100                self.__class__.__name__, self.content_type_label,
101                [a if a.name is None else a.prefixed_name for a in self.attributes.values()]
102            )
103
104    def _parse(self) -> None:
105        if self.elem.tag == XSD_RESTRICTION:
106            return  # a local restriction is already parsed by the caller
107
108        if 'abstract' in self.elem.attrib:
109            if self.elem.attrib['abstract'].strip() in {'true', '1'}:
110                self.abstract = True
111
112        if 'block' in self.elem.attrib:
113            try:
114                self._block = get_xsd_derivation_attribute(self.elem, 'block', XSD_TYPE_DERIVATIONS)
115            except ValueError as err:
116                self.parse_error(err)
117
118        if 'final' in self.elem.attrib:
119            try:
120                self._final = get_xsd_derivation_attribute(self.elem, 'final', XSD_TYPE_DERIVATIONS)
121            except ValueError as err:
122                self.parse_error(err)
123
124        if 'mixed' in self.elem.attrib:
125            if self.elem.attrib['mixed'].strip() in {'true', '1'}:
126                self.mixed = True
127
128        try:
129            self.name = get_qname(self.target_namespace, self.elem.attrib['name'])
130        except KeyError:
131            self.name = None
132            if self.parent is None:
133                self.parse_error("missing attribute 'name' in a global complexType")
134                self.name = 'nameless_%s' % str(id(self))
135        else:
136            if self.parent is not None:
137                self.parse_error("attribute 'name' not allowed for a local complexType")
138                self.name = None
139
140        content_elem = self._parse_child_component(self.elem, strict=False)
141        if content_elem is None or content_elem.tag in self._CONTENT_TAIL_TAGS:
142            self.content = self.schema.create_empty_content_group(self)
143            self._parse_content_tail(self.elem)
144            default_open_content = self.default_open_content
145            if default_open_content is not None and \
146                    (self.mixed or self.content or default_open_content.applies_to_empty):
147                self.open_content = default_open_content
148
149        elif content_elem.tag in {XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE}:
150            self.content = self.schema.xsd_group_class(content_elem, self.schema, self)
151            default_open_content = self.default_open_content
152            if default_open_content is not None and \
153                    (self.mixed or self.content or default_open_content.applies_to_empty):
154                self.open_content = default_open_content
155            self._parse_content_tail(self.elem)
156
157        elif content_elem.tag == XSD_SIMPLE_CONTENT:
158            if 'mixed' in content_elem.attrib:
159                self.parse_error("'mixed' attribute not allowed with simpleContent", content_elem)
160
161            derivation_elem = self._parse_derivation_elem(content_elem)
162            if derivation_elem is None:
163                return
164
165            self.base_type = base_type = self._parse_base_type(derivation_elem)
166            if derivation_elem.tag == XSD_RESTRICTION:
167                self._parse_simple_content_restriction(derivation_elem, base_type)
168            else:
169                self._parse_simple_content_extension(derivation_elem, base_type)
170
171            if content_elem is not self.elem[-1]:
172                k = 2 if content_elem is not self.elem[0] else 1
173                self.parse_error(
174                    "unexpected tag %r after simpleContent declaration:" % self.elem[k].tag
175                )
176
177        elif content_elem.tag == XSD_COMPLEX_CONTENT:
178            #
179            # complexType with complexContent restriction/extension
180            if 'mixed' in content_elem.attrib:
181                mixed = content_elem.attrib['mixed'] in ('true', '1')
182                if mixed is not self.mixed:
183                    self.mixed = mixed
184                    if 'mixed' in self.elem.attrib and self.xsd_version == '1.1':
185                        self.parse_error("value of 'mixed' attribute in complexType "
186                                         "and complexContent must be same")
187
188            derivation_elem = self._parse_derivation_elem(content_elem)
189            if derivation_elem is None:
190                return
191
192            self.base_type = self._parse_base_type(derivation_elem, complex_content=True)
193            if self.base_type is self and self.redefine is not None:
194                self.base_type = self.redefine
195                self.open_content = None
196
197            if derivation_elem.tag == XSD_RESTRICTION:
198                self._parse_complex_content_restriction(derivation_elem, self.base_type)
199            else:
200                self._parse_complex_content_extension(derivation_elem, self.base_type)
201
202            if content_elem is not self.elem[-1]:
203                k = 2 if content_elem is not self.elem[0] else 1
204                self.parse_error(
205                    "unexpected tag %r after complexContent declaration:" % self.elem[k].tag
206                )
207
208        elif content_elem.tag == XSD_OPEN_CONTENT and self.xsd_version > '1.0':
209            self.open_content = XsdOpenContent(content_elem, self.schema, self)
210
211            if content_elem is self.elem[-1]:
212                self.content = self.schema.create_empty_content_group(self)
213            else:
214                for index, child in enumerate(self.elem):
215                    if content_elem is not child:
216                        continue
217                    elif self.elem[index + 1].tag in {XSD_GROUP, XSD_SEQUENCE, XSD_ALL, XSD_CHOICE}:
218                        self.content = self.schema.xsd_group_class(
219                            self.elem[index + 1], self.schema, self
220                        )
221                    else:
222                        self.content = self.schema.create_empty_content_group(self)
223                    break
224            self._parse_content_tail(self.elem)
225
226        else:
227            if self.schema.validation == 'skip':
228                # Also generated by meta-schema validation for 'lax' and 'strict' modes
229                self.parse_error(
230                    "unexpected tag %r for complexType content:" % content_elem.tag
231                )
232            self.content = self.schema.create_any_content_group(self)
233            self.attributes = self.schema.create_any_attribute_group(self)
234
235        if self.redefine is None:
236            if self.base_type is not None and self.base_type.name == self.name:
237                self.parse_error("wrong definition with self-reference")
238        elif self.base_type is None or self.base_type.name != self.name:
239            self.parse_error("wrong redefinition without self-reference")
240
241    def _parse_content_tail(self, elem: ElementType, **kwargs: Any) -> None:
242        self.attributes = self.schema.xsd_attribute_group_class(
243            elem, self.schema, self, **kwargs
244        )
245
246    def _parse_derivation_elem(self, elem: ElementType) -> Optional[ElementType]:
247        derivation_elem = self._parse_child_component(elem)
248        if derivation_elem is None or derivation_elem.tag not in {XSD_RESTRICTION, XSD_EXTENSION}:
249            self.parse_error("restriction or extension tag expected", derivation_elem)
250            self.content = self.schema.create_any_content_group(self)
251            self.attributes = self.schema.create_any_attribute_group(self)
252            return None
253
254        if self.derivation is not None and self.redefine is None:
255            raise XMLSchemaValueError("{!r} is expected to have a redefined/"
256                                      "overridden component".format(self))
257        self.derivation = local_name(derivation_elem.tag)
258
259        if self.base_type is not None and self.derivation in self.base_type.final:
260            self.parse_error(f"{self.derivation!r} derivation not allowed for {self!r}")
261        return derivation_elem
262
263    def _parse_base_type(self, elem: ElementType, complex_content: bool = False) \
264            -> Union[XsdSimpleType, 'XsdComplexType']:
265        try:
266            base_qname = self.schema.resolve_qname(elem.attrib['base'])
267        except (KeyError, ValueError, RuntimeError) as err:
268            if 'base' not in elem.attrib:
269                self.parse_error("'base' attribute required", elem)
270            else:
271                self.parse_error(err, elem)
272            return self.any_type
273
274        try:
275            base_type = self.maps.lookup_type(base_qname)
276        except KeyError:
277            self.parse_error("missing base type %r" % base_qname, elem)
278            if complex_content:
279                return self.any_type
280            else:
281                return self.any_simple_type
282        else:
283            if isinstance(base_type, tuple):
284                self.parse_error("circularity definition found between %r "
285                                 "and %r" % (self, base_qname), elem)
286                return self.any_type
287            elif complex_content and base_type.is_simple():
288                self.parse_error("a complexType ancestor required: %r" % base_type, elem)
289                return self.any_type
290
291            if base_type.final and elem.tag.rsplit('}', 1)[-1] in base_type.final:
292                msg = "derivation by %r blocked by attribute 'final' in base type"
293                self.parse_error(msg % elem.tag.rsplit('}', 1)[-1])
294
295            return base_type
296
297    def _parse_simple_content_restriction(self, elem: ElementType, base_type: Any) -> None:
298        # simpleContent restriction: the base type must be a complexType with a simple
299        # content or a complex content with a mixed and emptiable content.
300        if base_type.is_simple():
301            self.parse_error("a complexType ancestor required: %r" % base_type, elem)
302            self.content = self.schema.create_any_content_group(self)
303            self._parse_content_tail(elem)
304        else:
305            if base_type.is_empty():
306                self.content = self.schema.xsd_atomic_restriction_class(elem, self.schema, self)
307                if not self.is_empty():
308                    self.parse_error("a not empty simpleContent cannot restrict "
309                                     "an empty content type", elem)
310                    self.content = self.schema.create_any_content_group(self)
311
312            elif base_type.has_simple_content():
313                self.content = self.schema.xsd_atomic_restriction_class(elem, self.schema, self)
314                if not self.content.is_derived(base_type.content, 'restriction'):
315                    self.parse_error("content type is not a restriction of base content", elem)
316
317            elif base_type.mixed and base_type.is_emptiable():
318                self.content = self.schema.xsd_atomic_restriction_class(elem, self.schema, self)
319            else:
320                self.parse_error("with simpleContent cannot restrict an "
321                                 "element-only content type", elem)
322                self.content = self.schema.create_any_content_group(self)
323
324            self._parse_content_tail(elem, derivation='restriction',
325                                     base_attributes=base_type.attributes)
326
327    def _parse_simple_content_extension(self, elem: ElementType, base_type: Any) -> None:
328        # simpleContent extension: the base type must be a simpleType or a complexType
329        # with simple content.
330        child = self._parse_child_component(elem, strict=False)
331        if child is not None and child.tag not in self._CONTENT_TAIL_TAGS:
332            self.parse_error('unexpected tag %r' % child.tag, child)
333
334        if base_type.is_simple():
335            self.content = base_type
336            self._parse_content_tail(elem)
337        else:
338            if base_type.has_simple_content():
339                self.content = base_type.content
340            else:
341                self.parse_error("base type %r has not simple content." % base_type, elem)
342                self.content = self.schema.create_any_content_group(self)
343
344            self._parse_content_tail(elem, derivation='extension',
345                                     base_attributes=base_type.attributes)
346
347    def _parse_complex_content_restriction(self, elem: ElementType, base_type: Any) -> None:
348        if 'restriction' in base_type.final:
349            self.parse_error("the base type is not derivable by restriction")
350        if base_type.is_simple() or base_type.has_simple_content():
351            self.parse_error("base %r is simple or has a simple content." % base_type, elem)
352            base_type = self.any_type
353
354        # complexContent restriction: the base type must be a complexType with a complex content.
355        for child in elem:
356            if child.tag == XSD_OPEN_CONTENT and self.xsd_version > '1.0':
357                self.open_content = XsdOpenContent(child, self.schema, self)
358                continue
359            elif child.tag in XSD_MODEL_GROUP_TAGS:
360                content = self.schema.xsd_group_class(child, self.schema, self)
361                if not base_type.content.admits_restriction(content.model):
362                    self.parse_error(
363                        "restriction of an xs:{} with more than one particle with xs:{} is "
364                        "forbidden".format(base_type.content.model, content.model)
365                    )
366                break
367        else:
368            content = self.schema.create_empty_content_group(
369                self, base_type.content.model
370            )
371
372        content.restriction = base_type.content
373
374        if base_type.is_element_only() and content.mixed:
375            self.parse_error(
376                "derived a mixed content from a base type that has element-only content.", elem
377            )
378        elif base_type.is_empty() and not content.is_empty():
379            self.parse_error(
380                "derived an empty content from base type that has not empty content.", elem
381            )
382
383        if self.open_content is None:
384            default_open_content = self.default_open_content
385            if default_open_content is not None and \
386                    (self.mixed or content or default_open_content.applies_to_empty):
387                self.open_content = default_open_content
388
389        if self.open_content and content and \
390                not self.open_content.is_restriction(base_type.open_content):
391            msg = "{!r} is not a restriction of the base type {!r}"
392            self.parse_error(msg.format(self.open_content, base_type.open_content))
393
394        self.content = content
395        self._parse_content_tail(elem, derivation='restriction',
396                                 base_attributes=base_type.attributes)
397
398    def _parse_complex_content_extension(self, elem: ElementType, base_type: Any) -> None:
399        if 'extension' in base_type.final:
400            self.parse_error("the base type is not derivable by extension")
401
402        group_elem: Optional[ElementType]
403        for group_elem in elem:
404            if group_elem.tag != XSD_ANNOTATION and not callable(group_elem.tag):
405                break
406        else:
407            group_elem = None
408
409        if base_type.is_empty():
410            if not base_type.mixed:
411                # Empty element-only model extension: don't create a nested group.
412                if group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
413                    self.content = self.schema.xsd_group_class(
414                        group_elem, self.schema, self
415                    )
416                elif base_type.is_simple() or base_type.has_simple_content():
417                    self.content = self.schema.create_empty_content_group(self)
418                else:
419                    self.content = self.schema.create_empty_content_group(
420                        parent=self, elem=base_type.content.elem
421                    )
422            elif base_type.mixed:
423                # Empty mixed model extension
424                self.content = self.schema.create_empty_content_group(self)
425                self.content.append(self.schema.create_empty_content_group(self.content))
426
427                if group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
428                    group = self.schema.xsd_group_class(
429                        group_elem, self.schema, self.content
430                    )
431                    if not self.mixed:
432                        self.parse_error("base has a different content type (mixed=%r) and the "
433                                         "extension group is not empty." % base_type.mixed, elem)
434                else:
435                    group = self.schema.create_empty_content_group(self)
436
437                self.content.append(group)
438                self.content.elem.append(base_type.content.elem)
439                self.content.elem.append(group.elem)
440
441        elif group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
442            # Derivation from a simple content is forbidden if base type is not empty.
443            if base_type.is_simple() or base_type.has_simple_content():
444                self.parse_error("base %r is simple or has a simple content." % base_type, elem)
445                base_type = self.any_type
446
447            group = self.schema.xsd_group_class(group_elem, self.schema, self)
448
449            if group.model == 'all':
450                self.parse_error("cannot extend a complex content with xs:all")
451            if base_type.content.model == 'all' and group.model == 'sequence':
452                self.parse_error("xs:sequence cannot extend xs:all")
453
454            content = self.schema.create_empty_content_group(self)
455            content.append(base_type.content)
456            content.append(group)
457            content.elem.append(base_type.content.elem)
458            content.elem.append(group.elem)
459
460            if base_type.content.model == 'all' and base_type.content and group:
461                self.parse_error(
462                    "XSD 1.0 does not allow extension of a not empty 'all' model group"
463                )
464            if base_type.mixed != self.mixed and base_type.name != XSD_ANY_TYPE:
465                self.parse_error("base has a different content type (mixed=%r) and the "
466                                 "extension group is not empty" % base_type.mixed, elem)
467            self.content = content
468
469        elif base_type.is_simple():
470            self.content = base_type
471        elif base_type.has_simple_content():
472            self.content = base_type.content
473        else:
474            self.content = self.schema.create_empty_content_group(self)
475            self.content.append(base_type.content)
476            self.content.elem.append(base_type.content.elem)
477            if base_type.mixed != self.mixed and base_type.name != XSD_ANY_TYPE and self.mixed:
478                self.parse_error(
479                    "extended type has a mixed content but the base is element-only", elem
480                )
481
482        self._parse_content_tail(elem, derivation='extension', base_attributes=base_type.attributes)
483
484    @property
485    def default_open_content(self) -> Optional[XsdDefaultOpenContent]:
486        return None
487
488    @property
489    def block(self) -> str:
490        return self.schema.block_default if self._block is None else self._block
491
492    @property
493    def built(self) -> bool:
494        return self.content.parent is not None or self.content.built
495
496    @property
497    def validation_attempted(self) -> str:
498        return 'full' if self.built else self.content.validation_attempted
499
500    @property
501    def simple_type(self) -> Optional[XsdSimpleType]:
502        return self.content if isinstance(self.content, XsdSimpleType) else None
503
504    @property
505    def model_group(self) -> Optional[XsdGroup]:
506        return self.content if isinstance(self.content, XsdGroup) else None
507
508    @property
509    def content_type(self) -> Union[XsdGroup, XsdSimpleType]:
510        """Property that returns the attribute *content*, for backward compatibility."""
511        import warnings
512        warnings.warn("'content_type' attribute has been replaced by 'content' "
513                      "and will be removed in version 2.0", DeprecationWarning, stacklevel=2)
514        return self.content
515
516    @property
517    def content_type_label(self) -> str:
518        if self.is_empty():
519            return 'empty'
520        elif isinstance(self.content, XsdSimpleType):
521            return 'simple'
522        elif self.mixed:
523            return 'mixed'
524        else:
525            return 'element-only'
526
527    @property
528    def sequence_type(self) -> str:
529        if self.is_empty():
530            return 'empty-sequence()'
531        elif not self.has_simple_content():
532            st = get_prefixed_qname(XSD_UNTYPED_ATOMIC, self.namespaces)
533        else:
534            try:
535                st = self.content.primitive_type.prefixed_name  # type: ignore[union-attr]
536            except AttributeError:
537                st = get_prefixed_qname(XSD_UNTYPED_ATOMIC, self.namespaces)
538            else:
539                if st is None:
540                    st = 'item()'
541
542        return f"{st}{'*' if self.is_emptiable() else '+'}"
543
544    @staticmethod
545    def is_simple() -> bool:
546        return False
547
548    @staticmethod
549    def is_complex() -> bool:
550        return True
551
552    def is_empty(self) -> bool:
553        if self.open_content and self.open_content.mode != 'none':
554            return False
555        return self.content.is_empty()
556
557    def is_emptiable(self) -> bool:
558        return self.content.is_emptiable()
559
560    def has_simple_content(self) -> bool:
561        if not isinstance(self.content, XsdGroup):
562            return not self.content.is_empty()
563        elif self.content or self.content.mixed or self.base_type is None:
564            return False
565        else:
566            return self.base_type.is_simple() or self.base_type.has_simple_content()
567
568    def has_complex_content(self) -> bool:
569        if not isinstance(self.content, XsdGroup):
570            return False
571        elif self.open_content and self.open_content.mode != 'none':
572            return True
573        return not self.content.is_empty()
574
575    def has_mixed_content(self) -> bool:
576        if not isinstance(self.content, XsdGroup):
577            return False
578        elif self.content.is_empty():
579            return False
580        else:
581            return self.content.mixed
582
583    def is_element_only(self) -> bool:
584        if not isinstance(self.content, XsdGroup):
585            return False
586        elif self.content.is_empty():
587            return False
588        else:
589            return not self.content.mixed
590
591    def is_list(self) -> bool:
592        return isinstance(self.content, XsdSimpleType) and self.content.is_list()
593
594    def validate(self, obj: Union[ElementType, str, bytes],
595                 use_defaults: bool = True,
596                 namespaces: Optional[NamespacesType] = None,
597                 max_depth: Optional[int] = None,
598                 extra_validator: Optional[ExtraValidatorType] = None) -> None:
599        kwargs: Any = {
600            'use_defaults': use_defaults,
601            'namespaces': namespaces,
602            'max_depth': max_depth,
603            'extra_validator': extra_validator
604        }
605        if not isinstance(obj, (str, bytes)):
606            super(XsdComplexType, self).validate(obj, **kwargs)
607        elif isinstance(self.content, XsdSimpleType):
608            self.content.validate(obj, **kwargs)
609        elif not self.mixed and self.base_type is not None:
610            self.base_type.validate(obj, **kwargs)
611
612    def is_valid(self, obj: Union[ElementType, str, bytes],
613                 use_defaults: bool = True,
614                 namespaces: Optional[NamespacesType] = None,
615                 max_depth: Optional[int] = None,
616                 extra_validator: Optional[ExtraValidatorType] = None) -> bool:
617        kwargs: Any = {
618            'use_defaults': use_defaults,
619            'namespaces': namespaces,
620            'max_depth': max_depth,
621            'extra_validator': extra_validator
622        }
623        if not isinstance(obj, (str, bytes)):
624            return super(XsdComplexType, self).is_valid(obj, **kwargs)
625        elif isinstance(self.content, XsdSimpleType):
626            return self.content.is_valid(obj, **kwargs)
627        else:
628            return self.mixed or self.base_type is not None and \
629                self.base_type.is_valid(obj, **kwargs)
630
631    def is_derived(self, other: Union[BaseXsdType, Tuple[ElementType, SchemaType]],
632                   derivation: Optional[str] = None) -> bool:
633        if derivation and derivation == self.derivation:
634            derivation = None  # derivation mode checked
635
636        if self is other:
637            return derivation is None
638        elif isinstance(other, tuple):
639            other[1].parse_error(f"global type {other[0].tag!r} is not built")
640            return False
641        elif other.name == XSD_ANY_TYPE:
642            return True
643        elif self.base_type is other:
644            return derivation is None  # or self.base_type.derivation == derivation
645        elif isinstance(other, XsdUnion):
646            return any(self.is_derived(m, derivation) for m in other.member_types)
647        elif self.base_type is None:
648            if not self.has_simple_content():
649                return False
650            return isinstance(self.content, XsdSimpleType) and \
651                self.content.is_derived(other, derivation)
652        elif self.has_simple_content():
653            return isinstance(self.content, XsdSimpleType) and \
654                self.content.is_derived(other, derivation) or \
655                self.base_type.is_derived(other, derivation)
656        else:
657            return self.base_type.is_derived(other, derivation)
658
659    def iter_components(self, xsd_classes: ComponentClassType = None) \
660            -> Iterator[XsdComponent]:
661        if xsd_classes is None or isinstance(self, xsd_classes):
662            yield self
663        if self.attributes and self.attributes.parent is not None:
664            yield from self.attributes.iter_components(xsd_classes)
665        if self.content.parent is not None:
666            yield from self.content.iter_components(xsd_classes)
667        if self.base_type is not None and self.base_type.parent is not None:
668            yield from self.base_type.iter_components(xsd_classes)
669
670        for obj in filter(lambda x: x.base_type is self, self.assertions):
671            if xsd_classes is None or isinstance(obj, xsd_classes):
672                yield obj
673
674    def get_facet(self, tag: str) -> Optional[FacetsValueType]:
675        if isinstance(self.content, XsdSimpleType):
676            return self.content.get_facet(tag)
677        return None
678
679    def admit_simple_restriction(self) -> bool:
680        if 'restriction' in self.final:
681            return False
682        else:
683            return self.has_simple_content() or self.mixed and self.is_emptiable()
684
685    def has_restriction(self) -> bool:
686        return self.derivation == 'restriction'
687
688    def has_extension(self) -> bool:
689        return self.derivation == 'extension'
690
691    def text_decode(self, text: str) -> Optional[AtomicValueType]:
692        if isinstance(self.content, XsdSimpleType):
693            return cast(Optional[AtomicValueType], self.content.decode(text, 'skip'))
694        else:
695            return text
696
697    def decode(self, obj: Union[ElementType, str, bytes], *args: Any, **kwargs: Any) \
698            -> DecodeType[Any]:
699        if not isinstance(obj, (str, bytes)):
700            return super(XsdComplexType, self).decode(obj, *args, **kwargs)
701        elif isinstance(self.content, XsdSimpleType):
702            return self.content.decode(obj, *args, **kwargs)
703        else:
704            raise XMLSchemaDecodeError(
705                self, obj, str, "cannot decode %r data with %r" % (obj, self)
706            )
707
708    def iter_decode(self, obj: Union[ElementType, str, bytes],
709                    validation: str = 'lax', **kwargs: Any) -> IterDecodeType[Any]:
710        """
711        Decodes an Element instance using a dummy XSD element. Typically used
712        for decoding with xs:anyType when an XSD element is not available.
713        Also decodes strings if the type has a simple content.
714
715        :param obj: the XML data that has to be decoded.
716        :param validation: the validation mode. Can be 'lax', 'strict' or 'skip'.
717        :param kwargs: keyword arguments for the decoding process.
718        :return: yields a decoded object, eventually preceded by a sequence of \
719        validation or decoding errors.
720        """
721        if not isinstance(obj, (str, bytes)):
722            xsd_element = self.schema.create_element(obj.tag, parent=self, form='unqualified')
723            xsd_element.type = self
724            yield from xsd_element.iter_decode(obj, validation, **kwargs)
725        elif isinstance(self.content, XsdSimpleType):
726            yield from self.content.iter_decode(obj, validation, **kwargs)
727        else:
728            raise XMLSchemaDecodeError(
729                self, obj, str, "cannot decode %r data with %r" % (obj, self)
730            )
731
732    def iter_encode(self, obj: Any, validation: str = 'lax', **kwargs: Any) \
733            -> IterEncodeType[ElementType]:
734        """
735        Encode XML data. A dummy element is created for the type and it's used for
736        encode data. Typically used for encoding with xs:anyType when an XSD element
737        is not available.
738
739        :param obj: decoded XML data.
740        :param validation: the validation mode: can be 'lax', 'strict' or 'skip'.
741        :param kwargs: keyword arguments for the encoding process.
742        :return: yields an Element, eventually preceded by a sequence of \
743        validation or encoding errors.
744        """
745        try:
746            name, value = obj
747        except ValueError:
748            name = obj.name
749            value = obj
750
751        xsd_element = self.schema.create_element(name, parent=self, form='unqualified')
752        xsd_element.type = self
753
754        if isinstance(value, MutableSequence) and not isinstance(value, dataobjects.DataElement):
755            try:
756                results = [x for item in value for x in xsd_element.iter_encode(
757                    item, validation, **kwargs
758                )]
759            except XMLSchemaValueError:
760                pass
761            else:
762                yield from results
763                return
764
765        yield from xsd_element.iter_encode(value, validation, **kwargs)
766
767
768class Xsd11ComplexType(XsdComplexType):
769    """
770    Class for XSD 1.1 *complexType* definitions.
771
772    ..  <complexType
773          abstract = boolean : false
774          block = (#all | List of (extension | restriction))
775          final = (#all | List of (extension | restriction))
776          id = ID
777          mixed = boolean
778          name = NCName
779          defaultAttributesApply = boolean : true
780          {any attributes with non-schema namespace . . .}>
781          Content: (annotation?, (simpleContent | complexContent | (openContent?,
782          (group | all | choice | sequence)?,
783          ((attribute | attributeGroup)*, anyAttribute?), assert*)))
784        </complexType>
785    """
786    default_attributes_apply = True
787
788    _CONTENT_TAIL_TAGS = {XSD_ATTRIBUTE_GROUP, XSD_ATTRIBUTE, XSD_ANY_ATTRIBUTE, XSD_ASSERT}
789
790    @property
791    def default_attributes(self) -> Optional[XsdAttributeGroup]:
792        if self.redefine is not None:
793            default_attributes = self.schema.default_attributes
794        else:
795            for child in self.schema.root:
796                if child.tag == XSD_OVERRIDE and self.elem in child:
797                    schema = self.schema.includes[child.attrib['schemaLocation']]
798                    if schema.override is self.schema:
799                        default_attributes = schema.default_attributes
800                        break
801            else:
802                default_attributes = self.schema.default_attributes
803
804        if isinstance(default_attributes, str):
805            return None
806        return default_attributes
807
808    @property
809    def default_open_content(self) -> Optional[XsdDefaultOpenContent]:
810        if self.parent is not None:
811            return self.schema.default_open_content
812
813        for child in self.schema.root:
814            if child.tag == XSD_OVERRIDE and self.elem in child:
815                schema = self.schema.includes[child.attrib['schemaLocation']]
816                if schema.override is self.schema:
817                    return schema.default_open_content
818        else:
819            return self.schema.default_open_content
820
821    def _parse(self) -> None:
822        super(Xsd11ComplexType, self)._parse()
823
824        if self.base_type and self.base_type.base_type is self.any_simple_type and \
825                self.base_type.derivation == 'extension' and not self.attributes:
826            # Derivation from xs:anySimpleType with missing variety.
827            # See: http://www.w3.org/TR/xmlschema11-1/#Simple_Type_Definition_details
828            msg = "the simple content of {!r} is not a valid simple type in XSD 1.1"
829            self.parse_error(msg.format(self.base_type))
830
831        # Add open content to a complex content type
832        if isinstance(self.content, XsdGroup):
833            if self.open_content is None:
834                if self.content.interleave is not None or self.content.suffix is not None:
835                    self.parse_error("openContent mismatch between type and model group")
836            elif self.open_content.mode == 'interleave':
837                self.content.interleave = self.content.suffix \
838                    = self.open_content.any_element
839            elif self.open_content.mode == 'suffix':
840                self.content.suffix = self.open_content.any_element
841
842        # Add inheritable attributes
843        if isinstance(self.base_type, XsdComplexType):
844            for name, attr in self.base_type.attributes.items():
845                if attr.inheritable:
846                    if name not in self.attributes:
847                        self.attributes[name] = attr
848                    elif not self.attributes[name].inheritable:
849                        self.parse_error("attribute %r must be inheritable")
850
851        if 'defaultAttributesApply' not in self.elem.attrib:
852            self.default_attributes_apply = True
853        elif self.elem.attrib['defaultAttributesApply'].strip() in {'false', '0'}:
854            self.default_attributes_apply = False
855        else:
856            self.default_attributes_apply = True
857
858        # Add default attributes
859        if self.default_attributes_apply and \
860                isinstance(self.default_attributes, XsdAttributeGroup):
861            if self.redefine is None:
862                for k in self.default_attributes:
863                    if k in self.attributes:
864                        self.parse_error(f"default attribute {k!r} is already "
865                                         f"declared in the complex type")
866
867            self.attributes.update((k, v) for k, v in self.default_attributes.items())
868
869    def _parse_complex_content_extension(self, elem: ElementType, base_type: Any) -> None:
870        # Complex content extension with simple base is forbidden XSD 1.1.
871        # For the detailed rule refer to XSD 1.1 documentation:
872        #   https://www.w3.org/TR/2012/REC-xmlschema11-1-20120405/#sec-cos-ct-extends
873        if base_type.is_simple() or base_type.has_simple_content():
874            self.parse_error("base %r is simple or has a simple content." % base_type, elem)
875            base_type = self.any_type
876
877        if 'extension' in base_type.final:
878            self.parse_error("the base type is not derivable by extension")
879
880        # Parse openContent
881        group_elem: Any
882        for group_elem in elem:
883            if group_elem.tag == XSD_ANNOTATION or callable(group_elem.tag):
884                continue
885            elif group_elem.tag != XSD_OPEN_CONTENT:
886                break
887            self.open_content = XsdOpenContent(group_elem, self.schema, self)
888            try:
889                any_element = base_type.open_content.any_element
890                self.open_content.any_element.union(any_element)
891            except AttributeError:
892                pass
893        else:
894            group_elem = None
895
896        if not base_type.content:
897            if not base_type.mixed:
898                # Empty element-only model extension: don't create a nested sequence group.
899                if group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
900                    self.content = self.schema.xsd_group_class(
901                        group_elem, self.schema, self
902                    )
903                elif base_type.content.max_occurs is None:
904                    self.content = self.schema.create_empty_content_group(
905                        parent=self,
906                        model=base_type.content.model,
907                        minOccurs=str(base_type.content.min_occurs),
908                        maxOccurs='unbounded',
909                    )
910                else:
911                    self.content = self.schema.create_empty_content_group(
912                        parent=self,
913                        model=base_type.content.model,
914                        minOccurs=str(base_type.content.min_occurs),
915                        maxOccurs=str(base_type.content.max_occurs),
916                    )
917
918            elif base_type.mixed:
919                # Empty mixed model extension
920                self.content = self.schema.create_empty_content_group(self)
921                self.content.append(self.schema.create_empty_content_group(self.content))
922
923                if group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
924                    group = self.schema.xsd_group_class(
925                        group_elem, self.schema, self.content
926                    )
927                    if not self.mixed:
928                        self.parse_error("base has a different content type (mixed=%r) and the "
929                                         "extension group is not empty." % base_type.mixed, elem)
930                    if group.model == 'all':
931                        self.parse_error("cannot extend an empty mixed content with an xs:all")
932                else:
933                    group = self.schema.create_empty_content_group(self)
934
935                self.content.append(group)
936                self.content.elem.append(base_type.content.elem)
937                self.content.elem.append(group.elem)
938
939        elif group_elem is not None and group_elem.tag in XSD_MODEL_GROUP_TAGS:
940            group = self.schema.xsd_group_class(group_elem, self.schema, self)
941
942            if base_type.content.model != 'all':
943                content = self.schema.create_empty_content_group(self)
944                content.append(base_type.content)
945                content.elem.append(base_type.content.elem)
946
947                if group.model == 'all':
948                    msg = "xs:all cannot extend a not empty xs:%s"
949                    self.parse_error(msg % base_type.content.model)
950                else:
951                    content.append(group)
952                    content.elem.append(group.elem)
953            else:
954                content = self.schema.create_empty_content_group(
955                    self, model='all', minOccurs=str(base_type.content.min_occurs)
956                )
957                content.extend(base_type.content)
958                content.elem.extend(base_type.content.elem)
959
960                if not group:
961                    pass
962                elif group.model != 'all':
963                    self.parse_error(
964                        "cannot extend a not empty 'all' model group with a different model"
965                    )
966                elif base_type.content.min_occurs != group.min_occurs:
967                    self.parse_error("when extend an xs:all group minOccurs must be the same")
968                elif base_type.mixed and not base_type.content:
969                    self.parse_error("cannot extend an xs:all group with mixed empty content")
970                else:
971                    content.extend(group)
972                    content.elem.extend(group.elem)
973
974            if base_type.mixed != self.mixed and base_type.name != XSD_ANY_TYPE:
975                self.parse_error("base has a different content type (mixed=%r) and the "
976                                 "extension group is not empty." % base_type.mixed, elem)
977
978            self.content = content
979
980        elif base_type.is_simple():
981            self.content = base_type
982        elif base_type.has_simple_content():
983            self.content = base_type.content
984        else:
985            self.content = self.schema.create_empty_content_group(self)
986            self.content.append(base_type.content)
987            self.content.elem.append(base_type.content.elem)
988            if base_type.mixed != self.mixed and base_type.name != XSD_ANY_TYPE and self.mixed:
989                self.parse_error(
990                    "extended type has a mixed content but the base is element-only", elem
991                )
992
993        if self.open_content is None:
994            default_open_content = self.default_open_content
995            if default_open_content is not None and \
996                    (self.mixed or self.content or default_open_content.applies_to_empty):
997                self.open_content = default_open_content
998            elif base_type.open_content is not None:
999                self.open_content = base_type.open_content
1000
1001        if base_type.open_content is not None and \
1002                self.open_content is not None and \
1003                self.open_content is not base_type.open_content:
1004
1005            if self.open_content.mode == 'none':
1006                self.open_content = base_type.open_content
1007            elif not base_type.open_content.is_restriction(self.open_content):
1008                msg = "{!r} is not an extension of the base type {!r}"
1009                self.parse_error(msg.format(self.open_content, base_type.open_content))
1010
1011        self._parse_content_tail(elem, derivation='extension',
1012                                 base_attributes=base_type.attributes)
1013
1014    def _parse_content_tail(self, elem: ElementType, **kwargs: Any) -> None:
1015        self.attributes = self.schema.xsd_attribute_group_class(
1016            elem, self.schema, self, **kwargs
1017        )
1018
1019        self.assertions = [XsdAssert(e, self.schema, self, self)
1020                           for e in elem if e.tag == XSD_ASSERT]
1021        if isinstance(self.base_type, XsdComplexType):
1022            self.assertions.extend(
1023                XsdAssert(assertion.elem, self.schema, self, self)
1024                for assertion in self.base_type.assertions
1025            )
1026