Skip to main content

xsd_schema/parser/frames/
schema.rs

1// ============================================================================
2// Schema Frame
3// ============================================================================
4
5/// Parsing phase for schema element
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7enum SchemaPhase {
8    /// Expecting composition elements (include, import, redefine, override)
9    Composition,
10    /// Expecting annotation or components
11    Components,
12}
13
14/// Frame for xs:schema element
15pub struct SchemaFrame {
16    phase: SchemaPhase,
17    target_namespace: Option<NameId>,
18    element_form_default: Option<String>,
19    attribute_form_default: Option<String>,
20    block_default: DerivationSet,
21    default_attributes: Option<QNameRef>,
22    xpath_default_namespace: Option<String>,
23    final_default: DerivationSet,
24    version: Option<String>,
25    default_open_content: Option<DefaultOpenContentResult>,
26    xml_lang: Option<String>,
27    id: Option<String>,
28    source: Option<SourceRef>,
29    annotations: Vec<Annotation>,
30    directives: Vec<DirectiveResult>,
31    components: Vec<FrameResult>,
32    foreign_attributes: Vec<ForeignAttribute>,
33    xml_namespace_id: Option<NameId>,
34    xml_lang_id: Option<NameId>,
35}
36
37impl SchemaFrame {
38    pub fn new(
39        attrs: &AttributeMap,
40        name_table: &NameTable,
41        source: Option<SourceRef>,
42        ns_snapshot: &NamespaceContextSnapshot,
43    ) -> SchemaResult<Self> {
44        let target_namespace = attrs
45            .get_value_by_name(name_table, "targetNamespace")
46            .map(|s| name_table.add(s));
47
48        validate_attr_value(attrs, name_table, "elementFormDefault", parse_form)?;
49        let element_form_default = attrs
50            .get_value_by_name(name_table, "elementFormDefault")
51            .map(String::from);
52
53        validate_attr_value(attrs, name_table, "attributeFormDefault", parse_form)?;
54        let attribute_form_default = attrs
55            .get_value_by_name(name_table, "attributeFormDefault")
56            .map(String::from);
57
58        let block_default = parse_derivation_set(
59            attrs.get_value_by_name(name_table, "blockDefault"),
60        )?;
61
62        let default_attributes = attrs
63            .get_value_by_name(name_table, "defaultAttributes")
64            .map(|s| parse_qname_ref(s, name_table, ns_snapshot))
65            .transpose()?;
66
67        #[cfg(feature = "xsd11")]
68        let xpath_default_namespace = attrs
69            .get_value_by_name(name_table, "xpathDefaultNamespace")
70            .map(String::from);
71        #[cfg(not(feature = "xsd11"))]
72        let xpath_default_namespace: Option<String> = None;
73
74        let final_default = parse_derivation_set(
75            attrs.get_value_by_name(name_table, "finalDefault"),
76        )?;
77
78        let version = attrs
79            .get_value_by_name(name_table, "version")
80            .map(String::from);
81
82        let id = attrs
83            .get_value_by_name(name_table, "id")
84            .map(String::from);
85
86        Ok(Self {
87            phase: SchemaPhase::Composition,
88            target_namespace,
89            element_form_default,
90            attribute_form_default,
91            block_default,
92            default_attributes,
93            xpath_default_namespace,
94            final_default,
95            version,
96            default_open_content: None,
97            xml_lang: None,
98            id,
99            source,
100            annotations: Vec::new(),
101            directives: Vec::new(),
102            components: Vec::new(),
103            foreign_attributes: Vec::new(),
104            xml_namespace_id: name_table.get(crate::namespace::XML_NAMESPACE),
105            xml_lang_id: name_table.get("lang"),
106        })
107    }
108}
109
110impl Frame for SchemaFrame {
111    fn allows(&self, local_name: &str, _name_table: &NameTable) -> bool {
112        #[cfg(feature = "xsd11")]
113        let is_xsd11_element = matches!(
114            local_name,
115            xsd_names::OVERRIDE | xsd_names::DEFAULT_OPEN_CONTENT
116        );
117        #[cfg(not(feature = "xsd11"))]
118        let is_xsd11_element = false;
119
120        match self.phase {
121            SchemaPhase::Composition => matches!(
122                local_name,
123                xsd_names::INCLUDE
124                    | xsd_names::IMPORT
125                    | xsd_names::REDEFINE
126                    | xsd_names::ANNOTATION
127                    | xsd_names::SIMPLE_TYPE
128                    | xsd_names::COMPLEX_TYPE
129                    | xsd_names::ELEMENT
130                    | xsd_names::ATTRIBUTE
131                    | xsd_names::GROUP
132                    | xsd_names::ATTRIBUTE_GROUP
133                    | xsd_names::NOTATION
134            ) || is_xsd11_element,
135            SchemaPhase::Components => matches!(
136                local_name,
137                xsd_names::ANNOTATION
138                    | xsd_names::SIMPLE_TYPE
139                    | xsd_names::COMPLEX_TYPE
140                    | xsd_names::ELEMENT
141                    | xsd_names::ATTRIBUTE
142                    | xsd_names::GROUP
143                    | xsd_names::ATTRIBUTE_GROUP
144                    | xsd_names::NOTATION
145            ),
146        }
147    }
148
149    fn allows_attribute(&self, local_name: &str, _name_table: &NameTable) -> bool {
150        #[cfg(feature = "xsd11")]
151        if local_name == "xpathDefaultNamespace" {
152            return true;
153        }
154        matches!(
155            local_name,
156            "targetNamespace"
157                | "elementFormDefault"
158                | "attributeFormDefault"
159                | "blockDefault"
160                | "defaultAttributes"
161                | "finalDefault"
162                | "version"
163                | "id"
164        )
165    }
166
167    fn on_child_start(&mut self, local_name: &str, _name_table: &NameTable) {
168        // Transition from Composition to Components when we see a component
169        if self.phase == SchemaPhase::Composition {
170            match local_name {
171                xsd_names::SIMPLE_TYPE
172                | xsd_names::COMPLEX_TYPE
173                | xsd_names::ELEMENT
174                | xsd_names::ATTRIBUTE
175                | xsd_names::GROUP
176                | xsd_names::ATTRIBUTE_GROUP
177                | xsd_names::NOTATION => {
178                    self.phase = SchemaPhase::Components;
179                }
180                _ => {}
181            }
182        }
183    }
184
185    fn attach(&mut self, child: FrameResult) -> SchemaResult<()> {
186        match child {
187            FrameResult::Annotation(ann) => {
188                self.annotations.push(ann);
189            }
190            FrameResult::Directive(dir) => {
191                self.directives.push(dir);
192            }
193            FrameResult::Type(_)
194            | FrameResult::Element(_)
195            | FrameResult::Attribute(_)
196            | FrameResult::Group(_)
197            | FrameResult::Notation(_) => {
198                self.components.push(child);
199            }
200            FrameResult::DefaultOpenContent(doc) => {
201                self.default_open_content = Some(doc);
202            }
203            FrameResult::Skip => {}
204            _ => {}
205        }
206        Ok(())
207    }
208
209    fn finish(self: Box<Self>) -> SchemaResult<FrameResult> {
210        Ok(FrameResult::Schema(SchemaFrameResult {
211            target_namespace: self.target_namespace,
212            element_form_default: self.element_form_default,
213            attribute_form_default: self.attribute_form_default,
214            block_default: self.block_default,
215            default_attributes: self.default_attributes,
216            xpath_default_namespace: self.xpath_default_namespace,
217            final_default: self.final_default,
218            version: self.version,
219            default_open_content: self.default_open_content,
220            xml_lang: self.xml_lang,
221            id: self.id,
222            source: self.source,
223            annotations: self.annotations,
224            directives: self.directives,
225            components: self.components,
226        }))
227    }
228
229    fn children_are_top_level(&self) -> bool {
230        true
231    }
232
233    fn source(&self) -> Option<&SourceRef> {
234        self.source.as_ref()
235    }
236
237    fn set_foreign_attributes(&mut self, attrs: Vec<ForeignAttribute>) {
238        if let (Some(xml_ns), Some(lang_id)) = (self.xml_namespace_id, self.xml_lang_id) {
239            if let Some(attr) = attrs
240                .iter()
241                .find(|attr| attr.namespace == Some(xml_ns) && attr.local_name == lang_id)
242            {
243                self.xml_lang = Some(attr.value.clone());
244            }
245        }
246        self.foreign_attributes = attrs;
247    }
248}
249