Skip to main content

xsd_schema/parser/frames/
factory.rs

1// ============================================================================
2// Frame Factory
3// ============================================================================
4
5/// Create a frame for the given element
6///
7/// The namespace snapshot is used to resolve QName references in attributes
8/// (type, ref, base, substitutionGroup, etc.) during frame construction.
9pub fn create_frame(
10    local_name: &str,
11    attrs: &AttributeMap,
12    name_table: &NameTable,
13    source: Option<SourceRef>,
14    ns_snapshot: &NamespaceContextSnapshot,
15) -> SchemaResult<Box<dyn Frame>> {
16    let frame: Box<dyn Frame> = match local_name {
17        xsd_names::SCHEMA => Box::new(SchemaFrame::new(attrs, name_table, source, ns_snapshot)?),
18        xsd_names::SIMPLE_TYPE => Box::new(SimpleTypeFrame::new(attrs, name_table, source)?),
19        xsd_names::COMPLEX_TYPE => Box::new(ComplexTypeFrame::new(attrs, name_table, source)?),
20        xsd_names::ELEMENT => Box::new(ElementFrame::new(attrs, name_table, source, ns_snapshot)?),
21        xsd_names::ATTRIBUTE => Box::new(AttributeFrame::new(attrs, name_table, source, ns_snapshot)?),
22        xsd_names::GROUP => Box::new(GroupFrame::new(attrs, name_table, source, ns_snapshot)?),
23        xsd_names::ATTRIBUTE_GROUP => Box::new(AttributeGroupFrame::new(attrs, name_table, source, ns_snapshot)?),
24        xsd_names::NOTATION => Box::new(NotationFrame::new(attrs, name_table, source)?),
25        xsd_names::SIMPLE_CONTENT => Box::new(SimpleContentFrame::new(attrs, name_table, source)?),
26        xsd_names::COMPLEX_CONTENT => Box::new(ComplexContentFrame::new(attrs, name_table, source)?),
27        xsd_names::RESTRICTION => Box::new(RestrictionFrame::new(attrs, name_table, source, ns_snapshot)?),
28        xsd_names::EXTENSION => Box::new(ExtensionFrame::new(attrs, name_table, source, ns_snapshot)?),
29        xsd_names::LIST => Box::new(ListFrame::new(attrs, name_table, source, ns_snapshot)?),
30        xsd_names::UNION => Box::new(UnionFrame::new(attrs, name_table, source, ns_snapshot)?),
31        xsd_names::SEQUENCE => {
32            Box::new(ModelGroupFrame::new(Compositor::Sequence, attrs, name_table, source, ns_snapshot)?)
33        }
34        xsd_names::CHOICE => {
35            Box::new(ModelGroupFrame::new(Compositor::Choice, attrs, name_table, source, ns_snapshot)?)
36        }
37        xsd_names::ALL => {
38            Box::new(ModelGroupFrame::new(Compositor::All, attrs, name_table, source, ns_snapshot)?)
39        }
40        xsd_names::ANY => Box::new(AnyFrame::new(
41            attrs, name_table, source,
42            #[cfg(feature = "xsd11")] ns_snapshot,
43        )?),
44        xsd_names::ANY_ATTRIBUTE => Box::new(AnyAttributeFrame::new(
45            attrs, name_table, source,
46            #[cfg(feature = "xsd11")] ns_snapshot,
47        )?),
48        xsd_names::ANNOTATION => Box::new(AnnotationFrame::new(attrs, name_table, source)?),
49        xsd_names::APPINFO => Box::new(AppinfoFrame::new(attrs, name_table, source)?),
50        xsd_names::DOCUMENTATION => Box::new(DocumentationFrame::new(attrs, name_table, source)?),
51        xsd_names::INCLUDE => Box::new(IncludeFrame::new(attrs, name_table, source)?),
52        xsd_names::IMPORT => Box::new(ImportFrame::new(attrs, name_table, source)?),
53        xsd_names::REDEFINE => Box::new(RedefineFrame::new(attrs, name_table, source)?),
54        #[cfg(feature = "xsd11")]
55        xsd_names::OVERRIDE => Box::new(OverrideFrame::new(attrs, name_table, source)?),
56        xsd_names::KEY => Box::new(IdentityFrame::new(IdentityKind::Key, attrs, name_table, source, ns_snapshot)?),
57        xsd_names::KEYREF => Box::new(IdentityFrame::new(IdentityKind::Keyref, attrs, name_table, source, ns_snapshot)?),
58        xsd_names::UNIQUE => Box::new(IdentityFrame::new(IdentityKind::Unique, attrs, name_table, source, ns_snapshot)?),
59        xsd_names::SELECTOR => Box::new(SelectorFrame::new(attrs, name_table, source, ns_snapshot.clone())?),
60        xsd_names::FIELD => Box::new(FieldFrame::new(attrs, name_table, source, ns_snapshot.clone())?),
61        #[cfg(feature = "xsd11")]
62        xsd_names::ALTERNATIVE => Box::new(AlternativeFrame::new(attrs, name_table, source, ns_snapshot.clone())?),
63        #[cfg(feature = "xsd11")]
64        xsd_names::ASSERT => Box::new(AssertFrame::new(attrs, name_table, source, ns_snapshot.clone())?),
65        xsd_names::ENUMERATION => {
66            Box::new(FacetFrame::new(FacetKind::Enumeration, attrs, name_table, source, None)?)
67        }
68        xsd_names::PATTERN => Box::new(FacetFrame::new(FacetKind::Pattern, attrs, name_table, source, None)?),
69        xsd_names::MIN_INCLUSIVE => {
70            Box::new(FacetFrame::new(FacetKind::MinInclusive, attrs, name_table, source, None)?)
71        }
72        xsd_names::MAX_INCLUSIVE => {
73            Box::new(FacetFrame::new(FacetKind::MaxInclusive, attrs, name_table, source, None)?)
74        }
75        xsd_names::MIN_EXCLUSIVE => {
76            Box::new(FacetFrame::new(FacetKind::MinExclusive, attrs, name_table, source, None)?)
77        }
78        xsd_names::MAX_EXCLUSIVE => {
79            Box::new(FacetFrame::new(FacetKind::MaxExclusive, attrs, name_table, source, None)?)
80        }
81        xsd_names::MIN_LENGTH => Box::new(FacetFrame::new(FacetKind::MinLength, attrs, name_table, source, None)?),
82        xsd_names::MAX_LENGTH => Box::new(FacetFrame::new(FacetKind::MaxLength, attrs, name_table, source, None)?),
83        xsd_names::LENGTH => Box::new(FacetFrame::new(FacetKind::Length, attrs, name_table, source, None)?),
84        xsd_names::TOTAL_DIGITS => Box::new(FacetFrame::new(FacetKind::TotalDigits, attrs, name_table, source, None)?),
85        xsd_names::FRACTION_DIGITS => Box::new(FacetFrame::new(FacetKind::FractionDigits, attrs, name_table, source, None)?),
86        xsd_names::WHITE_SPACE => Box::new(FacetFrame::new(FacetKind::WhiteSpace, attrs, name_table, source, None)?),
87        #[cfg(feature = "xsd11")]
88        xsd_names::OPEN_CONTENT => Box::new(OpenContentFrame::new(attrs, name_table, source)?),
89        #[cfg(feature = "xsd11")]
90        xsd_names::DEFAULT_OPEN_CONTENT => {
91            Box::new(DefaultOpenContentFrame::new(attrs, name_table, source)?)
92        }
93        // XSD 1.1 facets
94        xsd_names::ASSERTION => {
95            Box::new(FacetFrame::new(FacetKind::Assertion, attrs, name_table, source, Some(ns_snapshot.clone()))?)
96        }
97        xsd_names::EXPLICIT_TIMEZONE => {
98            Box::new(FacetFrame::new(FacetKind::ExplicitTimezone, attrs, name_table, source, None)?)
99        }
100        _ => {
101            // Unknown element - skip it
102            Box::new(SkipFrame::new(source))
103        }
104    };
105
106    frame.validate_attributes(attrs, name_table)?;
107    Ok(frame)
108}
109
110pub fn create_frame_recovering(
111    local_name: &str,
112    attrs: &AttributeMap,
113    name_table: &NameTable,
114    source: Option<SourceRef>,
115    ns_snapshot: &NamespaceContextSnapshot,
116    errors: &mut Vec<SchemaError>,
117) -> Box<dyn Frame> {
118    let recovery_source = source.clone();
119    match create_frame(local_name, attrs, name_table, source, ns_snapshot) {
120        Ok(frame) => frame,
121        Err(err) => {
122            errors.push(err);
123            Box::new(SkipFrame::new(recovery_source))
124        }
125    }
126}