xsd_schema/parser/frames/
open_content.rs1fn validate_open_content_wildcard_occurs(
14 min_occurs: u32,
15 max_occurs: Option<u32>,
16 _source: Option<&SourceRef>,
17) -> SchemaResult<()> {
18 if min_occurs != 1 || max_occurs != Some(1) {
19 return Err(SchemaError::structural(
20 "src-openContent",
21 "xs:any inside xs:openContent/xs:defaultOpenContent must not \
22 carry 'minOccurs' or 'maxOccurs' (XSD 1.1 structures schema, \
23 see W3C Bugzilla 15618)"
24 .to_string(),
25 None,
26 ));
27 }
28 Ok(())
29}
30
31pub struct OpenContentFrame {
33 mode: OpenContentMode,
34 wildcard: Option<WildcardResult>,
35 id: Option<String>,
36 annotation: Option<Annotation>,
37 source: Option<SourceRef>,
38 foreign_attributes: Vec<ForeignAttribute>,
39}
40
41impl OpenContentFrame {
42 pub fn new(
43 attrs: &AttributeMap,
44 name_table: &NameTable,
45 source: Option<SourceRef>,
46 ) -> SchemaResult<Self> {
47 let mode = parse_open_content_mode_attr(attrs, name_table, "mode")?;
48
49 let id = attrs
50 .get_value_by_name(name_table, "id")
51 .map(String::from);
52
53 Ok(Self {
54 mode,
55 wildcard: None,
56 id,
57 annotation: None,
58 source,
59 foreign_attributes: Vec::new(),
60 })
61 }
62}
63
64impl Frame for OpenContentFrame {
65 fn allows(&self, local_name: &str, _name_table: &NameTable) -> bool {
66 matches!(local_name, xsd_names::ANNOTATION | xsd_names::ANY)
67 }
68
69 fn allows_attribute(&self, local_name: &str, _name_table: &NameTable) -> bool {
70 matches!(local_name, "id" | "mode")
71 }
72
73 fn on_child_start(&mut self, _local_name: &str, _name_table: &NameTable) {}
74
75 fn attach(&mut self, child: FrameResult) -> SchemaResult<()> {
76 match child {
77 FrameResult::Annotation(ann) => {
78 self.annotation = Some(ann);
79 }
80 FrameResult::Particle(particle) => {
81 if let ParticleTerm::Any(wc) = particle.term {
82 validate_open_content_wildcard_occurs(
88 particle.min_occurs,
89 particle.max_occurs,
90 particle.source.as_ref(),
91 )?;
92 self.wildcard = Some(wc);
93 }
94 }
95 FrameResult::Skip => {}
96 _ => {}
97 }
98 Ok(())
99 }
100
101 fn finish(self: Box<Self>) -> SchemaResult<FrameResult> {
102 if self.mode == OpenContentMode::None && self.wildcard.is_some() {
106 return Err(SchemaError::structural(
107 "src-openContent",
108 "xs:openContent with mode='none' must not contain an xs:any \
109 child wildcard (W3C Bugzilla 7069)"
110 .to_string(),
111 None,
112 ));
113 }
114 let annotation = merge_foreign_attributes(
115 self.annotation,
116 self.foreign_attributes,
117 self.source.clone(),
118 );
119 Ok(FrameResult::OpenContent(OpenContentResult {
120 mode: self.mode,
121 wildcard: self.wildcard,
122 id: self.id,
123 annotation,
124 source: self.source,
125 }))
126 }
127
128 fn has_annotation(&self) -> bool {
129 self.annotation.is_some()
130 }
131
132 fn source(&self) -> Option<&SourceRef> {
133 self.source.as_ref()
134 }
135
136 fn set_foreign_attributes(&mut self, attrs: Vec<ForeignAttribute>) {
137 self.foreign_attributes = attrs;
138 }
139}
140
141pub struct DefaultOpenContentFrame {
143 mode: OpenContentMode,
144 applies_to_empty: bool,
145 wildcard: Option<WildcardResult>,
146 id: Option<String>,
147 annotation: Option<Annotation>,
148 source: Option<SourceRef>,
149 foreign_attributes: Vec<ForeignAttribute>,
150}
151
152impl DefaultOpenContentFrame {
153 pub fn new(
154 attrs: &AttributeMap,
155 name_table: &NameTable,
156 source: Option<SourceRef>,
157 ) -> SchemaResult<Self> {
158 let mode = parse_open_content_mode_attr(attrs, name_table, "mode")?;
159
160 let applies_to_empty =
161 parse_bool_attr_default(attrs, name_table, "appliesToEmpty", false)?;
162
163 let id = attrs
164 .get_value_by_name(name_table, "id")
165 .map(String::from);
166
167 Ok(Self {
168 mode,
169 applies_to_empty,
170 wildcard: None,
171 id,
172 annotation: None,
173 source,
174 foreign_attributes: Vec::new(),
175 })
176 }
177}
178
179impl Frame for DefaultOpenContentFrame {
180 fn allows(&self, local_name: &str, _name_table: &NameTable) -> bool {
181 matches!(local_name, xsd_names::ANNOTATION | xsd_names::ANY)
182 }
183
184 fn allows_attribute(&self, local_name: &str, _name_table: &NameTable) -> bool {
185 matches!(local_name, "id" | "mode" | "appliesToEmpty")
186 }
187
188 fn on_child_start(&mut self, _local_name: &str, _name_table: &NameTable) {}
189
190 fn attach(&mut self, child: FrameResult) -> SchemaResult<()> {
191 match child {
192 FrameResult::Annotation(ann) => {
193 self.annotation = Some(ann);
194 }
195 FrameResult::Particle(particle) => {
196 if let ParticleTerm::Any(wc) = particle.term {
197 validate_open_content_wildcard_occurs(
200 particle.min_occurs,
201 particle.max_occurs,
202 particle.source.as_ref(),
203 )?;
204 self.wildcard = Some(wc);
205 }
206 }
207 FrameResult::Skip => {}
208 _ => {}
209 }
210 Ok(())
211 }
212
213 fn finish(self: Box<Self>) -> SchemaResult<FrameResult> {
214 let annotation = merge_foreign_attributes(
215 self.annotation,
216 self.foreign_attributes,
217 self.source.clone(),
218 );
219 Ok(FrameResult::DefaultOpenContent(DefaultOpenContentResult {
220 mode: self.mode,
221 applies_to_empty: self.applies_to_empty,
222 wildcard: self.wildcard,
223 id: self.id,
224 annotation,
225 source: self.source,
226 }))
227 }
228
229 fn has_annotation(&self) -> bool {
230 self.annotation.is_some()
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 self.foreign_attributes = attrs;
239 }
240}
241