Source code for xsdata.models.elements

from dataclasses import dataclass
from dataclasses import field
from pathlib import Path
from typing import Any as Anything
from typing import Dict
from typing import Iterator
from typing import List as Array
from typing import Optional
from typing import Union as UnionType

from xsdata.exceptions import SchemaValueError
from xsdata.formats.dataclass.serializers import XmlSerializer
from xsdata.models.enums import DataType
from xsdata.models.enums import FormType
from xsdata.models.enums import Mode
from xsdata.models.enums import Namespace
from xsdata.models.enums import NamespaceType
from xsdata.models.enums import ProcessType
from xsdata.models.enums import TagType
from xsdata.models.enums import UseType
from xsdata.models.mixins import ElementBase
from xsdata.utils.text import collapse_whitespace


[docs]def attribute(default=None, init=True, **kwargs): kwargs.update(type=TagType.ATTRIBUTE) return field(init=init, default=default, metadata=kwargs)
[docs]def element(init=True, **kwargs): kwargs.update(type=TagType.ELEMENT) return field(init=init, default=None, metadata=kwargs)
[docs]def array_element(init=True, **kwargs): kwargs.update(type=TagType.ELEMENT) return field(init=init, default_factory=list, metadata=kwargs)
[docs]def array_any_element(init=True, **kwargs): kwargs.update(type=TagType.ANY, namespace=NamespaceType.ANY.value) return field(init=init, default_factory=list, metadata=kwargs)
[docs]@dataclass(frozen=True) class XmlString: elements: Array[object] = array_any_element()
[docs] def render(self): name = self.__class__.__name__ xml = XmlSerializer(pretty_print=True, xml_declaration=False).render(self) return xml[xml.find(">") + 1 :].replace(f"</{name}>", "").strip()
[docs]@dataclass class Documentation(ElementBase): """ <documentation source = anyURI xml:lang = language {any attributes with non-schema namespace . . .}> Content: ({any})* </documentation> """
[docs] class Meta: mixed = True
lang: Optional[str] = attribute() source: Optional[str] = attribute() elements: Array[object] = array_any_element() attributes: Optional["AnyAttribute"] = element()
[docs] def tostring(self) -> Optional[str]: if self.elements: return XmlString(self.elements).render() else: return None
[docs]@dataclass class Appinfo(ElementBase): """ <appinfo source = anyURI {any attributes with non-schema namespace . . .}> Content: ({any})* </appinfo> """
[docs] class Meta: mixed = True
source: Optional[str] = attribute() elements: Array[object] = array_any_element() any_attribute: Optional["AnyAttribute"] = element()
[docs]@dataclass class Annotation(ElementBase): """ <annotation id = ID {any attributes with non-schema namespace . . .}> Content: (appinfo | documentation)* </annotation> """ appinfo: Optional[Appinfo] = element() documentations: Array[Documentation] = array_element(name="documentation") any_attribute: Optional["AnyAttribute"] = element()
[docs]@dataclass class AnnotationBase(ElementBase): """Base Class for elements that can contain annotations.""" annotation: Optional[Annotation] = element() any_attribute: Optional["AnyAttribute"] = element() @property def display_help(self) -> Optional[str]: if self.annotation and len(self.annotation.documentations): return "\n".join( filter(None, [doc.tostring() for doc in self.annotation.documentations]) ) return None
[docs]@dataclass class AnyAttribute(AnnotationBase): """ <anyAttribute id = ID namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local))) notNamespace = List of (anyURI | (##targetNamespace | ##local)) notQName = List of (QName | ##defined) processContents = (lax | skip | strict) : strict {any attributes with non-schema namespace . . .}> Content: (annotation?) </anyAttribute> """ namespace: Optional[str] = attribute(default="##any") process_contents: Optional[ProcessType] = attribute() def __post_init__(self): self.namespace = collapse_whitespace(self.namespace) @property def is_attribute(self) -> bool: return True @property def is_wildcard(self) -> bool: return True @property def raw_namespace(self) -> Optional[str]: return self.namespace @property def real_name(self) -> str: return f"{self.namespace}_attributes" @property def real_type(self) -> Optional[str]: prefix = self.schema_prefix() suffix = DataType.QMAP.code return f"{prefix}:{suffix}" if prefix else suffix
[docs]@dataclass class Assertion(AnnotationBase): """ <assertion id = ID test = an XPath expression xpathDefaultNamespace = (anyURI | (##defaultNamespace | ##targetNamespace | ##local)) {any attributes with non-schema namespace . . .}> Content: (annotation?) </assertion> """ test: Optional[str] = attribute()
[docs]@dataclass class SimpleType(AnnotationBase): """ <simpleType final = (#all | List of (list | union | restriction | extension)) id = ID name = NCName {any attributes with non-schema namespace . . .}> Content: (annotation?, (restriction | list | union)) </simpleType> """ name: Optional[str] = attribute() restriction: Optional["Restriction"] = element() list: Optional["List"] = element() union: Optional["Union"] = element() @property def is_enumeration(self): return self.restriction and len(self.restriction.enumerations) > 0 @property def is_attribute(self) -> bool: return self.is_enumeration @property def real_type(self) -> Optional[str]: if self.restriction: return self.restriction.real_type if self.list: return self.list.real_type if self.union: return self.union.member_types return None
[docs] def get_restrictions(self) -> Dict[str, Anything]: if self.restriction: return self.restriction.get_restrictions() if self.list: return self.list.get_restrictions() return dict()
[docs]@dataclass class List(AnnotationBase): """ <list id = ID itemType = QName {any attributes with non-schema namespace . . .}> Content: (annotation?, simpleType?) </list> """ simple_type: Optional[SimpleType] = element() item_type: Optional[str] = attribute() @property def is_attribute(self) -> bool: return True @property def real_name(self) -> str: return "value" @property def real_type(self) -> Optional[str]: return None
[docs]@dataclass class Union(AnnotationBase): """ <union id = ID memberTypes = List of QName {any attributes with non-schema namespace . . .}> Content: (annotation?, simpleType*) </union> """ member_types: Optional[str] = attribute() simple_types: Array[SimpleType] = array_element(name="simpleType") @property def extends(self) -> Optional[str]: if self.member_types: return self.member_types return None @property def is_attribute(self) -> bool: return True @property def real_type(self) -> Optional[str]: types = [] if self.simple_types: types.extend( [ simple_type.real_type for simple_type in self.simple_types if simple_type.real_type ] ) if self.member_types: types.extend([member for member in self.member_types.split(" ") if member]) return " ".join(types) if types else None @property def real_name(self) -> str: return "value"
[docs] def get_restrictions(self) -> Dict[str, Anything]: restrictions = dict() for simple_type in self.simple_types: restrictions.update(simple_type.get_restrictions()) return restrictions
[docs]@dataclass class Attribute(AnnotationBase): """ <attribute default = string fixed = string form = (qualified | unqualified) id = ID name = NCName ref = QName targetNamespace = anyURI type = QName use = (optional | prohibited | required) : optional inheritable = boolean {any attributes with non-schema namespace . . .}> Content: (annotation?, simpleType?) </attribute> """ default: Optional[str] = attribute() fixed: Optional[str] = attribute() form: Optional[FormType] = attribute() name: Optional[str] = attribute() ref: Optional[str] = attribute() type: Optional[str] = attribute() target_namespace: Optional[str] = attribute(name="targetNamespace") simple_type: Optional[SimpleType] = element() use: Optional[UseType] = attribute(default=UseType.OPTIONAL) @property def is_attribute(self) -> bool: return True @property def real_type(self) -> Optional[str]: if self.simple_type: return self.simple_type.real_type if self.type: return self.type if self.ref: return self.ref return None
[docs] def get_restrictions(self) -> Dict[str, Anything]: restrictions = dict() if self.use == UseType.REQUIRED: restrictions.update({"min_occurs": 1, "max_occurs": 1, "required": True}) elif self.use == UseType.PROHIBITED: restrictions.update({"prohibited": True}) if self.simple_type: restrictions.update(self.simple_type.get_restrictions()) return restrictions
[docs]@dataclass class AttributeGroup(AnnotationBase): """ <attributeGroup id = ID ref = QName {any attributes with non-schema namespace . . .}> Content: (annotation?) </attributeGroup> """ name: Optional[str] = attribute() ref: Optional[str] = attribute() attributes: Array[Attribute] = array_element(name="attribute") attribute_groups: Array["AttributeGroup"] = array_element(name="attributeGroup") @property def is_attribute(self) -> bool: return True @property def real_type(self) -> Optional[str]: return self.ref
[docs]@dataclass class Any(AnnotationBase): """ <any id = ID maxOccurs = (nonNegativeInteger | unbounded) : 1 minOccurs = nonNegativeInteger : 1 namespace = ((##any | ##other) | List of (anyURI | (##targetNamespace | ##local))) notNamespace = List of (anyURI | (##targetNamespace | ##local)) notQName = List of (QName | (##defined | ##definedSibling)) processContents = (lax | skip | strict) : strict {any attributes with non-schema namespace . . .}> Content: (annotation?) </any> """ min_occurs: int = attribute(default=1) max_occurs: int = attribute(default=1) namespace: Optional[str] = attribute(default="##any") process_contents: Optional[ProcessType] = attribute() def __post_init__(self): self.namespace = collapse_whitespace(self.namespace) @property def is_attribute(self) -> bool: return True @property def is_wildcard(self) -> bool: return True @property def real_name(self) -> str: return f"{self.namespace}_element" @property def raw_namespace(self) -> Optional[str]: return self.namespace @property def real_type(self) -> Optional[str]: prefix = self.schema_prefix() suffix = DataType.OBJECT.code return f"{prefix}:{suffix}" if prefix else suffix
[docs] def get_restrictions(self) -> Dict[str, Anything]: return {"min_occurs": self.min_occurs, "max_occurs": self.max_occurs}
[docs]@dataclass class All(AnnotationBase): """ <all id = ID maxOccurs = (0 | 1) : 1 minOccurs = (0 | 1) : 1 {any attributes with non-schema namespace . . .}> Content: (annotation?, (element | any | group)*) </all> """ min_occurs: int = attribute(default=1) max_occurs: int = attribute(default=1) any: Array[Any] = array_element(name="any") elements: Array["Element"] = array_element(name="element") groups: Array["Group"] = array_element(name="group")
[docs] def get_restrictions(self) -> Dict[str, Anything]: return {"min_occurs": self.min_occurs, "max_occurs": self.max_occurs}
[docs]@dataclass class Sequence(AnnotationBase): """ <sequence id = ID maxOccurs = (nonNegativeInteger | unbounded) : 1 minOccurs = nonNegativeInteger : 1 {any attributes with non-schema namespace . . .}> Content: (annotation?, (element | group | choice | sequence | any)*) </sequence> """ min_occurs: int = attribute(default=1) max_occurs: int = attribute(default=1) elements: Array["Element"] = array_element(name="element") groups: Array["Group"] = array_element(name="group") choices: Array["Choice"] = array_element(name="choice") sequences: Array["Sequence"] = array_element(name="sequence") any: Array["Any"] = array_element()
[docs] def get_restrictions(self) -> Dict[str, Anything]: return { "min_occurs": self.min_occurs, "max_occurs": self.max_occurs, "sequential": True, }
[docs]@dataclass class Choice(AnnotationBase): """ <choice id = ID maxOccurs = (nonNegativeInteger | unbounded) : 1 minOccurs = nonNegativeInteger : 1 {any attributes with non-schema namespace . . .}> Content: (annotation?, (element | group | choice | sequence | any)*) </choice> """ min_occurs: int = attribute(default=1) max_occurs: int = attribute(default=1) elements: Array["Element"] = array_element(name="element") groups: Array["Group"] = array_element(name="group") choices: Array["Choice"] = array_element(name="choice") sequences: Array[Sequence] = array_element(name="sequence") any: Array["Any"] = array_element()
[docs] def get_restrictions(self) -> Dict[str, Anything]: return { "min_occurs": self.min_occurs if self.min_occurs > 1 else 0, "max_occurs": self.max_occurs, }
[docs]@dataclass class Group(AnnotationBase): """ <group id = ID maxOccurs = (nonNegativeInteger | unbounded) : 1 minOccurs = nonNegativeInteger : 1 name = NCName ref = QName {any attributes with non-schema namespace . . .}> Content: (annotation?, (all | choice | sequence)?) </group> """ name: Optional[str] = attribute() ref: Optional[str] = attribute() min_occurs: int = attribute(default=1) max_occurs: int = attribute(default=1) all: Optional[All] = element() choice: Optional[Choice] = element() sequence: Optional[Sequence] = element() @property def is_attribute(self) -> bool: return True @property def real_type(self) -> Optional[str]: return self.ref
[docs] def get_restrictions(self) -> Dict[str, Anything]: return {"min_occurs": self.min_occurs, "max_occurs": self.max_occurs}
[docs]@dataclass class OpenContent(AnnotationBase): """ <openContent id = ID mode = (none | interleave | suffix) : interleave {any attributes with non-schema namespace . . .}> Content: (annotation?, any?) </openContent> """ applies_to_empty: bool = attribute(default=False, name="appliesToEmpty") mode: Mode = attribute(default=Mode.INTERLEAVE) any: Any = element()
[docs]@dataclass class DefaultOpenContent(OpenContent): """ <defaultOpenContent appliesToEmpty = boolean : false id = ID mode = (interleave | suffix) : interleave {any attributes with non-schema namespace . . .}> Content: (annotation?, any) </defaultOpenContent> """
[docs]@dataclass class Extension(AnnotationBase): """ <extension base = QName id = ID {any attributes with non-schema namespace . . .}> Content: (annotation?, ((attribute | attributeGroup)*, anyAttribute?), assert*) </extension> """ base: Optional[str] = attribute() group: Optional[Group] = element() all: Optional[All] = element() choice: Optional[Choice] = element() sequence: Optional[Sequence] = element() any_attribute: Optional[AnyAttribute] = element() open_content: Optional[OpenContent] = element(name="openContent") attributes: Array[Attribute] = array_element(name="attribute") attribute_groups: Array[AttributeGroup] = array_element(name="attributeGroup") assertions: Array[Assertion] = array_element(name="assert") @property def extends(self) -> Optional[str]: return self.base
[docs]@dataclass class Enumeration(AnnotationBase): """ <enumeration id = ID value = anySimpleType {any attributes with non-schema namespace . . .}> Content: (annotation?) </enumeration> """ value: str = attribute() @property def is_attribute(self) -> bool: return True @property def real_type(self): return None @property def real_name(self): return self.value @property def default(self): return self.value
[docs]@dataclass class FractionDigits(AnnotationBase): """ <fractionDigits fixed = boolean : false id = ID value = nonNegativeInteger {any attributes with non-schema namespace . . .}> Content: (annotation?) </fractionDigits> """ value: int = attribute()
[docs]@dataclass class Length(AnnotationBase): """ <length fixed = boolean : false id = ID value = nonNegativeInteger {any attributes with non-schema namespace . . .}> Content: (annotation?) </length> """ value: int = attribute()
[docs]@dataclass class MaxExclusive(AnnotationBase): """ <maxExclusive fixed = boolean : false id = ID value = anySimpleType {any attributes with non-schema namespace . . .}> Content: (annotation?) </maxExclusive> """ value: float = attribute()
[docs]@dataclass class MaxInclusive(AnnotationBase): """ <maxInclusive fixed = boolean : false id = ID value = anySimpleType {any attributes with non-schema namespace . . .}> Content: (annotation?) </maxInclusive> """ value: float = attribute()
[docs]@dataclass class MaxLength(AnnotationBase): """ <maxLength fixed = boolean : false id = ID value = nonNegativeInteger {any attributes with non-schema namespace . . .}> Content: (annotation?) </maxLength> """ value: float = attribute()
[docs]@dataclass class MinExclusive(AnnotationBase): """ <minExclusive fixed = boolean : false id = ID value = anySimpleType {any attributes with non-schema namespace . . .}> Content: (annotation?) </minExclusive> """ value: float = attribute()
[docs]@dataclass class MinInclusive(AnnotationBase): """ <minInclusive fixed = boolean : false id = ID value = anySimpleType {any attributes with non-schema namespace . . .}> Content: (annotation?) </minInclusive> """ value: float = attribute()
[docs]@dataclass class MinLength(AnnotationBase): """ <minLength fixed = boolean : false id = ID value = nonNegativeInteger {any attributes with non-schema namespace . . .}> Content: (annotation?) </minLength> """ value: float = attribute()
[docs]@dataclass class Pattern(AnnotationBase): """ <pattern id = ID value = string {any attributes with non-schema namespace . . .}> Content: (annotation?) </pattern> """ value: str = attribute()
[docs]@dataclass class TotalDigits(AnnotationBase): """ <totalDigits fixed = boolean : false id = ID value = positiveInteger {any attributes with non-schema namespace . . .}> Content: (annotation?) </totalDigits> """ value: int = attribute()
[docs]@dataclass class WhiteSpace(AnnotationBase): """ <whiteSpace fixed = boolean : false id = ID value = (collapse | preserve | replace) {any attributes with non-schema namespace . . .}> Content: (annotation?) </whiteSpace> """ value: str = attribute() # preserve, collapse, replace
[docs]@dataclass class ExplicitTimezone(AnnotationBase): """ <explicitTimezone fixed = boolean : false id = ID value = NCName {any attributes with non-schema namespace . . .}> Content: (annotation?) </explicitTimezone> """ value: str = attribute() fixed: bool = attribute(default=False)
[docs]@dataclass class Restriction(AnnotationBase): """ <restriction base = QName id = ID {any attributes with non-schema namespace . . .}> Content: (annotation?, (simpleType?, ( minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern | assertion | explicitTimezone | {any with namespace: ##other})*) ) </restriction> """ base: Optional[str] = attribute() group: Optional[Group] = element() all: Optional[All] = element() choice: Optional[Choice] = element() sequence: Optional[Sequence] = element() open_content: Optional[OpenContent] = element(name="openContent") attributes: Array[Attribute] = array_element(name="attribute") attribute_groups: Array[AttributeGroup] = array_element(name="attributeGroup") enumerations: Array[Enumeration] = array_element(name="enumeration") asserts: Array[Assertion] = array_element(name="assert") assertions: Array[Assertion] = array_element(name="assertion") any_element: Array[object] = array_any_element() min_exclusive: Optional[MinExclusive] = element() min_inclusive: Optional[MinInclusive] = element() min_length: Optional[MinLength] = element() max_exclusive: Optional[MaxExclusive] = element() max_inclusive: Optional[MaxInclusive] = element() max_length: Optional[MaxLength] = element() total_digits: Optional[TotalDigits] = element() fraction_digits: Optional[FractionDigits] = element() length: Optional[Length] = element() white_space: Optional[WhiteSpace] = element() patterns: Array[Pattern] = array_element(name="pattern") explicit_timezone: Optional[ExplicitTimezone] = element() simple_type: Optional[SimpleType] = element() @property def real_type(self) -> Optional[str]: if self.simple_type: return self.simple_type.real_type return self.base @property def real_name(self) -> str: return "value" @property def extends(self) -> Optional[str]: return self.base
[docs] def get_restrictions(self) -> Dict[str, Anything]: keys = ( "min_exclusive", "min_inclusive", "min_length", "max_exclusive", "max_inclusive", "max_length", "total_digits", "fraction_digits", "length", "white_space", "explicit_timezone", ) restrictions = { key: getattr(self, key).value for key in keys if getattr(self, key) is not None } if self.patterns: restrictions["pattern"] = "|".join( [pattern.value for pattern in self.patterns] ) return restrictions
[docs]@dataclass class SimpleContent(AnnotationBase): """ <simpleContent id = ID {any attributes with non-schema namespace . . .}> Content: (annotation?, (restriction | extension)) </simpleContent> """ restriction: Optional[Restriction] = element() extension: Optional[Extension] = element()
[docs]@dataclass class ComplexContent(SimpleContent): """ <complexContent id = ID mixed = boolean {any attributes with non-schema namespace . . .}> Content: (annotation?, (restriction | extension)) </complexContent> """ mixed: bool = attribute(default=False)
[docs]@dataclass class ComplexType(AnnotationBase): """ <complexType abstract = boolean : false block = (#all | List of (extension | restriction)) final = (#all | List of (extension | restriction)) id = ID mixed = boolean name = NCName defaultAttributesApply = boolean : true {any attributes with non-schema namespace . . .}> Content: (annotation?, ( simpleContent | complexContent | (openContent?, (group | all | choice | sequence)?, ((attribute | attributeGroup)*, anyAttribute?), assert*)) ) </complexType> """ name: Optional[str] = attribute() block: Optional[str] = attribute() final: Optional[str] = attribute() simple_content: Optional[SimpleContent] = element() complex_content: Optional[ComplexContent] = element() group: Optional[Group] = element() all: Optional[All] = element() choice: Optional[Choice] = element() sequence: Optional[Sequence] = element() any_attribute: Optional[AnyAttribute] = element() open_content: Optional[OpenContent] = element(name="openContent") attributes: Array[Attribute] = array_element(name="attribute") attribute_groups: Array[AttributeGroup] = array_element(name="attributeGroup") assertion: Array[Assertion] = array_element(name="assert") abstract: bool = attribute(default=False) mixed: bool = attribute(default=False) default_attributes_apply: bool = attribute( default=True, name="defaultAttributesApply" ) @property def is_mixed(self) -> bool: if self.mixed: return True elif self.complex_content and self.complex_content.mixed: return True else: return False
[docs]@dataclass class Field(AnnotationBase): """ <field id = ID xpath = a subset of XPath expression, see below xpathDefaultNamespace = (anyURI | (##defaultNamespace | ##targetNamespace | ##local)) {any attributes with non-schema namespace . . .}> Content: (annotation?) </field> """ xpath: Optional[str] = attribute()
[docs]@dataclass class Selector(Field): """ <selector id = ID xpath = a subset of XPath expression, see below xpathDefaultNamespace = (anyURI | (##defaultNamespace | ##targetNamespace | ##local)) {any attributes with non-schema namespace . . .}> Content: (annotation?) </selector> """
[docs]@dataclass class Unique(AnnotationBase): """ <unique id = ID name = NCName ref = QName {any attributes with non-schema namespace . . .}> Content: (annotation?, (selector, field+)?) </unique> """ name: Optional[str] = attribute() selector: Optional[Selector] = element() fields: Array[Field] = array_element(name="field")
[docs]@dataclass class Key(AnnotationBase): """ <key id = ID name = NCName ref = QName {any attributes with non-schema namespace . . .}> Content: (annotation?, (selector, field+)?) </key> """ name: Optional[str] = attribute() selector: Optional[Selector] = element() fields: Array[Selector] = array_element(name="field")
[docs]@dataclass class Keyref(AnnotationBase): """ <keyref id = ID name = NCName ref = QName refer = QName {any attributes with non-schema namespace . . .}> Content: (annotation?, (selector, field+)?) </keyref> """ name: Optional[str] = attribute() refer: Optional[str] = attribute() selector: Optional[Selector] = element() fields: Array[Selector] = array_element(name="field")
[docs]@dataclass class Alternative(AnnotationBase): """ <alternative id = ID test = an XPath expression type = QName xpathDefaultNamespace = (anyURI | (##defaultNamespace | ##targetNamespace | ##local)) {any attributes with non-schema namespace . . .}> Content: (annotation?, (simpleType | complexType)?) </alternative> """ type: Optional[str] = attribute() test: Optional[str] = attribute() simple_type: Optional[SimpleType] = element() complex_type: Optional[ComplexType] = element()
[docs]@dataclass class Element(AnnotationBase): """ <element abstract = boolean : false block = (#all | List of (extension | restriction | substitution)) default = string final = (#all | List of (extension | restriction)) fixed = string form = (qualified | unqualified) id = ID maxOccurs = (nonNegativeInteger | unbounded) : 1 minOccurs = nonNegativeInteger : 1 name = NCName nillable = boolean : false ref = QName substitutionGroup = List of QName targetNamespace = anyURI type = QName {any attributes with non-schema namespace . . .}> Content: (annotation?, ((simpleType | complexType)?, alternative*, (unique | key | keyref)*)) </element> """ name: Optional[str] = attribute() id: Optional[str] = attribute() ref: Optional[str] = attribute() type: Optional[str] = attribute() substitution_group: Optional[str] = attribute(name="substitutionGroup") default: Optional[str] = attribute() fixed: Optional[str] = attribute() form: Optional[FormType] = attribute() block: Optional[str] = attribute() final: Optional[str] = attribute() target_namespace: Optional[str] = attribute(name="targetNamespace") simple_type: Optional[SimpleType] = element() complex_type: Optional[ComplexType] = element() alternatives: Array[Alternative] = array_element(name="alternative") uniques: Array[Unique] = array_element(name="unique") keys: Array[Key] = array_element(name="key") keyrefs: Array[Keyref] = array_element(name="keyref") min_occurs: int = attribute(default=1) max_occurs: int = attribute(default=1) nillable: bool = attribute(default=False) abstract: bool = attribute(default=False) @property def is_attribute(self) -> bool: return True @property def is_mixed(self) -> bool: if self.complex_type: return self.complex_type.is_mixed else: return False @property def raw_type(self) -> Optional[str]: if self.type: return self.type elif self.has_children: return None else: prefix = self.schema_prefix() suffix = DataType.ANY_TYPE.code return f"{prefix}:{suffix}" if prefix else suffix @property def real_type(self) -> Optional[str]: types = set( alternative.type for alternative in self.alternatives if alternative.type ) if self.type: types.add(self.type) elif self.ref: types.add(self.ref) elif self.simple_type and self.simple_type.real_type: types.add(self.simple_type.real_type) return " ".join(sorted(types)) or None @property def substitutions(self) -> Array[str]: if self.substitution_group: return list(filter(None, self.substitution_group.split(" "))) return list()
[docs] def get_restrictions(self) -> Dict[str, Anything]: restrictions = {"min_occurs": self.min_occurs, "max_occurs": self.max_occurs} if self.simple_type: restrictions.update(self.simple_type.get_restrictions()) if self.nillable: restrictions.update({"nillable": True}) return restrictions
[docs]@dataclass class Notation(AnnotationBase): """ <notation id = ID name = NCName public = token system = anyURI {any attributes with non-schema namespace . . .}> Content: (annotation?) </notation> """ name: Optional[str] = attribute() public: Optional[str] = attribute() system: Optional[str] = attribute()
[docs]@dataclass class SchemaLocation(AnnotationBase): location: Optional[Path] = field(default=None)
[docs]@dataclass class Import(SchemaLocation): """ <import id = ID namespace = anyURI schemaLocation = anyURI {any attributes with non-schema namespace . . .}> Content: (annotation?) </import> """ namespace: Optional[str] = attribute() schema_location: Optional[str] = attribute()
[docs]@dataclass class Include(SchemaLocation): """ <include id = ID schemaLocation = anyURI {any attributes with non-schema namespace . . .}> Content: (annotation?) </include> """ schema_location: Optional[str] = attribute()
[docs]@dataclass class Redefine(SchemaLocation): """ <redefine id = ID schemaLocation = anyURI {any attributes with non-schema namespace . . .}> Content: (annotation | (simpleType | complexType | group | attributeGroup))* </redefine> """ schema_location: Optional[str] = attribute() simple_types: Array[SimpleType] = array_element(name="simpleType") complex_types: Array[ComplexType] = array_element(name="complexType") groups: Array[Group] = array_element(name="group") attribute_groups: Array[AttributeGroup] = array_element(name="attributeGroup")
[docs]@dataclass class Override(SchemaLocation): """ <override id = ID schemaLocation = anyURI {any attributes with non-schema namespace . . .}> Content: ( annotation | (simpleType | complexType | group | attributeGroup | element | attribute | notation) )* </override> """ schema_location: Optional[str] = attribute() simple_types: Array[SimpleType] = array_element(name="simpleType") complex_types: Array[ComplexType] = array_element(name="complexType") groups: Array[Group] = array_element(name="group") attribute_groups: Array[AttributeGroup] = array_element(name="attributeGroup") elements: Array[Element] = array_element(name="element") attributes: Array[Attribute] = array_element(name="attribute") notations: Array[Notation] = array_element(name="notation")
[docs]@dataclass class Schema(SchemaLocation): """ <schema attributeFormDefault = (qualified | unqualified) : unqualified blockDefault = (#all | List of (extension | restriction | substitution)) : '' defaultAttributes = QName xpathDefaultNamespace = (anyURI | (##defaultNamespace | ##targetNamespace | ##local)) : ##local elementFormDefault = (qualified | unqualified) : unqualified finalDefault = (#all | List of (extension | restriction | list | union)) : '' id = ID targetNamespace = anyURI version = token xml:lang = language {any attributes with non-schema namespace . . .}> Content: ( (include | import | redefine | override | annotation)*, (defaultOpenContent, annotation*)?, ((simpleType | complexType | group | attributeGroup | element | attribute | notation), annotation*)*) </schema> """
[docs] class Meta: namespace = Namespace.XS.uri
target: Optional[str] = attribute() block_default: Optional[str] = attribute() default_attributes: Optional[str] = attribute(name="defaultAttributes") final_default: Optional[str] = attribute() target_namespace: Optional[str] = attribute() version: Optional[str] = attribute() xmlns: Optional[str] = attribute() element_form_default: FormType = attribute(default=FormType.UNQUALIFIED) attribute_form_default: FormType = attribute(default=FormType.UNQUALIFIED) default_open_content: Optional[DefaultOpenContent] = element( name="defaultOpenContent" ) includes: Array[Include] = array_element(name="include") imports: Array[Import] = array_element(name="import") redefines: Array[Redefine] = array_element(name="redefine") overrides: Array[Override] = array_element(name="override") annotations: Array[Annotation] = array_element(name="annotation") simple_types: Array[SimpleType] = array_element(name="simpleType") complex_types: Array[ComplexType] = array_element(name="complexType") groups: Array[Group] = array_element(name="group") attribute_groups: Array[AttributeGroup] = array_element(name="attributeGroup") elements: Array[Element] = array_element(name="element") attributes: Array[Attribute] = array_element(name="attribute") notations: Array[Notation] = array_element(name="notation")
[docs] def included(self) -> Iterator[UnionType[Import, Include, Redefine, Override]]: for imp in self.imports: yield imp for inc in self.includes: yield inc for red in self.redefines: yield red for over in self.overrides: yield over
@property def module(self) -> str: if self.location: return self.location.name if self.target_namespace: return Path(self.target_namespace).stem raise SchemaValueError("Unknown schema module") @property def target_prefix(self): return next( ( prefix for prefix, namespace in self.nsmap.items() if namespace == self.target_namespace ), None, )