Skip to main content

xsd_schema/parser/frames/
core.rs

1/// Result of finishing a frame
2#[derive(Debug)]
3pub enum FrameResult {
4    /// Schema document completed
5    Schema(SchemaFrameResult),
6    /// Type definition completed
7    Type(TypeFrameResult),
8    /// Element declaration completed
9    Element(ElementFrameResult),
10    /// Attribute declaration completed
11    Attribute(AttributeFrameResult),
12    /// Group definition completed
13    Group(GroupFrameResult),
14    /// Notation declaration completed
15    Notation(NotationResult),
16    /// Assert completed (XSD 1.1)
17    Assert(AssertResult),
18    /// Alternative completed (XSD 1.1)
19    Alternative(AlternativeResult),
20    /// Open content completed (XSD 1.1)
21    OpenContent(OpenContentResult),
22    /// Default open content completed (XSD 1.1)
23    DefaultOpenContent(DefaultOpenContentResult),
24    /// Annotation completed
25    Annotation(Annotation),
26    /// AppInfo element completed
27    AppInfo(AppInfoElement),
28    /// Documentation element completed
29    Documentation(DocumentationElement),
30    /// Facet completed
31    Facet(FacetResult),
32    /// Restriction completed
33    Restriction(Box<RestrictionResult>),
34    /// Extension completed
35    Extension(ExtensionResult),
36    /// Simple content completed
37    SimpleContent(SimpleContentDefResult),
38    /// Complex content completed
39    ComplexContent(ComplexContentDefResult),
40    /// Identity constraint completed
41    Identity(IdentityResult),
42    /// Identity constraint reference (XSD 1.1 @ref)
43    IdentityRef(IdentityRefResult),
44    /// Selector completed
45    Selector(SelectorResult),
46    /// Field completed
47    Field(FieldResult),
48    /// Wildcard completed
49    Wildcard(WildcardResult),
50    /// Composition directive completed
51    Directive(DirectiveResult),
52    /// Content particle completed
53    Particle(ParticleResult),
54    /// Skip frame (error recovery)
55    Skip,
56    /// Nothing to return (for internal frames)
57    None,
58}
59
60/// Schema document result
61#[derive(Debug)]
62pub struct SchemaFrameResult {
63    pub target_namespace: Option<NameId>,
64    pub element_form_default: Option<String>,
65    pub attribute_form_default: Option<String>,
66    pub block_default: DerivationSet,
67    pub default_attributes: Option<QNameRef>,
68    pub xpath_default_namespace: Option<String>,
69    pub final_default: DerivationSet,
70    pub version: Option<String>,
71    pub default_open_content: Option<DefaultOpenContentResult>,
72    pub xml_lang: Option<String>,
73    pub id: Option<String>,
74    pub source: Option<SourceRef>,
75    pub annotations: Vec<Annotation>,
76    pub directives: Vec<DirectiveResult>,
77    pub components: Vec<FrameResult>,
78}
79
80/// Type definition result
81#[derive(Debug, Clone)]
82pub enum TypeFrameResult {
83    Simple(Box<SimpleTypeResult>),
84    Complex(Box<ComplexTypeResult>),
85}
86
87/// Simple type result
88#[derive(Debug, Clone)]
89pub struct SimpleTypeResult {
90    pub name: Option<NameId>,
91    pub variety: SimpleTypeVariety,
92    pub base_type: Option<TypeRefResult>,
93    pub item_type: Option<TypeRefResult>,
94    pub member_types: Vec<TypeRefResult>,
95    pub facets: FacetSet,
96    pub final_derivation: Option<DerivationSet>,
97    pub id: Option<String>,
98    pub derivation_id: Option<String>,
99    pub annotation: Option<Annotation>,
100    pub source: Option<SourceRef>,
101}
102
103/// Simple type variety
104#[derive(Debug, Clone, Copy, PartialEq, Eq)]
105pub enum SimpleTypeVariety {
106    Atomic,
107    List,
108    Union,
109}
110
111/// Complex type result
112#[derive(Debug, Clone)]
113pub struct ComplexTypeResult {
114    pub name: Option<NameId>,
115    pub base_type: Option<TypeRefResult>,
116    pub derivation_method: Option<DerivationMethod>,
117    pub content: ComplexContentResult,
118    pub attributes: Vec<AttributeUseResult>,
119    pub attribute_groups: Vec<QNameRef>,
120    pub attribute_wildcard: Option<WildcardResult>,
121    pub mixed: bool,
122    pub is_abstract: bool,
123    pub final_derivation: Option<DerivationSet>,
124    pub block: Option<DerivationSet>,
125    pub default_attributes_apply: bool,
126    pub id: Option<String>,
127    #[cfg(feature = "xsd11")]
128    pub xpath_default_namespace: Option<String>,
129    pub annotation: Option<Annotation>,
130    pub source: Option<SourceRef>,
131}
132
133/// Derivation method
134#[derive(Debug, Clone, Copy, PartialEq, Eq)]
135pub enum DerivationMethod {
136    Restriction,
137    Extension,
138}
139
140/// Complex content result
141#[derive(Debug, Clone)]
142pub enum ComplexContentResult {
143    Empty,
144    Simple(SimpleContentDefResult),
145    Complex(ComplexContentDefResult),
146}
147
148impl ComplexContentResult {
149    /// Returns `true` if this content has *empty explicit content* per
150    /// §3.4.2.3 step 2 (used by §3.4.6.3 effective content and the
151    /// `<defaultOpenContent appliesToEmpty="false">` gate).
152    ///
153    /// Empty cases:
154    /// - 2.1.1: no `<group>/<all>/<choice>/<sequence>` child (no particle)
155    /// - 2.1.2: an `<all>` or `<sequence>` child with empty particles
156    /// - 2.1.3: a `<choice>` child with `minOccurs=0` and empty particles
157    /// - 2.1.4: the child has `maxOccurs=0`
158    ///
159    /// `SimpleContent` is never empty.
160    pub fn is_empty(&self) -> bool {
161        match self {
162            ComplexContentResult::Empty => true,
163            ComplexContentResult::Complex(def) => match &def.particle {
164                None => true,
165                Some(p) => particle_is_explicit_empty(p),
166            },
167            ComplexContentResult::Simple(_) => false,
168        }
169    }
170
171    /// True when this complex content collapses to *explicit content type
172    /// variety = empty* per §3.4.2.3 step 4.1.1 (restriction) — used by the
173    /// `<defaultOpenContent appliesToEmpty="false">` gate (§3.4.2.3 step
174    /// 5.2.2). Equivalent to "explicit content empty AND effective mixed
175    /// false": when mixed is true, step 3.1.1 promotes the empty explicit
176    /// content to a non-empty effective content (an empty sequence
177    /// particle), which means the explicit content type variety is `mixed`,
178    /// not `empty`.
179    pub fn explicit_content_type_is_empty(&self) -> bool {
180        match self {
181            ComplexContentResult::Empty => true,
182            ComplexContentResult::Complex(def) => {
183                let particle_empty = match &def.particle {
184                    None => true,
185                    Some(p) => particle_is_explicit_empty(p),
186                };
187                particle_empty && !def.mixed
188            }
189            ComplexContentResult::Simple(_) => false,
190        }
191    }
192}
193
194/// True when a particle counts as "empty explicit content" per §3.4.2.3
195/// clauses 2.1.2 / 2.1.3 / 2.1.4.
196///
197/// `compositor: None` means the particle is a `<xs:group ref="…">` whose
198/// referenced model group has not been resolved yet — its emptiness can
199/// only be decided after group resolution, so we conservatively treat it
200/// as non-empty (the safe default for runtime content-type computation).
201pub fn particle_is_explicit_empty(p: &ParticleResult) -> bool {
202    if p.max_occurs == Some(0) {
203        return true; // 2.1.4
204    }
205    match &p.term {
206        ParticleTerm::Group(group) => match group.compositor {
207            Some(Compositor::All) | Some(Compositor::Sequence) => group.particles.is_empty(),
208            Some(Compositor::Choice) => group.particles.is_empty() && group.min_occurs == 0,
209            None => false,
210        },
211        _ => false,
212    }
213}
214
215/// Simple content definition result
216#[derive(Debug, Clone)]
217pub struct SimpleContentDefResult {
218    pub base_type: Option<TypeRefResult>,
219    /// Inline simpleType from simpleContent/restriction (B in spec 3.4.2.2 clause 1.1).
220    /// When present alongside base_type, the base_type names the complex type being restricted
221    /// and this field holds the content type restriction.
222    pub content_type: Option<Box<SimpleTypeResult>>,
223    pub derivation: DerivationMethod,
224    pub facets: FacetSet,
225    pub attributes: Vec<AttributeUseResult>,
226    pub attribute_groups: Vec<QNameRef>,
227    pub attribute_wildcard: Option<WildcardResult>,
228    pub assertions: Vec<AssertResult>,
229    pub id: Option<String>,
230    pub derivation_id: Option<String>,
231    pub source: Option<SourceRef>,
232}
233
234/// Complex content definition result
235#[derive(Debug, Clone)]
236pub struct ComplexContentDefResult {
237    pub particle: Option<ParticleResult>,
238    pub derivation: DerivationMethod,
239    /// Effective `mixed` value. Per §3.4.2.3 clause 1.1, `mixed` on
240    /// `<xs:complexContent>` takes precedence when present, otherwise the
241    /// outer `<xs:complexType mixed="…">` attribute is used. The assembler
242    /// (`ComplexTypeFrame::attach`) consults `mixed_explicit` to decide
243    /// whether to inherit the outer value when this field is false.
244    pub mixed: bool,
245    /// `true` when the `<xs:complexContent>` element carried an explicit
246    /// `mixed="…"` attribute — distinguishes "explicitly false" from
247    /// "absent, fall back to outer".
248    pub mixed_explicit: bool,
249    pub base_type: Option<TypeRefResult>,
250    pub open_content: Option<OpenContentResult>,
251    pub attributes: Vec<AttributeUseResult>,
252    pub attribute_groups: Vec<QNameRef>,
253    pub attribute_wildcard: Option<WildcardResult>,
254    pub assertions: Vec<AssertResult>,
255    pub id: Option<String>,
256    pub derivation_id: Option<String>,
257    pub source: Option<SourceRef>,
258}
259
260/// Element declaration result
261#[derive(Debug, Clone)]
262pub struct ElementFrameResult {
263    pub name: Option<NameId>,
264    pub ref_name: Option<QNameRef>,
265    pub target_namespace: Option<NameId>,
266    pub type_ref: Option<TypeRefResult>,
267    pub inline_type: Option<Box<TypeFrameResult>>,
268    pub substitution_group: Vec<QNameRef>,
269    pub default_value: Option<String>,
270    pub fixed_value: Option<String>,
271    pub nillable: bool,
272    pub is_abstract: bool,
273    pub min_occurs: u32,
274    pub max_occurs: Option<u32>,
275    pub block: Option<DerivationSet>,
276    pub final_derivation: Option<DerivationSet>,
277    pub form: Option<String>,
278    pub id: Option<String>,
279    pub alternatives: Vec<AlternativeResult>,
280    pub identity_constraints: Vec<IdentityResult>,
281    /// XSD 1.1: pending identity constraint references (@ref)
282    pub identity_constraint_refs: Vec<IdentityRefResult>,
283    pub annotation: Option<Annotation>,
284    pub source: Option<SourceRef>,
285}
286
287/// Attribute declaration result
288#[derive(Debug, Clone)]
289pub struct AttributeFrameResult {
290    pub name: Option<NameId>,
291    pub ref_name: Option<QNameRef>,
292    pub target_namespace: Option<NameId>,
293    pub type_ref: Option<TypeRefResult>,
294    pub inline_type: Option<Box<SimpleTypeResult>>,
295    pub default_value: Option<String>,
296    pub fixed_value: Option<String>,
297    pub use_kind: Option<String>,
298    pub form: Option<String>,
299    pub inheritable: bool,
300    pub id: Option<String>,
301    pub annotation: Option<Annotation>,
302    pub source: Option<SourceRef>,
303}
304
305/// Attribute use result (attribute within complex type)
306#[derive(Debug, Clone)]
307pub struct AttributeUseResult {
308    pub attribute: AttributeFrameResult,
309    pub use_kind: AttributeUseKind,
310}
311
312/// Attribute use kind
313#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
314pub enum AttributeUseKind {
315    #[default]
316    Optional,
317    Required,
318    Prohibited,
319}
320
321/// Group definition result
322#[derive(Debug)]
323pub enum GroupFrameResult {
324    Model(Box<ModelGroupDefResult>),
325    Attribute(Box<AttributeGroupDefResult>),
326}
327
328/// Model group definition result
329#[derive(Debug, Clone)]
330pub struct ModelGroupDefResult {
331    pub name: Option<NameId>,
332    pub ref_name: Option<QNameRef>,
333    pub compositor: Option<Compositor>,
334    pub particles: Vec<ParticleResult>,
335    pub min_occurs: u32,
336    pub max_occurs: Option<u32>,
337    pub id: Option<String>,
338    pub annotation: Option<Annotation>,
339    pub source: Option<SourceRef>,
340}
341
342/// Attribute group definition result
343#[derive(Debug, Clone)]
344pub struct AttributeGroupDefResult {
345    pub name: Option<NameId>,
346    pub ref_name: Option<QNameRef>,
347    pub attributes: Vec<AttributeUseResult>,
348    pub attribute_groups: Vec<QNameRef>,
349    pub attribute_wildcard: Option<WildcardResult>,
350    pub id: Option<String>,
351    pub annotation: Option<Annotation>,
352    pub source: Option<SourceRef>,
353}
354
355/// Compositor type
356#[derive(Debug, Clone, Copy, PartialEq, Eq)]
357pub enum Compositor {
358    Sequence,
359    Choice,
360    All,
361}
362
363/// Particle result
364#[derive(Debug, Clone)]
365pub struct ParticleResult {
366    pub term: ParticleTerm,
367    pub min_occurs: u32,
368    pub max_occurs: Option<u32>,
369    pub source: Option<SourceRef>,
370}
371
372/// Particle term
373#[derive(Debug, Clone)]
374pub enum ParticleTerm {
375    Element(ElementFrameResult),
376    Group(ModelGroupDefResult),
377    Any(WildcardResult),
378}
379
380/// Type reference result
381#[derive(Debug, Clone)]
382pub enum TypeRefResult {
383    QName(QNameRef),
384    Inline(Box<TypeFrameResult>),
385}
386
387/// QName reference (unresolved)
388#[derive(Debug, Clone)]
389pub struct QNameRef {
390    pub prefix: Option<NameId>,
391    pub local_name: NameId,
392    pub namespace: Option<NameId>,
393}
394
395/// Facet result
396#[derive(Debug, Clone)]
397pub struct FacetResult {
398    pub kind: FacetKind,
399    pub value: String,
400    pub fixed: bool,
401    pub annotation: Option<Annotation>,
402    pub source: Option<SourceRef>,
403    /// XSD 1.1 assertion: xpathDefaultNamespace attribute value (raw string)
404    pub xpath_default_namespace: Option<String>,
405    /// XSD 1.1 assertion: namespace bindings snapshot for XPath prefix resolution
406    pub ns_snapshot: Option<NamespaceContextSnapshot>,
407}
408
409/// Restriction result
410#[derive(Debug, Clone)]
411pub struct RestrictionResult {
412    pub base_type: Option<TypeRefResult>,
413    pub inline_type: Option<SimpleTypeResult>,
414    pub facets: FacetSet,
415    pub particle: Option<ParticleResult>,
416    pub open_content: Option<OpenContentResult>,
417    pub attributes: Vec<AttributeUseResult>,
418    pub attribute_groups: Vec<QNameRef>,
419    pub attribute_wildcard: Option<WildcardResult>,
420    pub assertions: Vec<AssertResult>,
421    pub id: Option<String>,
422    pub annotation: Option<Annotation>,
423    pub source: Option<SourceRef>,
424}
425
426/// Extension result
427#[derive(Debug, Clone)]
428pub struct ExtensionResult {
429    pub base_type: Option<TypeRefResult>,
430    pub particle: Option<ParticleResult>,
431    pub open_content: Option<OpenContentResult>,
432    pub attributes: Vec<AttributeUseResult>,
433    pub attribute_groups: Vec<QNameRef>,
434    pub attribute_wildcard: Option<WildcardResult>,
435    pub assertions: Vec<AssertResult>,
436    pub id: Option<String>,
437    pub annotation: Option<Annotation>,
438    pub source: Option<SourceRef>,
439}
440
441/// Facet kind
442#[derive(Debug, Clone, Copy, PartialEq, Eq)]
443pub enum FacetKind {
444    Enumeration,
445    Pattern,
446    MinInclusive,
447    MaxInclusive,
448    MinExclusive,
449    MaxExclusive,
450    MinLength,
451    MaxLength,
452    Length,
453    TotalDigits,
454    FractionDigits,
455    WhiteSpace,
456    // XSD 1.1 facets
457    Assertion,
458    ExplicitTimezone,
459}
460
461/// Selector result
462#[derive(Debug, Clone)]
463pub struct SelectorResult {
464    pub xpath: String,
465    pub xpath_default_namespace: Option<String>,
466    pub ns_snapshot: NamespaceContextSnapshot,
467    pub id: Option<String>,
468    pub annotation: Option<Annotation>,
469    pub source: Option<SourceRef>,
470}
471
472/// Notation declaration result
473#[derive(Debug, Clone)]
474pub struct NotationResult {
475    pub name: Option<NameId>,
476    pub public: Option<String>,
477    pub system: Option<String>,
478    pub id: Option<String>,
479    pub annotation: Option<Annotation>,
480    pub source: Option<SourceRef>,
481}
482
483/// Field result
484#[derive(Debug, Clone)]
485pub struct FieldResult {
486    pub xpath: String,
487    pub xpath_default_namespace: Option<String>,
488    pub ns_snapshot: NamespaceContextSnapshot,
489    pub id: Option<String>,
490    pub annotation: Option<Annotation>,
491    pub source: Option<SourceRef>,
492}
493
494/// Assert result (XSD 1.1)
495#[derive(Debug, Clone)]
496pub struct AssertResult {
497    pub test: String,
498    pub xpath_default_namespace: Option<String>,
499    pub ns_snapshot: NamespaceContextSnapshot,
500    pub id: Option<String>,
501    pub annotation: Option<Annotation>,
502    pub source: Option<SourceRef>,
503}
504
505/// Alternative result (XSD 1.1)
506#[derive(Debug, Clone)]
507pub struct AlternativeResult {
508    pub test: Option<String>,
509    pub type_ref: Option<TypeRefResult>,
510    pub inline_type: Option<Box<TypeFrameResult>>,
511    pub xpath_default_namespace: Option<String>,
512    pub ns_snapshot: NamespaceContextSnapshot,
513    pub resolved_type: Option<TypeKey>,
514    pub id: Option<String>,
515    pub annotation: Option<Annotation>,
516    pub source: Option<SourceRef>,
517}
518
519/// Open content result (XSD 1.1)
520#[derive(Debug, Clone)]
521pub struct OpenContentResult {
522    pub mode: OpenContentMode,
523    pub wildcard: Option<WildcardResult>,
524    pub id: Option<String>,
525    pub annotation: Option<Annotation>,
526    pub source: Option<SourceRef>,
527}
528
529/// Default open content result (XSD 1.1)
530#[derive(Debug, Clone)]
531pub struct DefaultOpenContentResult {
532    pub mode: OpenContentMode,
533    pub applies_to_empty: bool,
534    pub wildcard: Option<WildcardResult>,
535    pub id: Option<String>,
536    pub annotation: Option<Annotation>,
537    pub source: Option<SourceRef>,
538}
539
540/// Identity constraint result
541#[derive(Debug, Clone)]
542pub struct IdentityResult {
543    pub kind: IdentityKind,
544    pub name: NameId,
545    pub ref_name: Option<QNameRef>,
546    pub refer: Option<QNameRef>,
547    pub selector: SelectorResult,
548    pub fields: Vec<FieldResult>,
549    pub id: Option<String>,
550    pub annotation: Option<Annotation>,
551    pub source: Option<SourceRef>,
552}
553
554/// Identity constraint reference result (XSD 1.1 @ref on unique/key/keyref)
555///
556/// Per §3.11.2: when @ref is present, the element does not define a new
557/// component — it IS the referenced component.
558#[derive(Debug, Clone)]
559pub struct IdentityRefResult {
560    pub kind: IdentityKind,
561    pub ref_name: QNameRef,
562    pub id: Option<String>,
563    pub annotation: Option<Annotation>,
564    pub source: Option<SourceRef>,
565}
566
567/// Identity constraint kind
568#[derive(Debug, Clone, Copy, PartialEq, Eq)]
569pub enum IdentityKind {
570    Key,
571    Keyref,
572    Unique,
573}
574
575/// A parsed namespace token from namespace/notNamespace attributes.
576/// Preserves ##targetNamespace and ##local as distinct variants
577/// (resolved to concrete NameIds at assembly time).
578#[derive(Debug, Clone, PartialEq, Eq)]
579pub enum NamespaceToken {
580    /// A concrete namespace URI (interned)
581    Uri(NameId),
582    /// ##local (absent namespace)
583    Local,
584    /// ##targetNamespace (resolved at assembly)
585    TargetNamespace,
586}
587
588impl NamespaceToken {
589    /// Resolve this token to a concrete namespace, given the target namespace.
590    pub fn resolve(&self, target_namespace: Option<NameId>) -> Option<NameId> {
591        match self {
592            NamespaceToken::Uri(id) => Some(*id),
593            NamespaceToken::Local => None,
594            NamespaceToken::TargetNamespace => target_namespace,
595        }
596    }
597}
598
599/// Parsed item from notQName attribute (XSD 1.1)
600#[derive(Debug, Clone, PartialEq, Eq)]
601pub enum NotQNameItem {
602    /// Specific QName that is disallowed
603    QName { namespace: Option<NameId>, local_name: NameId },
604    /// ##defined
605    Defined,
606    /// ##definedSibling (xs:any only, not xs:anyAttribute)
607    DefinedSibling,
608}
609
610/// Wildcard result
611#[derive(Debug, Clone)]
612pub struct WildcardResult {
613    pub namespace: WildcardNamespace,
614    pub process_contents: ProcessContents,
615    pub not_namespace: Vec<NamespaceToken>,
616    pub not_qname: Vec<NotQNameItem>,
617    pub id: Option<String>,
618    pub annotation: Option<Annotation>,
619    pub source: Option<SourceRef>,
620}
621
622/// Wildcard namespace constraint
623#[derive(Debug, Clone)]
624pub enum WildcardNamespace {
625    Any,
626    Other,
627    TargetNamespace,
628    Local,
629    List(Vec<NamespaceToken>),
630}
631
632/// Process contents mode
633#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
634pub enum ProcessContents {
635    #[default]
636    Strict,
637    Lax,
638    Skip,
639}
640
641/// Open content mode (XSD 1.1)
642#[derive(Debug, Clone, Copy, PartialEq, Eq)]
643pub enum OpenContentMode {
644    None,
645    Interleave,
646    Suffix,
647}
648
649/// Directive result (include/import/redefine/override)
650#[derive(Debug)]
651pub enum DirectiveResult {
652    Include(IncludeResult),
653    Import(ImportResult),
654    Redefine(RedefineResult),
655    Override(OverrideResult),
656}
657
658/// Include directive result
659#[derive(Debug)]
660pub struct IncludeResult {
661    pub schema_location: String,
662    pub id: Option<String>,
663    pub annotation: Option<Annotation>,
664    pub source: Option<SourceRef>,
665}
666
667/// Import directive result
668#[derive(Debug)]
669pub struct ImportResult {
670    pub namespace: Option<String>,
671    pub schema_location: Option<String>,
672    pub id: Option<String>,
673    pub annotation: Option<Annotation>,
674    pub source: Option<SourceRef>,
675}
676
677/// Redefine directive result
678#[derive(Debug)]
679pub struct RedefineResult {
680    pub schema_location: String,
681    pub id: Option<String>,
682    pub annotation: Option<Annotation>,
683    pub components: Vec<RedefineComponent>,
684    pub source: Option<SourceRef>,
685}
686
687/// Redefine component
688#[derive(Debug)]
689pub enum RedefineComponent {
690    SimpleType(Box<SimpleTypeResult>),
691    ComplexType(Box<ComplexTypeResult>),
692    Group(Box<ModelGroupDefResult>),
693    AttributeGroup(Box<AttributeGroupDefResult>),
694}
695
696/// Override directive result (XSD 1.1)
697#[derive(Debug)]
698pub struct OverrideResult {
699    pub schema_location: String,
700    pub id: Option<String>,
701    pub annotation: Option<Annotation>,
702    pub source: Option<SourceRef>,
703    // Overridden components (schemaTop)
704    pub simple_types: Vec<SimpleTypeResult>,
705    pub complex_types: Vec<ComplexTypeResult>,
706    pub elements: Vec<ElementFrameResult>,
707    pub attributes: Vec<AttributeFrameResult>,
708    pub groups: Vec<GroupFrameResult>,
709    pub attribute_groups: Vec<GroupFrameResult>,
710    pub notations: Vec<NotationResult>,
711}
712
713// ============================================================================
714// Frame trait and implementation
715// ============================================================================
716
717/// Parser frame trait for handling XSD elements
718pub trait Frame {
719    /// Check if a child element is allowed in the current phase
720    fn allows(&self, local_name: &str, name_table: &NameTable) -> bool;
721
722    /// Check if an attribute is allowed on this element
723    fn allows_attribute(&self, local_name: &str, name_table: &NameTable) -> bool;
724
725    /// Validate attributes for this element
726    fn validate_attributes(
727        &self,
728        attrs: &AttributeMap,
729        name_table: &NameTable,
730    ) -> SchemaResult<()> {
731        for name_id in attrs.names() {
732            let local_name = match name_table.try_resolve(name_id) {
733                Some(name) => name,
734                None => continue,
735            };
736
737            if !self.allows_attribute(&local_name, name_table) {
738                return Err(SchemaError::structural(
739                    "ct-props-correct",
740                    format!("Attribute '{}' is not allowed here", local_name),
741                    None,
742                ));
743            }
744        }
745
746        Ok(())
747    }
748
749    /// Called when a child element is pushed
750    fn on_child_start(&mut self, local_name: &str, name_table: &NameTable);
751
752    /// Attach a completed child frame result
753    fn attach(&mut self, child: FrameResult) -> SchemaResult<()>;
754
755    /// Finish processing and return result
756    fn finish(self: Box<Self>) -> SchemaResult<FrameResult>;
757
758    /// Get the source location
759    fn source(&self) -> Option<&SourceRef>;
760
761    /// Set foreign attributes
762    fn set_foreign_attributes(&mut self, attrs: Vec<ForeignAttribute>);
763
764    /// Returns true if this is a SkipFrame (for error recovery depth tracking)
765    fn is_skip_frame(&self) -> bool {
766        false
767    }
768
769    /// Returns true if children of this frame are treated as top-level declarations.
770    /// True for schema, redefine, and override frames.
771    fn children_are_top_level(&self) -> bool {
772        false
773    }
774
775    /// Returns true if children of this frame are inside a `<complexType>` ancestor
776    /// for purposes of src-element §3.3.3 / src-attribute §3.2.3 — i.e. the local
777    /// declaration's `targetNamespace` may diverge from the schema's only when there
778    /// is a complexType ancestor (and inside it, a restriction of a non-anyType base).
779    /// True for the complexType frame and the descendants that propagate the flag.
780    fn children_inside_complex_type(&self) -> bool {
781        false
782    }
783
784    /// Returns true if this frame already has an annotation child.
785    /// Used to reject duplicate annotations per XSD content model.
786    fn has_annotation(&self) -> bool {
787        false
788    }
789
790    /// Called when leaving a child element in a skip frame
791    /// Returns true if the skip frame is complete (depth reached 0)
792    fn on_child_end(&mut self) -> bool {
793        false
794    }
795
796    /// Check if this frame accepts text content
797    fn accepts_text(&self) -> bool {
798        false
799    }
800
801    /// Returns true if this frame accepts foreign-namespace child elements.
802    /// Defaults to false: only `xs:appinfo` and `xs:documentation` (and skip
803    /// frames during error recovery) accept arbitrary foreign content.
804    fn accepts_foreign_children(&self) -> bool {
805        false
806    }
807
808    /// Handle text content (for annotation content like appinfo/documentation)
809    fn on_text(&mut self, _text: &str) {}
810
811    /// Handle CDATA content (for annotation content like appinfo/documentation)
812    fn on_cdata(&mut self, _cdata: &str) {}
813
814    /// Set namespace context snapshot (for annotation content)
815    fn set_namespaces(&mut self, _namespaces: NamespaceContextSnapshot) {}
816}