1use std::collections::{HashMap, HashSet};
29use std::path::Path;
30use std::sync::Arc;
31
32use crate::reader::{Attr, EventInto, XmlReader};
33
34use super::error::SchemaCompileError;
35use super::facets::{Bound, Facet, FacetSet};
36use super::resolver::{FsResolver, NoResolver, SchemaResolver};
37use super::schema::{
38 AttributeDecl, AttributeGroup, AttributeUse, AttributeUseKind, BlockSet, ContentModel,
39 ElementDecl, GroupKind, MaxOccurs, ModelGroup, NamespaceConstraint, NotationDecl, Particle,
40 ProcessContents, QName, Schema, SchemaInner, SchemaOptions, SchemaVersion, Term, TypeRef,
41 Wildcard,
42};
43use super::types::{
44 BuiltinType, ComplexType, Derivation, DerivationMethod, SimpleType,
45};
46use super::whitespace::WhitespaceMode;
47
48const MAX_INCLUDE_DEPTH: u32 = 64;
49
50impl Schema {
53 pub fn compile_str(xsd: &str) -> Result<Schema, SchemaCompileError> {
57 Self::compile_with(xsd, NoResolver)
58 }
59
60 pub fn compile_str_with_options(
64 xsd: &str,
65 options: SchemaOptions,
66 ) -> Result<Schema, SchemaCompileError> {
67 Self::compile_with_options(xsd, NoResolver, options)
68 }
69
70 pub fn compile_with<R: SchemaResolver>(
76 xsd: &str,
77 resolver: R,
78 ) -> Result<Schema, SchemaCompileError> {
79 Self::compile_with_options(xsd, resolver, SchemaOptions::default())
80 }
81
82 pub fn compile_with_options<R: SchemaResolver>(
86 xsd: &str,
87 resolver: R,
88 options: SchemaOptions,
89 ) -> Result<Schema, SchemaCompileError> {
90 let mut builder = Builder::default();
91 builder.effective_version = options.version;
95 builder.options = options;
96 parse_one_file(xsd, &mut builder, &resolver, None, false)?;
97 builder.into_schema()
98 }
99
100 pub fn compile_file(path: impl AsRef<Path>) -> Result<Schema, SchemaCompileError> {
110 let path = path.as_ref();
111 let xsd = std::fs::read_to_string(path).map_err(|e|
112 SchemaCompileError::msg(format!("read {}: {e}", path.display())))?;
113 let dir = path.parent().unwrap_or_else(|| Path::new("."));
114 Self::compile_with(&xsd, FsResolver::new(dir))
115 }
116}
117
118#[derive(Default)]
121struct Builder {
122 options: SchemaOptions,
126 effective_version: SchemaVersion,
131 target_ns: Option<Arc<str>>,
132 elements: HashMap<QName, Arc<ElementDecl>>,
133 attributes: HashMap<QName, Arc<AttributeDecl>>,
134 types: HashMap<QName, TypeRef>,
135 attr_groups: HashMap<QName, Arc<AttributeGroup>>,
136 model_groups: HashMap<QName, Arc<ModelGroup>>,
137 notations: HashMap<QName, Arc<NotationDecl>>,
138 substitutions: HashMap<QName, Vec<Arc<ElementDecl>>>,
139 loaded: HashSet<String>,
141 depth: u32,
143 pending_attribute_refs: Vec<QName>,
148 pending_element_refs: Vec<QName>,
151 pending_ag_refs_in_ag: Vec<QName>,
156 #[allow(dead_code)]
159 pending_group_refs: Vec<QName>,
160 redefined_groups: HashSet<QName>,
165 redefined_group_originals: Vec<(QName, Particle, Particle)>,
170 redefined_attr_group_originals: Vec<(QName, Arc<AttributeGroup>, Arc<AttributeGroup>, bool)>,
180 redefining_ag_name: Option<QName>,
185 redefining_ag_saw_self_ref: bool,
189 imported_namespaces: HashSet<Option<Arc<str>>>,
197 pending_simple_facet_checks: Vec<(QName, Vec<Facet>)>,
205 ag_refs_by_owner: HashMap<QName, Vec<QName>>,
212}
213
214impl Builder {
215 fn into_schema(mut self) -> Result<Schema, SchemaCompileError> {
216 check_attribute_group_ref_kinds(&self.types, &self.elements,
221 &self.attr_groups, &self.attributes)?;
222
223 check_ag_refs_in_ag(&self.pending_ag_refs_in_ag, &self.attr_groups,
226 &self.types, &self.elements, &self.attributes)?;
227
228 check_attribute_group_cycles(&self.ag_refs_by_owner)?;
232
233 check_attribute_refs(&self.pending_attribute_refs, &self.attributes,
238 &self.attr_groups, &self.types, &self.elements,
239 self.target_ns.as_deref(), &self.imported_namespaces)?;
240
241 check_element_refs(&self.pending_element_refs, &self.elements,
247 &self.types, &self.attributes, &self.attr_groups,
248 self.target_ns.as_deref(), &self.imported_namespaces)?;
249
250 check_substitution_group_heads(&self.elements)?;
253 check_substitution_group_typing(&self.elements, &self.types)?;
257
258 check_id_typed_element_value_constraints(&self.elements, &self.types)?;
265
266 check_type_refs_collide(&self.types, &self.attributes,
270 &self.attr_groups, &self.elements)?;
271
272 flatten_nested_attribute_group_refs(
284 &mut self.attr_groups, &self.ag_refs_by_owner,
285 );
286 resolve_attribute_group_refs(&mut self.types, &mut self.elements, &self.attr_groups)?;
292
293 check_model_group_cycles(&self.model_groups, &self.redefined_groups)?;
300
301 resolve_group_refs(&mut self.types, &mut self.elements, &self.model_groups)?;
306
307 resolve_element_refs(&mut self.types, &mut self.elements);
317
318 check_derivation_content_kind(&self.types)?;
324
325 check_complex_mixed_consistency(&self.types, &self.elements)?;
331
332 check_complex_type_final(&self.types, &self.elements)?;
337
338 merge_extension_chains(&mut self.types)?;
343
344 resolve_simple_member_placeholders(&mut self.types);
349
350 merge_inline_extension_in_elements(&mut self.elements, &self.types);
361
362 merge_restriction_attributes(&mut self.types, &mut self.elements);
367
368 resolve_element_refs(&mut self.types, &mut self.elements);
374
375 check_element_decls_consistent(&self.types, &self.elements)?;
384
385 check_pending_simple_facet_tightening(
392 &self.pending_simple_facet_checks, &self.types,
393 )?;
394
395 super::particle_restriction::check_restriction_chains(&self.types, &self.elements,
396 self.target_ns.as_deref())?;
397
398 super::particle_restriction::check_redefined_groups(
404 &self.redefined_group_originals, &self.types, &self.elements,
405 self.target_ns.as_deref(),
406 )?;
407 check_redefined_attribute_groups(&self.redefined_attr_group_originals,
412 &self.types)?;
413
414 check_attribute_type_kinds(&self.types, &self.attributes, &self.elements)?;
419
420 check_complex_restriction_attributes(&self.types, &self.elements)?;
425
426 check_keyref_refer(&self.elements)?;
429
430
431 check_element_value_constraints(&self.types, &self.elements)?;
437
438 let mut subs: HashMap<QName, Vec<Arc<ElementDecl>>> = HashMap::new();
444 for decl in self.elements.values() {
445 if let Some(head) = &decl.substitution_group {
446 subs.entry(head.clone()).or_default().push(decl.clone());
447 }
448 }
449 let mut changed = true;
452 let mut guard = 0;
453 while changed && guard < 64 {
454 changed = false;
455 guard += 1;
456 let heads: Vec<QName> = subs.keys().cloned().collect();
457 for head in heads {
458 let direct: Vec<Arc<ElementDecl>> = subs[&head].clone();
459 for m in direct {
460 let Some(deeper) = subs.get(&m.name).cloned() else { continue };
461 for d in deeper {
462 let list = subs.get_mut(&head).unwrap();
463 if !list.iter().any(|x| Arc::ptr_eq(x, &d) || x.name == d.name) {
464 list.push(d);
465 changed = true;
466 }
467 }
468 }
469 }
470 }
471 self.substitutions = subs;
472
473 let mut visited: HashSet<usize> = HashSet::new();
478 let types_snapshot = self.types.clone();
479 let target_ns_str = self.target_ns.as_deref().map(|s| s.to_owned());
480 let target_ns_ref = target_ns_str.as_deref();
481 for tr in self.types.values() {
482 if let TypeRef::Complex(ct) = tr {
483 walk_complex_for_matchers(ct, &self.substitutions, &types_snapshot,
484 &mut visited, target_ns_ref)?;
485 }
486 }
487 for decl in self.elements.values() {
488 if let TypeRef::Complex(ct) = &decl.type_def {
489 walk_complex_for_matchers(ct, &self.substitutions, &types_snapshot,
490 &mut visited, target_ns_ref)?;
491 }
492 }
493
494 Ok(Schema::from_inner(SchemaInner {
495 target_namespace: self.target_ns,
496 elements: self.elements,
497 attributes: self.attributes,
498 types: self.types,
499 attribute_groups: self.attr_groups,
500 model_groups: self.model_groups,
501 notations: self.notations,
502 substitutions: self.substitutions,
503 }))
504 }
505}
506
507fn parse_one_file<R: SchemaResolver>(
510 xsd: &str,
511 builder: &mut Builder,
512 resolver: &R,
513 expected_target_ns: Option<&str>,
514 is_import: bool,
515) -> Result<(), SchemaCompileError> {
516 if builder.depth >= MAX_INCLUDE_DEPTH {
517 return Err(SchemaCompileError::msg(format!(
518 "schema include nesting exceeded {MAX_INCLUDE_DEPTH} levels"
519 )));
520 }
521 let mut p = Parser::new(xsd, builder, resolver, expected_target_ns);
522 p.is_import_target = is_import;
523 p.parse_schema()
524}
525
526struct Parser<'a, 'b, R: SchemaResolver> {
529 reader: XmlReader<'a>,
530 builder: &'b mut Builder,
531 resolver: &'b R,
532 expected_target_ns: Option<&'b str>,
536 is_import_target: bool,
542 current_target_ns: Option<Arc<str>>,
548 element_form_default: Form,
552 attribute_form_default: Form,
554 block_default: BlockSet,
558 final_default: BlockSet,
560 ns_stack: Vec<HashMap<String, String>>,
561 attr_buf: Vec<Attr<'a>>,
562 seen_ids: HashSet<String>,
567 seen_ic_names: HashSet<QName>,
571 local_top_element_names: HashSet<QName>,
575 in_redefine: bool,
579 last_simple_restriction_base: Option<QName>,
584 simple_type_in_flight: Option<QName>,
589}
590
591#[derive(Debug, Clone, Copy, PartialEq, Eq)]
592enum Form { Qualified, Unqualified }
593
594impl Form {
595 fn parse(s: &str) -> Option<Self> {
596 match s {
597 "qualified" => Some(Form::Qualified),
598 "unqualified" => Some(Form::Unqualified),
599 _ => None,
600 }
601 }
602}
603
604const XS: &str = "http://www.w3.org/2001/XMLSchema";
605
606impl<'a, 'b, R: SchemaResolver> Parser<'a, 'b, R> {
607 fn new(
608 input: &'a str,
609 builder: &'b mut Builder,
610 resolver: &'b R,
611 expected_target_ns: Option<&'b str>,
612 ) -> Self {
613 Self {
614 reader: XmlReader::from_str(input),
615 builder,
616 resolver,
617 expected_target_ns,
618 is_import_target: false,
619 current_target_ns: None,
623 element_form_default: Form::Unqualified,
627 attribute_form_default: Form::Unqualified,
628 block_default: BlockSet::default(),
629 final_default: BlockSet::default(),
630 ns_stack: vec![{
631 let mut m = HashMap::new();
635 m.insert("xml".to_string(), "http://www.w3.org/XML/1998/namespace".to_string());
636 m
637 }],
638 attr_buf: Vec::new(),
639 seen_ids: HashSet::new(),
640 seen_ic_names: HashSet::new(),
641 local_top_element_names: HashSet::new(),
642 in_redefine: false,
643 last_simple_restriction_base: None,
644 simple_type_in_flight: None,
645 }
646 }
647
648 fn take_attrs(&mut self) -> Result<Vec<Attr<'a>>, SchemaCompileError> {
653 let attrs: Vec<Attr<'a>> = self.attr_buf.drain(..).collect();
654 self.validate_id_attr(&attrs)?;
655 self.validate_name_attr(&attrs)?;
656 Ok(attrs)
657 }
658
659 fn validate_id_attr(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
660 let Some(id) = self.attr(attrs, "id") else { return Ok(()) };
661 super::types::SimpleType::of_builtin(super::types::BuiltinType::Id)
662 .validate(id)
663 .map_err(|e| self.err(format!(
664 "id={id:?} is not a valid ID/NCName: {}", e.message
665 )))?;
666 if !self.seen_ids.insert(id.to_owned()) {
667 return Err(self.err(format!("duplicate id {id:?} in schema")));
668 }
669 Ok(())
670 }
671
672 fn validate_name_attr(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
680 let Some(name) = self.attr(attrs, "name") else { return Ok(()) };
681 super::types::SimpleType::of_builtin(super::types::BuiltinType::NCName)
682 .validate(name)
683 .map_err(|e| self.err(format!(
684 "name={name:?} is not a valid NCName: {}", e.message
685 )))?;
686 Ok(())
687 }
688
689 fn err(&self, msg: impl Into<String>) -> SchemaCompileError {
690 SchemaCompileError::msg(msg)
691 }
692
693 fn parse_xsd_bool(
698 &self,
699 attrs: &[Attr<'a>],
700 name: &str,
701 ) -> Result<Option<bool>, SchemaCompileError> {
702 let Some(raw) = self.attr(attrs, name) else { return Ok(None); };
703 match raw {
704 "true" | "1" => Ok(Some(true)),
705 "false" | "0" => Ok(Some(false)),
706 _ => Err(self.err(format!(
707 "{name}={raw:?}: must be \"true\", \"false\", \"1\", or \"0\""
708 ))),
709 }
710 }
711
712 fn check_annotation_pos(
719 &self,
720 local: &str,
721 seen_annotation: &mut bool,
722 seen_non_annotation: &mut bool,
723 parent: &str,
724 ) -> Result<(), SchemaCompileError> {
725 if local == "annotation" {
726 if *seen_annotation {
727 return Err(self.err(format!(
728 "<xs:{parent}> may have at most one <xs:annotation> child"
729 )));
730 }
731 if *seen_non_annotation {
732 return Err(self.err(format!(
733 "<xs:annotation> must precede other children of <xs:{parent}>"
734 )));
735 }
736 *seen_annotation = true;
737 } else {
738 *seen_non_annotation = true;
739 }
740 Ok(())
741 }
742
743 fn parse_anno_only_body(&mut self, parent: &str) -> Result<(), SchemaCompileError> {
749 let mut seen_anno = false;
750 let mut seen_other = false;
751 loop {
752 match self.next_event()? {
753 EventInto::StartElement { name } => {
754 let child_attrs = self.take_attrs()?;
755 self.push_ns_scope(&child_attrs);
756 let qn = self.qname_of_element(&name)?;
757 if qn.namespace.as_deref() == Some(XS) {
758 self.check_annotation_pos(
759 &qn.local, &mut seen_anno, &mut seen_other, parent,
760 )?;
761 match qn.local.as_ref() {
762 "annotation" => self.parse_annotation_body(&child_attrs)?,
763 other => return Err(self.err(format!(
764 "<xs:{parent}> body may only contain <xs:annotation>, \
765 found <xs:{other}>"
766 ))),
767 }
768 } else if qn.namespace.is_none() {
769 return Err(self.err(format!(
776 "<xs:{parent}> body may only contain <xs:annotation>, \
777 found <{}>", qn.local,
778 )));
779 } else {
780 self.skip_body()?;
783 }
784 self.pop_ns_scope();
785 }
786 EventInto::Text(t) | EventInto::CData(t) => {
787 if !t.chars().all(char::is_whitespace) {
788 return Err(self.err(format!(
789 "<xs:{parent}> body has non-whitespace text content"
790 )));
791 }
792 }
793 EventInto::EndElement { .. } => return Ok(()),
794 EventInto::Eof => return Err(self.err("unexpected EOF")),
795 _ => {}
796 }
797 }
798 }
799
800 fn type_ref_for(&self, type_qn: QName) -> TypeRef {
808 if type_qn.namespace.as_deref() == Some(QName::XSD_NS) {
809 if let Some(b) = BuiltinType::from_name(&type_qn.local) {
810 return TypeRef::Simple(Arc::new(SimpleType::of_builtin(b)));
811 }
812 if type_qn.local.as_ref() == "anyType" {
817 return any_type_ref();
818 }
819 }
820 TypeRef::Simple(Arc::new(SimpleType {
822 name: Some(Arc::from(format!("UNRESOLVED:{type_qn}"))),
823 builtin: BuiltinType::String,
824 facets: FacetSet::default(),
825 whitespace: WhitespaceMode::Preserve,
826 variety: super::types::Variety::Atomic,
827 final_: super::schema::BlockSet::default(),
828 assertions: Vec::new(),
829 }))
830 }
831
832 fn simple_type_for(&self, type_qn: QName) -> Arc<SimpleType> {
835 if type_qn.namespace.as_deref() == Some(QName::XSD_NS) {
836 if let Some(b) = BuiltinType::from_name(&type_qn.local) {
837 return Arc::new(SimpleType::of_builtin(b));
838 }
839 }
840 Arc::new(SimpleType {
841 name: Some(Arc::from(format!("UNRESOLVED:{type_qn}"))),
842 builtin: BuiltinType::String,
843 facets: FacetSet::default(),
844 whitespace: WhitespaceMode::Preserve,
845 variety: super::types::Variety::Atomic,
846 final_: super::schema::BlockSet::default(),
847 assertions: Vec::new(),
848 })
849 }
850
851 fn push_ns_scope(&mut self, attrs: &[Attr<'a>]) {
854 let top = self.ns_stack.last().cloned().unwrap_or_default();
855 let mut new = top;
856 for a in attrs {
857 let name = a.name;
858 if name == "xmlns" {
859 new.insert(String::new(), a.value.to_string());
860 } else if let Some(prefix) = name.strip_prefix("xmlns:") {
861 new.insert(prefix.to_string(), a.value.to_string());
862 }
863 }
864 self.ns_stack.push(new);
865 }
866
867 fn pop_ns_scope(&mut self) {
868 self.ns_stack.pop();
869 }
870
871 fn resolve_prefix(&self, prefix: &str) -> Option<&str> {
874 for scope in self.ns_stack.iter().rev() {
875 if let Some(uri) = scope.get(prefix) {
876 return Some(uri.as_str());
877 }
878 }
879 None
880 }
881
882 fn parse_qname(&self, raw: &str, null_ns_default: bool) -> Result<QName, SchemaCompileError> {
887 let ncname_check = |s: &str, label: &str| -> Result<(), SchemaCompileError> {
890 super::types::SimpleType::of_builtin(super::types::BuiltinType::NCName)
891 .validate(s)
892 .map_err(|e| self.err(format!(
893 "QName {label} {s:?} is not an NCName: {}", e.message,
894 )))?;
895 Ok(())
896 };
897 match raw.split_once(':') {
898 Some((prefix, local)) => {
899 ncname_check(prefix, "prefix")?;
900 ncname_check(local, "local part")?;
901 let uri = self.resolve_prefix(prefix).ok_or_else(||
902 self.err(format!("undeclared namespace prefix {prefix:?}"))
903 )?;
904 Ok(QName::new(Some(uri), local))
905 }
906 None => {
907 ncname_check(raw, "local part")?;
908 let uri = if null_ns_default { None } else {
909 self.resolve_prefix("").map(|s| s.to_owned())
910 .or_else(|| self.current_target_ns.as_deref().map(|s| s.to_owned()))
911 };
912 Ok(QName {
913 namespace: uri.map(Arc::from),
914 local: Arc::from(raw),
915 })
916 }
917 }
918 }
919
920 fn parse_inheritable(&self, attrs: &[Attr<'a>]) -> Result<bool, SchemaCompileError> {
926 let Some(raw) = self.attr(attrs, "inheritable") else { return Ok(false); };
927 if !matches!(self.builder.effective_version, SchemaVersion::Xsd11) {
928 return Err(self.err(
929 "<xs:attribute inheritable=...> is an XSD 1.1 attribute — \
930 set SchemaOptions::version to Xsd11, or to Auto with \
931 vc:minVersion=\"1.1\" on <xs:schema>",
932 ));
933 }
934 match raw {
935 "true" | "1" => Ok(true),
936 "false" | "0" => Ok(false),
937 other => Err(self.err(format!(
938 "<xs:attribute inheritable={other:?}>: must be \"true\" or \"false\""
939 ))),
940 }
941 }
942
943 fn parse_wildcard(&self, attrs: &[Attr<'a>]) -> Result<Wildcard, SchemaCompileError> {
947 self.check_known_attrs(attrs, &[
955 "id", "namespace", "processContents", "minOccurs", "maxOccurs",
956 "notQName", "notNamespace",
957 ], "any")?;
958 parse_wildcard_attrs(
959 attrs,
960 &self.current_target_ns,
961 self.builder.effective_version,
962 &mut |tok| self.parse_qname(tok, false),
963 )
964 }
965
966 fn next_event(&mut self) -> Result<EventInto<'a>, SchemaCompileError> {
969 loop {
970 let ev = self.reader.next_into(&mut self.attr_buf)?;
971 match ev {
972 EventInto::Comment(_) | EventInto::Pi { .. } => continue,
973 _ => return Ok(ev),
974 }
975 }
976 }
977
978 fn skip_body(&mut self) -> Result<(), SchemaCompileError> {
981 let mut depth = 1usize;
982 while depth > 0 {
983 match self.next_event()? {
984 EventInto::StartElement { .. } => depth += 1,
985 EventInto::EndElement { .. } => depth -= 1,
986 EventInto::Eof => return Err(self.err("unexpected EOF inside element")),
987 _ => {}
988 }
989 }
990 Ok(())
991 }
992
993 fn parse_assertion_body(&mut self, attrs: &[Attr<'a>])
1005 -> Result<Option<super::schema::Assertion>, SchemaCompileError>
1006 {
1007 let test = self.attr(attrs, "test").map(str::to_string);
1008 let default = self.attr(attrs, "xpathDefaultNamespace").map(str::to_string);
1009 let namespaces: Vec<(Option<String>, String)> = self.ns_stack.last()
1012 .map(|top| top.iter()
1013 .map(|(prefix, uri)| {
1014 let p = if prefix.is_empty() { None } else { Some(prefix.clone()) };
1015 (p, uri.clone())
1016 })
1017 .collect())
1018 .unwrap_or_default();
1019 self.skip_body()?;
1020 Ok(test.filter(|t| !t.is_empty()).map(|test| super::schema::Assertion {
1021 test,
1022 namespaces,
1023 xpath_default_namespace: default,
1024 }))
1025 }
1026
1027 fn parse_annotation_body(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
1033 self.check_known_attrs(attrs, &["id"], "annotation")?;
1037 loop {
1038 match self.next_event()? {
1039 EventInto::StartElement { name } => {
1040 let child_attrs = self.take_attrs()?;
1041 self.push_ns_scope(&child_attrs);
1042 let qn = self.qname_of_element(&name)?;
1043 if qn.namespace.as_deref() == Some(XS) {
1044 match qn.local.as_ref() {
1045 "appinfo" => {
1046 self.check_known_attrs(&child_attrs, &["source"], "appinfo")?;
1047 }
1048 "documentation" => {
1049 self.check_known_attrs(&child_attrs,
1050 &["source", "xml:lang"], "documentation")?;
1051 if let Some(lang) = self.attr(&child_attrs, "xml:lang") {
1052 if lang.trim().is_empty() {
1053 return Err(self.err(
1054 "<xs:documentation xml:lang=...>: language tag \
1055 must not be empty or whitespace-only",
1056 ));
1057 }
1058 }
1059 }
1060 other => return Err(self.err(format!(
1061 "<xs:{other}> is not allowed as a child of <xs:annotation>"
1062 ))),
1063 }
1064 }
1065 self.skip_body()?;
1068 self.pop_ns_scope();
1069 }
1070 EventInto::EndElement { .. } => return Ok(()),
1071 EventInto::Eof => return Err(self.err("unexpected EOF inside <xs:annotation>")),
1072 _ => {}
1073 }
1074 }
1075 }
1076
1077 fn parse_schema(&mut self) -> Result<(), SchemaCompileError> {
1080 let ev = self.next_event()?;
1082 let attrs = match ev {
1083 EventInto::StartElement { name } => {
1084 let attrs = self.take_attrs()?;
1085 self.push_ns_scope(&attrs);
1086 let qn = self.qname_of_element(&name)?;
1087 if qn.namespace.as_deref() != Some(XS) || qn.local.as_ref() != "schema" {
1088 return Err(self.err(format!(
1089 "root element must be xs:schema, got {qn}"
1090 )));
1091 }
1092 attrs
1093 }
1094 _ => return Err(self.err("XSD must start with <xs:schema>")),
1095 };
1096 self.check_known_attrs(&attrs, &[
1104 "id", "targetNamespace", "version", "attributeFormDefault",
1105 "elementFormDefault", "blockDefault", "finalDefault",
1106 "defaultAttributes",
1107 ], "schema")?;
1108 let mut this_target_ns: Option<Arc<str>> = None;
1114 for a in &attrs {
1115 match a.name() {
1116 "targetNamespace" => {
1117 let v = a.value.as_ref();
1118 if v.is_empty() {
1119 return Err(self.err(
1120 "<xs:schema targetNamespace=\"\">: empty namespace URI is not allowed"
1121 ));
1122 }
1123 this_target_ns = Some(Arc::from(v));
1124 }
1125 "elementFormDefault" => {
1126 self.element_form_default = Form::parse(a.value.as_ref()).ok_or_else(|| self.err(
1127 format!("<xs:schema elementFormDefault={:?}>: must be \"qualified\" or \"unqualified\"", a.value)
1128 ))?;
1129 }
1130 "attributeFormDefault" => {
1131 self.attribute_form_default = Form::parse(a.value.as_ref()).ok_or_else(|| self.err(
1132 format!("<xs:schema attributeFormDefault={:?}>: must be \"qualified\" or \"unqualified\"", a.value)
1133 ))?;
1134 }
1135 "blockDefault" => {
1136 self.block_default = parse_block_set(Some(a.value.as_ref()))?;
1137 }
1138 "finalDefault" => {
1139 self.final_default = parse_block_set(Some(a.value.as_ref()))?;
1140 }
1141 _ => {}
1142 }
1143 }
1144 if matches!(self.builder.options.version, SchemaVersion::Auto) {
1150 let min_version = attrs.iter().find(|a| a.name() == "vc:minVersion");
1151 if let Some(mv) = min_version {
1152 if mv.value.as_ref().trim() == "1.1" {
1153 self.builder.effective_version = SchemaVersion::Xsd11;
1154 }
1155 }
1156 }
1157 match (&self.expected_target_ns, &this_target_ns) {
1158 (Some(expected), Some(found)) => {
1159 if expected != &found.as_ref() {
1160 return Err(self.err(format!(
1161 "included schema has targetNamespace={found:?}, expected {expected:?}"
1162 )));
1163 }
1164 self.current_target_ns = Some(found.clone());
1165 }
1166 (Some(expected), None) => {
1167 if self.is_import_target {
1168 return Err(self.err(format!(
1173 "imported schema has no targetNamespace, expected {expected:?}"
1174 )));
1175 }
1176 self.current_target_ns = Some(Arc::from(*expected));
1179 }
1180 (None, Some(found)) => {
1181 if self.builder.depth > 0 {
1182 return Err(self.err(format!(
1187 "included schema has targetNamespace={found:?}, \
1188 but the including schema has no targetNamespace"
1189 )));
1190 }
1191 self.current_target_ns = Some(found.clone());
1192 if self.builder.target_ns.is_none() {
1193 self.builder.target_ns = Some(found.clone());
1194 }
1195 }
1196 (None, None) => {} }
1198
1199 loop {
1201 match self.next_event()? {
1202 EventInto::StartElement { name } => {
1203 let attrs = self.take_attrs()?;
1204 self.push_ns_scope(&attrs);
1205 let qn = self.qname_of_element(&name)?;
1206 let ns = qn.namespace.as_deref();
1207 if ns != Some(XS) {
1208 if ns.is_none() {
1209 return Err(self.err(format!(
1215 "element <{}> at the schema top level is not in \
1216 the XML Schema namespace (missing prefix?)",
1217 qn.local)));
1218 }
1219 self.skip_body()?;
1223 self.pop_ns_scope();
1224 continue;
1225 }
1226 match qn.local.as_ref() {
1227 "element" => self.parse_top_element(&attrs)?,
1228 "attribute" => self.parse_top_attribute(&attrs)?,
1229 "simpleType" => self.parse_top_simple_type(&attrs)?,
1230 "complexType" => self.parse_top_complex_type(&attrs)?,
1231 "attributeGroup" => self.parse_top_attribute_group(&attrs)?,
1232 "group" => self.parse_top_group(&attrs)?,
1233 "notation" => self.parse_top_notation(&attrs)?,
1234 "import" => self.handle_import(&attrs)?,
1235 "include" => self.handle_include(&attrs)?,
1236 "redefine" => self.handle_redefine(&attrs)?,
1237 "override" => {
1238 if !matches!(self.builder.effective_version, SchemaVersion::Xsd11) {
1239 return Err(self.err(
1240 "<xs:override> is an XSD 1.1 directive — \
1241 set SchemaOptions::version to Xsd11, or to Auto \
1242 with vc:minVersion=\"1.1\" on <xs:schema>",
1243 ));
1244 }
1245 self.handle_override(&attrs)?;
1246 }
1247 "annotation" => self.parse_annotation_body(&attrs)?,
1248 other => return Err(self.err(format!(
1249 "unexpected top-level element <xs:{other}>"
1250 ))),
1251 }
1252 self.pop_ns_scope();
1253 }
1254 EventInto::EndElement { .. } => break,
1255 EventInto::Eof => return Err(self.err("unexpected EOF")),
1256 _ => {}
1257 }
1258 }
1259 Ok(())
1260 }
1261
1262 fn handle_import(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
1265 self.check_known_attrs(attrs, &["id", "namespace", "schemaLocation"], "import")?;
1266 let imported_ns = self.attr(attrs, "namespace").map(|s| s.to_owned());
1267 self.builder.imported_namespaces.insert(
1270 imported_ns.as_deref().map(Arc::from),
1271 );
1272 if imported_ns.as_deref() == Some("") {
1276 return Err(self.err(
1277 "<xs:import namespace=\"\">: empty namespace URI is not allowed \
1278 (omit the attribute to import the no-namespace components)"
1279 ));
1280 }
1281 if imported_ns.as_deref() == self.current_target_ns.as_deref() {
1289 return Err(self.err(format!(
1290 "<xs:import namespace={:?}> matches this schema's own \
1291 targetNamespace — use <xs:include> for same-namespace composition",
1292 imported_ns.as_deref().unwrap_or(""),
1293 )));
1294 }
1295 let location = self.attr(attrs, "schemaLocation");
1296 self.parse_anno_only_body("import")?;
1297
1298 let Some(loc) = location else {
1299 return Ok(());
1303 };
1304 if let (Some(imp), Some(root)) = (
1310 imported_ns.as_deref(), self.builder.target_ns.as_deref(),
1311 ) {
1312 if imp == root {
1313 return Ok(());
1318 }
1319 }
1320 self.load_schema_via_resolver(loc, imported_ns.as_deref(), true)
1321 }
1322
1323 fn handle_include(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
1324 let location = self.attr(attrs, "schemaLocation").ok_or_else(||
1325 self.err("<xs:include> missing schemaLocation")
1326 )?.to_owned();
1327 self.parse_anno_only_body("include")?;
1328 let expected_ns = self.current_target_ns.as_deref().map(str::to_owned);
1330 self.load_schema_via_resolver(&location, expected_ns.as_deref(), false)
1331 }
1332
1333 fn handle_redefine(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
1343 self.check_known_attrs(attrs, &["id", "schemaLocation"], "redefine")?;
1344 let location = self.attr(attrs, "schemaLocation").ok_or_else(||
1345 self.err("<xs:redefine> missing schemaLocation")
1346 )?.to_owned();
1347 let expected_ns = self.current_target_ns.as_deref().map(str::to_owned);
1348 self.load_schema_via_resolver(&location, expected_ns.as_deref(), false)?;
1349
1350 let snapshot: HashMap<QName, TypeRef> = self.builder.types.clone();
1359 let snapshot_groups: HashSet<QName> = self.builder.model_groups.keys().cloned().collect();
1364 let snapshot_attr_groups: HashSet<QName> = self.builder.attr_groups.keys().cloned().collect();
1365
1366 let prev_in_redefine = self.in_redefine;
1367 self.in_redefine = true;
1368 let result = (|| -> Result<(), SchemaCompileError> {
1369 loop {
1370 match self.next_event()? {
1371 EventInto::StartElement { name } => {
1372 let child_attrs = self.take_attrs()?;
1373 self.push_ns_scope(&child_attrs);
1374 let qn = self.qname_of_element(&name)?;
1375 if qn.namespace.as_deref() == Some(XS) {
1376 match qn.local.as_ref() {
1377 "simpleType" => {
1378 self.check_redefined_type_exists(&child_attrs, &snapshot)?;
1379 self.last_simple_restriction_base = None;
1380 self.parse_top_simple_type(&child_attrs)?;
1381 self.check_redefined_simple_base(&child_attrs)?;
1382 }
1383 "complexType" => {
1384 self.check_redefined_type_exists(&child_attrs, &snapshot)?;
1385 self.parse_top_complex_type(&child_attrs)?;
1386 self.check_redefined_complex_base(&child_attrs)?;
1387 self.fixup_redefined_complex_base(&child_attrs, &snapshot);
1388 }
1389 "group" => {
1390 self.check_redefined_set_exists(&child_attrs,
1391 &snapshot_groups, "group")?;
1392 let qn = self.attr(&child_attrs, "name").map(|n| QName {
1393 namespace: self.current_target_ns.clone(),
1394 local: Arc::from(n),
1395 });
1396 let original_particle = qn.as_ref()
1397 .and_then(|n| self.builder.model_groups.get(n))
1398 .map(|g| g.particle.clone());
1399 self.parse_top_group(&child_attrs)?;
1400 if let Some(name) = qn {
1401 self.builder.redefined_groups.insert(name.clone());
1402 if let (Some(original), Some(new_group)) =
1403 (original_particle, self.builder.model_groups.get(&name))
1404 {
1405 self.builder.redefined_group_originals.push((
1406 name,
1407 new_group.particle.clone(),
1408 original,
1409 ));
1410 }
1411 }
1412 }
1413 "attributeGroup" => {
1414 self.check_redefined_set_exists(&child_attrs,
1415 &snapshot_attr_groups, "attributeGroup")?;
1416 let qn = self.attr(&child_attrs, "name").map(|n| QName {
1417 namespace: self.current_target_ns.clone(),
1418 local: Arc::from(n),
1419 });
1420 let original = qn.as_ref()
1421 .and_then(|n| self.builder.attr_groups.get(n))
1422 .cloned();
1423 self.builder.redefining_ag_name = qn.clone();
1424 self.builder.redefining_ag_saw_self_ref = false;
1425 self.parse_top_attribute_group(&child_attrs)?;
1426 let saw_self_ref = self.builder.redefining_ag_saw_self_ref;
1427 self.builder.redefining_ag_name = None;
1428 self.builder.redefining_ag_saw_self_ref = false;
1429 if let (Some(name), Some(orig)) = (qn, original) {
1430 if let Some(new_ag) = self.builder.attr_groups.get(&name) {
1431 self.builder.redefined_attr_group_originals.push((
1432 name, new_ag.clone(), orig, saw_self_ref,
1433 ));
1434 }
1435 }
1436 }
1437 "annotation" => self.parse_annotation_body(&child_attrs)?,
1438 other => return Err(self.err(format!(
1439 "<xs:redefine> body: unexpected child <xs:{other}>"
1440 ))),
1441 }
1442 } else {
1443 self.skip_body()?;
1445 }
1446 self.pop_ns_scope();
1447 }
1448 EventInto::EndElement { .. } => break,
1449 EventInto::Eof => return Err(self.err("unexpected EOF in <xs:redefine>")),
1450 _ => {}
1451 }
1452 }
1453 Ok(())
1454 })();
1455 self.in_redefine = prev_in_redefine;
1456 result
1457 }
1458
1459 fn handle_override(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
1477 let location = self.attr(attrs, "schemaLocation").ok_or_else(||
1478 self.err("<xs:override> missing schemaLocation")
1479 )?.to_owned();
1480 let expected_ns = self.current_target_ns.as_deref().map(str::to_owned);
1481 self.load_schema_via_resolver(&location, expected_ns.as_deref(), false)?;
1482
1483 loop {
1484 match self.next_event()? {
1485 EventInto::StartElement { name } => {
1486 let child_attrs = self.take_attrs()?;
1487 self.push_ns_scope(&child_attrs);
1488 let qn = self.qname_of_element(&name)?;
1489 if qn.namespace.as_deref() == Some(XS) {
1490 match qn.local.as_ref() {
1491 "simpleType" => self.parse_top_simple_type(&child_attrs)?,
1492 "complexType" => self.parse_top_complex_type(&child_attrs)?,
1493 "group" => self.parse_top_group(&child_attrs)?,
1494 "attributeGroup" => self.parse_top_attribute_group(&child_attrs)?,
1495 "element" => self.parse_top_element(&child_attrs)?,
1496 "attribute" => self.parse_top_attribute(&child_attrs)?,
1497 "notation" => self.parse_top_notation(&child_attrs)?,
1498 "annotation" => self.parse_annotation_body(&child_attrs)?,
1499 other => return Err(self.err(format!(
1500 "<xs:override> body: unexpected child <xs:{other}>"
1501 ))),
1502 }
1503 } else {
1504 self.skip_body()?;
1506 }
1507 self.pop_ns_scope();
1508 }
1509 EventInto::EndElement { .. } => break,
1510 EventInto::Eof => return Err(self.err("unexpected EOF in <xs:override>")),
1511 _ => {}
1512 }
1513 }
1514 Ok(())
1515 }
1516
1517 fn check_redefined_type_exists(
1526 &self,
1527 child_attrs: &[Attr<'a>],
1528 snapshot: &HashMap<QName, TypeRef>,
1529 ) -> Result<(), SchemaCompileError> {
1530 let Some(name) = self.attr(child_attrs, "name") else { return Ok(()); };
1531 let own_qn = QName {
1532 namespace: self.current_target_ns.clone(),
1533 local: Arc::from(name),
1534 };
1535 if !snapshot.contains_key(&own_qn) {
1536 return Err(self.err(format!(
1537 "<xs:redefine>: cannot redefine type {:?} — the loaded original \
1538 doesn't declare a type with this name (src-redefine)",
1539 own_qn.local,
1540 )));
1541 }
1542 Ok(())
1543 }
1544
1545 fn check_redefined_set_exists(
1546 &self,
1547 child_attrs: &[Attr<'a>],
1548 snapshot: &HashSet<QName>,
1549 kind: &str,
1550 ) -> Result<(), SchemaCompileError> {
1551 let Some(name) = self.attr(child_attrs, "name") else { return Ok(()); };
1552 let own_qn = QName {
1553 namespace: self.current_target_ns.clone(),
1554 local: Arc::from(name),
1555 };
1556 if !snapshot.contains(&own_qn) {
1557 return Err(self.err(format!(
1558 "<xs:redefine>: cannot redefine {kind} {:?} — the loaded original \
1559 doesn't declare a {kind} with this name (src-redefine)",
1560 own_qn.local,
1561 )));
1562 }
1563 Ok(())
1564 }
1565
1566 fn check_redefined_simple_base(
1571 &mut self,
1572 child_attrs: &[Attr<'a>],
1573 ) -> Result<(), SchemaCompileError> {
1574 let Some(name) = self.attr(child_attrs, "name") else { return Ok(()); };
1575 let own_qn = QName {
1576 namespace: self.current_target_ns.clone(),
1577 local: Arc::from(name),
1578 };
1579 let bad = match &self.last_simple_restriction_base {
1580 None => true,
1583 Some(base) => base != &own_qn,
1584 };
1585 if bad {
1586 return Err(self.err(format!(
1587 "<xs:redefine><xs:simpleType name={:?}>: the redefining body must \
1588 restrict {0:?} itself (its `<xs:restriction base=>` must resolve \
1589 to {0:?}); a different base is not a self-restriction per \
1590 src-redefine",
1591 own_qn.local,
1592 )));
1593 }
1594 Ok(())
1595 }
1596
1597 fn check_redefined_complex_base(
1601 &mut self,
1602 child_attrs: &[Attr<'a>],
1603 ) -> Result<(), SchemaCompileError> {
1604 let Some(name) = self.attr(child_attrs, "name") else { return Ok(()); };
1605 let own_qn = QName {
1606 namespace: self.current_target_ns.clone(),
1607 local: Arc::from(name),
1608 };
1609 let Some(TypeRef::Complex(redef)) = self.builder.types.get(&own_qn).cloned() else { return Ok(()) };
1610 let Some(d) = redef.derivation.as_ref() else {
1611 return Err(self.err(format!(
1612 "<xs:redefine><xs:complexType name={:?}>: the redefining body must \
1613 derive (via <xs:restriction> or <xs:extension>) from the original \
1614 {0:?}",
1615 own_qn.local,
1616 )));
1617 };
1618 let base_qn = resolve_typeref_to_qname(&d.base);
1619 if base_qn.as_ref() != Some(&own_qn) {
1620 return Err(self.err(format!(
1621 "<xs:redefine><xs:complexType name={:?}>: the redefining body's \
1622 derivation base must be {0:?} itself (per src-redefine), not a \
1623 different type",
1624 own_qn.local,
1625 )));
1626 }
1627 Ok(())
1628 }
1629
1630 fn fixup_redefined_complex_base(
1631 &mut self,
1632 child_attrs: &[Attr<'a>],
1633 snapshot: &HashMap<QName, TypeRef>,
1634 ) {
1635 let Some(name) = self.attr(child_attrs, "name") else { return };
1636 let own_qn = QName {
1637 namespace: self.current_target_ns.clone(),
1638 local: Arc::from(name),
1639 };
1640 let Some(TypeRef::Complex(redef)) = self.builder.types.get(&own_qn).cloned() else { return };
1641 let Some(d) = redef.derivation.as_ref() else { return };
1642 let Some(base_qn) = resolve_typeref_to_qname(&d.base) else { return };
1643 if base_qn != own_qn { return; }
1644 let Some(original) = snapshot.get(&own_qn).cloned() else { return };
1645 let new_derivation = Derivation {
1646 method: d.method,
1647 base: original,
1648 };
1649 let new_ct = ComplexType {
1650 name: redef.name.clone(),
1651 derivation: Some(new_derivation),
1652 content: redef.content.clone(),
1653 matcher: std::sync::OnceLock::new(),
1654 attributes: redef.attributes.clone(),
1655 any_attribute: redef.any_attribute.clone(),
1656 abstract_: redef.abstract_,
1657 block: redef.block,
1658 final_: redef.final_,
1659 pending_attribute_group_refs: redef.pending_attribute_group_refs.clone(),
1660 assertions: redef.assertions.clone(),
1661 };
1662 self.builder.types.insert(own_qn, TypeRef::Complex(Arc::new(new_ct)));
1663 }
1664
1665 fn load_schema_via_resolver(
1668 &mut self,
1669 location: &str,
1670 expected_ns: Option<&str>,
1671 is_import: bool,
1672 ) -> Result<(), SchemaCompileError> {
1673 if self.builder.loaded.contains(location) {
1674 return Ok(()); }
1676 let bytes = match self.resolver.resolve(location, expected_ns) {
1692 Ok(Some(b)) => b,
1693 Ok(None) => {
1694 self.builder.loaded.insert(location.to_owned());
1695 return Ok(());
1696 }
1697 Err(e) => {
1698 self.builder.loaded.insert(location.to_owned());
1699 return Err(self.err(format!(
1700 "<xs:{}>: failed to resolve schemaLocation {location:?}: {e}",
1701 if is_import { "import" } else { "include" },
1702 )));
1703 }
1704 };
1705 let s = std::str::from_utf8(&bytes).map_err(|e| self.err(format!(
1706 "schema {location:?} is not valid UTF-8: {e}"
1707 )))?;
1708
1709 self.builder.loaded.insert(location.to_owned());
1710 self.builder.depth += 1;
1711 let result = parse_one_file(s, self.builder, self.resolver, expected_ns, is_import);
1712 self.builder.depth -= 1;
1713 result
1714 }
1715
1716 fn qname_of_element(&self, name: &str) -> Result<QName, SchemaCompileError> {
1719 match name.split_once(':') {
1720 Some((prefix, local)) => {
1721 let uri = self.resolve_prefix(prefix).ok_or_else(||
1722 self.err(format!("undeclared element prefix {prefix:?}"))
1723 )?;
1724 Ok(QName::new(Some(uri), local))
1725 }
1726 None => {
1727 let uri = self.resolve_prefix("").map(|s| s.to_owned());
1729 Ok(QName {
1730 namespace: uri.map(Arc::from),
1731 local: Arc::from(name),
1732 })
1733 }
1734 }
1735 }
1736
1737 fn attr<'r>(&self, attrs: &'r [Attr<'a>], name: &str) -> Option<&'r str> {
1740 attrs.iter().find(|a| a.name() == name).map(|a| a.value.as_ref())
1741 }
1742
1743 fn check_known_attrs(
1749 &self,
1750 attrs: &[Attr<'a>],
1751 allowed: &[&str],
1752 owner: &str,
1753 ) -> Result<(), SchemaCompileError> {
1754 for a in attrs {
1755 let name = a.name;
1756 if name == "xmlns" || name.starts_with("xmlns:") { continue; }
1758 if name.starts_with("xml:") { continue; }
1761 if let Some((prefix, _local)) = name.split_once(':') {
1762 let resolved = self.resolve_prefix(prefix);
1763 if matches!(resolved, Some(uri) if uri != XS) {
1767 continue;
1768 }
1769 return Err(self.err(format!(
1774 "<xs:{owner}>: attribute {name:?} is in the XSD namespace; \
1775 XSD-defined attributes on schema elements must be unqualified"
1776 )));
1777 } else {
1778 if !allowed.contains(&name) {
1779 return Err(self.err(format!(
1780 "<xs:{owner}>: attribute {name:?} is not recognised \
1781 (allowed: {allowed:?})"
1782 )));
1783 }
1784 }
1785 }
1786 Ok(())
1787 }
1788
1789 fn parse_top_element(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
1792 self.check_known_attrs(attrs, &[
1794 "id", "name", "type", "default", "fixed", "nillable",
1795 "abstract", "substitutionGroup", "block", "final",
1796 ], "element")?;
1797 let name = self.attr(attrs, "name").ok_or_else(||
1798 self.err("<xs:element> missing name attribute")
1799 )?.to_owned();
1800 let qn = QName {
1801 namespace: self.current_target_ns.clone(),
1802 local: Arc::from(name.as_str()),
1803 };
1804
1805 let (inline, identity) = self.parse_inline_type(attrs)?;
1807 let type_def = match self.attr(attrs, "type") {
1808 Some(t) => {
1809 if inline.is_some() {
1813 return Err(self.err(format!(
1814 "<xs:element name={name:?}> has both a `type=` attribute and \
1815 a nested type body; pick one (XSD §3.3.3 src-element.3)",
1816 )));
1817 }
1818 let type_qn = self.parse_qname(t, false)?;
1819 self.type_ref_for(type_qn)
1820 }
1821 None => match inline {
1822 Some(t) => t,
1823 None => any_type_ref(),
1824 },
1825 };
1826
1827 let nillable = self.parse_xsd_bool(attrs, "nillable")?.unwrap_or(false);
1828 let default = self.attr(attrs, "default").map(|s| s.to_owned());
1829 let fixed = self.attr(attrs, "fixed").map(|s| s.to_owned());
1830 if default.is_some() && fixed.is_some() {
1831 return Err(self.err(
1832 "<xs:element> may have either default= or fixed=, not both",
1833 ));
1834 }
1835 if let Some(v) = default.as_deref().or(fixed.as_deref()) {
1843 match &type_def {
1844 TypeRef::Simple(st) => {
1845 if matches!(st.builtin, super::types::BuiltinType::Id) {
1851 return Err(self.err(format!(
1852 "<xs:element name={name:?}> of type xs:ID (or derived) cannot have a default or fixed value",
1853 )));
1854 }
1855 if let Err(e) = st.validate(v) {
1856 return Err(self.err(format!(
1857 "<xs:element name={name:?}> default/fixed value {v:?} is not valid for its type: {}",
1858 e.message,
1859 )));
1860 }
1861 }
1862 TypeRef::Complex(ct) => {
1863 let allowed = match &ct.content {
1868 crate::xsd::schema::ContentModel::Simple(_) => true,
1869 crate::xsd::schema::ContentModel::Complex { mixed, .. } => *mixed,
1870 crate::xsd::schema::ContentModel::Empty => false,
1871 };
1872 if !allowed {
1873 return Err(self.err(format!(
1874 "<xs:element name={name:?}> with element-only or empty content cannot \
1875 have a default or fixed value (XSD §3.3.6)",
1876 )));
1877 }
1878 }
1879 }
1880 }
1881 let abstract_ = self.parse_xsd_bool(attrs, "abstract")?.unwrap_or(false);
1882 let substitution_group = match self.attr(attrs, "substitutionGroup") {
1883 Some(s) => Some(self.parse_qname(s, false)?),
1884 None => None,
1885 };
1886
1887 let decl = Arc::new(ElementDecl {
1888 name: qn.clone(),
1889 type_def,
1890 nillable,
1891 default,
1892 fixed,
1893 abstract_,
1894 substitution_group,
1895 block: match self.attr(attrs, "block") {
1900 Some(_) => parse_element_block_set(self.attr(attrs, "block"))?,
1901 None => self.block_default
1902 & (BlockSet::RESTRICTION
1903 | BlockSet::EXTENSION
1904 | BlockSet::SUBSTITUTION),
1905 },
1906 final_: match self.attr(attrs, "final") {
1910 Some(_) => parse_ct_derivation_set(self.attr(attrs, "final"), "final")?,
1911 None => self.final_default
1912 & (BlockSet::RESTRICTION | BlockSet::EXTENSION),
1913 },
1914 identity,
1915 });
1916 if !self.local_top_element_names.insert(qn.clone()) {
1921 return Err(self.err(format!(
1922 "duplicate top-level <xs:element name={:?}> in this schema document",
1923 qn.local,
1924 )));
1925 }
1926 self.builder.elements.insert(qn, decl);
1927 Ok(())
1928 }
1929
1930 fn parse_inline_type(
1935 &mut self,
1936 _attrs: &[Attr<'a>],
1937 ) -> Result<(Option<TypeRef>, Vec<super::identity::IdentityConstraint>), SchemaCompileError> {
1938 let mut found_type: Option<TypeRef> = None;
1939 let mut constraints: Vec<super::identity::IdentityConstraint> = Vec::new();
1940 let mut seen_anno = false;
1941 let mut seen_other = false;
1942 loop {
1943 match self.next_event()? {
1944 EventInto::StartElement { name } => {
1945 let child_attrs = self.take_attrs()?;
1946 self.push_ns_scope(&child_attrs);
1947 let qn = self.qname_of_element(&name)?;
1948 let is_xs = qn.namespace.as_deref() == Some(XS);
1949 if is_xs {
1950 self.check_annotation_pos(
1951 &qn.local, &mut seen_anno, &mut seen_other, "element",
1952 )?;
1953 }
1954 match (is_xs, qn.local.as_ref()) {
1955 (true, "simpleType") => {
1956 let st = self.parse_simple_type_body(&child_attrs)?;
1957 found_type = Some(TypeRef::Simple(Arc::new(st)));
1958 }
1959 (true, "complexType") => {
1960 let ct = self.parse_complex_type_body(&child_attrs)?;
1961 found_type = Some(TypeRef::Complex(Arc::new(ct)));
1962 }
1963 (true, "annotation") => self.parse_annotation_body(&child_attrs)?,
1964 (true, kind @ ("key" | "keyref" | "unique")) => {
1965 constraints.push(self.parse_identity_constraint(&child_attrs, kind)?);
1966 }
1967 (true, other) => return Err(self.err(format!(
1968 "<xs:{other}> is not allowed as a child of <xs:element>"
1969 ))),
1970 _ => self.skip_body()?,
1971 }
1972 self.pop_ns_scope();
1973 }
1974 EventInto::EndElement { .. } => return Ok((found_type, constraints)),
1975 EventInto::Eof => return Err(self.err("unexpected EOF in element body")),
1976 _ => {}
1977 }
1978 }
1979 }
1980
1981 fn parse_identity_constraint(
1985 &mut self,
1986 attrs: &[Attr<'a>],
1987 kind_str: &str,
1988 ) -> Result<super::identity::IdentityConstraint, SchemaCompileError> {
1989 use super::identity::ConstraintKind;
1990 let kind = match kind_str {
1991 "key" => ConstraintKind::Key,
1992 "unique" => ConstraintKind::Unique,
1993 "keyref" => ConstraintKind::KeyRef,
1994 _ => unreachable!(),
1995 };
1996 let name_str = self.attr(attrs, "name").ok_or_else(||
1997 self.err(format!("<xs:{kind_str}> missing name"))
1998 )?.to_owned();
1999 let name = QName {
2000 namespace: self.current_target_ns.clone(),
2001 local: Arc::from(name_str.as_str()),
2002 };
2003 if !self.seen_ic_names.insert(name.clone()) {
2004 return Err(self.err(format!(
2005 "duplicate identity-constraint name {name_str:?} \
2006 (unique/key/keyref share one namespace, XSD §3.11.1)"
2007 )));
2008 }
2009 let refer = if kind == ConstraintKind::KeyRef {
2010 let r = self.attr(attrs, "refer").ok_or_else(||
2011 self.err("<xs:keyref> missing refer attribute")
2012 )?;
2013 Some(self.parse_qname(r, false)?)
2014 } else {
2015 if self.attr(attrs, "refer").is_some() {
2016 return Err(self.err(format!(
2017 "<xs:{kind_str} refer=...> is only valid on <xs:keyref>"
2018 )));
2019 }
2020 None
2021 };
2022
2023 let prefix_lookup: Vec<(String, String)> = self.ns_stack.iter()
2027 .flat_map(|m| m.iter().map(|(k, v)| (k.clone(), v.clone())))
2028 .collect();
2029 let resolve_prefix = |p: &str| -> Option<String> {
2030 for (k, v) in prefix_lookup.iter().rev() {
2031 if k == p { return Some(v.clone()); }
2032 }
2033 None
2034 };
2035
2036 let mut selector_xpath: Option<String> = None;
2038 let mut field_xpaths: Vec<String> = Vec::new();
2039 let mut seen_anno = false;
2040 let mut seen_other = false;
2041 loop {
2042 match self.next_event()? {
2043 EventInto::StartElement { name: child } => {
2044 let cattrs = self.take_attrs()?;
2045 self.push_ns_scope(&cattrs);
2046 let qn = self.qname_of_element(&child)?;
2047 if qn.namespace.as_deref() == Some(XS) {
2048 self.check_annotation_pos(
2049 &qn.local, &mut seen_anno, &mut seen_other, kind_str,
2050 )?;
2051 match qn.local.as_ref() {
2052 "selector" => {
2053 if selector_xpath.is_some() {
2054 return Err(self.err(format!(
2055 "<xs:{kind_str}> may have at most one <xs:selector>"
2056 )));
2057 }
2058 if !field_xpaths.is_empty() {
2059 return Err(self.err(format!(
2060 "<xs:{kind_str}> body: <xs:selector> must precede <xs:field>"
2061 )));
2062 }
2063 if self.attr(&cattrs, "name").is_some() {
2064 return Err(self.err(
2065 "<xs:selector> does not take a 'name' attribute",
2066 ));
2067 }
2068 let xp = self.attr(&cattrs, "xpath").ok_or_else(||
2069 self.err("<xs:selector> missing xpath")
2070 )?.to_owned();
2071 selector_xpath = Some(xp);
2072 self.parse_anno_only_body("selector")?;
2073 self.pop_ns_scope();
2074 continue;
2075 }
2076 "field" => {
2077 if self.attr(&cattrs, "name").is_some() {
2078 return Err(self.err(
2079 "<xs:field> does not take a 'name' attribute",
2080 ));
2081 }
2082 let xp = self.attr(&cattrs, "xpath").ok_or_else(||
2083 self.err("<xs:field> missing xpath")
2084 )?.to_owned();
2085 field_xpaths.push(xp);
2086 self.parse_anno_only_body("field")?;
2087 self.pop_ns_scope();
2088 continue;
2089 }
2090 "annotation" => {}
2091 other => return Err(self.err(format!(
2092 "<xs:{other}> is not allowed as a child of <xs:{kind_str}>"
2093 ))),
2094 }
2095 }
2096 self.skip_body()?;
2097 self.pop_ns_scope();
2098 }
2099 EventInto::EndElement { .. } => break,
2100 EventInto::Eof => return Err(self.err(format!(
2101 "unexpected EOF in <xs:{kind_str}>"
2102 ))),
2103 _ => {}
2104 }
2105 }
2106
2107 let selector_xpath = selector_xpath.ok_or_else(||
2108 self.err(format!("<xs:{kind_str} name={:?}> has no <xs:selector>", name.local))
2109 )?;
2110 if field_xpaths.is_empty() {
2111 return Err(self.err(format!(
2112 "<xs:{kind_str} name={:?}> has no <xs:field>", name.local
2113 )));
2114 }
2115
2116 let selector = super::identity::parse_selector(&selector_xpath, &resolve_prefix)
2117 .map_err(|e| self.err(format!("<xs:selector xpath={selector_xpath:?}>: {e}")))?;
2118 let fields: Vec<_> = field_xpaths.iter()
2119 .map(|fp| super::identity::parse_field(fp, &resolve_prefix)
2120 .map_err(|e| self.err(format!("<xs:field xpath={fp:?}>: {e}"))))
2121 .collect::<Result<_, _>>()?;
2122
2123 Ok(super::identity::IdentityConstraint {
2124 name, kind, selector, fields, refer,
2125 })
2126 }
2127
2128 fn parse_top_attribute(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
2131 self.check_known_attrs(attrs, &[
2133 "id", "name", "type", "default", "fixed",
2134 ], "attribute")?;
2135 let name = self.attr(attrs, "name").ok_or_else(||
2136 self.err("<xs:attribute> missing name attribute")
2137 )?.to_owned();
2138 if name == "xmlns" {
2142 return Err(self.err(
2143 "<xs:attribute name=\"xmlns\"> is reserved by the Namespaces in XML spec",
2144 ));
2145 }
2146 if self.attr(attrs, "form").is_some() {
2149 return Err(self.err(
2150 "<xs:attribute form=...> is only valid on local attribute declarations"
2151 ));
2152 }
2153 if self.attr(attrs, "use").is_some() {
2154 return Err(self.err(
2155 "<xs:attribute use=...> is only valid on local attribute declarations"
2156 ));
2157 }
2158 if self.attr(attrs, "ref").is_some() {
2159 return Err(self.err(
2160 "<xs:attribute ref=...> is only valid on local attribute declarations"
2161 ));
2162 }
2163 if self.attr(attrs, "default").is_some() && self.attr(attrs, "fixed").is_some() {
2165 return Err(self.err(
2166 "<xs:attribute> may have either default= or fixed=, not both"
2167 ));
2168 }
2169 let qn = QName {
2170 namespace: self.current_target_ns.clone(),
2171 local: Arc::from(name.as_str()),
2172 };
2173 check_xsi_attribute_name(&qn).map_err(|m| self.err(m))?;
2174
2175 let inline_type = self.parse_inline_simple_type(attrs)?;
2177 if self.attr(attrs, "type").is_some() && inline_type.is_some() {
2178 return Err(self.err(
2179 "<xs:attribute> may have either type= or an inline <xs:simpleType>, not both"
2180 ));
2181 }
2182 let st = match self.attr(attrs, "type") {
2183 Some(t) => {
2184 let type_qn = self.parse_qname(t, false)?;
2185 self.simple_type_for(type_qn)
2186 }
2187 None => match inline_type {
2188 Some(t) => Arc::new(t),
2189 None => Arc::new(SimpleType::of_builtin(BuiltinType::String)),
2190 },
2191 };
2192
2193 let decl = Arc::new(AttributeDecl {
2194 name: qn.clone(),
2195 type_def: st,
2196 default: self.attr(attrs, "default").map(|s| s.to_owned()),
2197 fixed: self.attr(attrs, "fixed").map(|s| s.to_owned()),
2198 inheritable: self.parse_inheritable(attrs)?,
2199 });
2200 if self.builder.attributes.contains_key(&qn) {
2201 return Err(self.err(format!(
2202 "duplicate top-level <xs:attribute name={:?}> in target namespace",
2203 qn.local,
2204 )));
2205 }
2206 self.builder.attributes.insert(qn, decl);
2207 Ok(())
2208 }
2209
2210 fn parse_inline_simple_type(&mut self, _attrs: &[Attr<'a>])
2217 -> Result<Option<SimpleType>, SchemaCompileError>
2218 {
2219 let mut found: Option<SimpleType> = None;
2220 let mut seen_anno = false;
2221 let mut seen_other = false;
2222 loop {
2223 match self.next_event()? {
2224 EventInto::StartElement { name } => {
2225 let child_attrs = self.take_attrs()?;
2226 self.push_ns_scope(&child_attrs);
2227 let qn = self.qname_of_element(&name)?;
2228 if qn.namespace.as_deref() == Some(XS) {
2229 self.check_annotation_pos(
2230 &qn.local, &mut seen_anno, &mut seen_other, "attribute",
2231 )?;
2232 match qn.local.as_ref() {
2233 "simpleType" => {
2234 if found.is_some() {
2235 return Err(self.err(
2236 "<xs:attribute> may have at most one inline <xs:simpleType>",
2237 ));
2238 }
2239 found = Some(self.parse_simple_type_body(&child_attrs)?);
2240 }
2241 "annotation" => self.parse_annotation_body(&child_attrs)?,
2242 other => return Err(self.err(format!(
2243 "<xs:{other}> is not allowed as a child of <xs:attribute>"
2244 ))),
2245 }
2246 } else {
2247 self.skip_body()?;
2248 }
2249 self.pop_ns_scope();
2250 }
2251 EventInto::EndElement { .. } => return Ok(found),
2252 EventInto::Eof => return Err(self.err("unexpected EOF")),
2253 _ => {}
2254 }
2255 }
2256 }
2257
2258 fn parse_top_simple_type(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
2261 if self.attr(attrs, "name").is_none() {
2263 return Err(self.err(
2264 "top-level <xs:simpleType> requires a 'name' attribute",
2265 ));
2266 }
2267 let prev_in_flight = self.simple_type_in_flight.take();
2272 let name_qn = self.attr(attrs, "name").map(|n| QName {
2273 namespace: self.current_target_ns.clone(),
2274 local: Arc::from(n),
2275 });
2276 self.simple_type_in_flight = name_qn.clone();
2277 let st = self.parse_simple_type_body_inner(attrs, true);
2278 self.simple_type_in_flight = prev_in_flight;
2279 let st = st?;
2280 if let Some(name) = &st.name {
2281 let qn = QName {
2282 namespace: self.current_target_ns.clone(),
2283 local: name.clone(),
2284 };
2285 if !self.in_redefine && self.builder.types.contains_key(&qn) {
2286 return Err(self.err(format!(
2287 "duplicate top-level type definition {:?} \
2288 (a type with this name is already declared)",
2289 qn.local,
2290 )));
2291 }
2292 self.builder.types.insert(qn, TypeRef::Simple(Arc::new(st)));
2293 }
2294 Ok(())
2295 }
2296
2297 fn parse_simple_type_body(&mut self, attrs: &[Attr<'a>])
2303 -> Result<SimpleType, SchemaCompileError>
2304 {
2305 self.parse_simple_type_body_inner(attrs, false)
2306 }
2307
2308 fn parse_simple_type_body_inner(&mut self, attrs: &[Attr<'a>], allow_name: bool)
2312 -> Result<SimpleType, SchemaCompileError>
2313 {
2314 if !allow_name && self.attr(attrs, "name").is_some() {
2315 return Err(self.err(
2316 "inline <xs:simpleType> must not have a 'name' attribute (XSD §3.14.2)",
2317 ));
2318 }
2319 let name: Option<Arc<str>> = self.attr(attrs, "name").map(Arc::from);
2320
2321 let final_ = match self.attr(attrs, "final") {
2327 Some(_) => parse_block_set(self.attr(attrs, "final"))?,
2328 None => self.final_default,
2329 };
2330
2331 let mut builtin = BuiltinType::String;
2332 let mut facets = FacetSet::default();
2333 let mut whitespace = WhitespaceMode::Preserve;
2334 let mut variety: super::types::Variety = super::types::Variety::Atomic;
2335 let mut assertions: Vec<super::schema::Assertion> = Vec::new();
2336 let mut seen_anno = false;
2337 let mut seen_other = false;
2338 let mut saw_derivation = false;
2339
2340 loop {
2341 match self.next_event()? {
2342 EventInto::StartElement { name: child_name } => {
2343 let child_attrs = self.take_attrs()?;
2344 self.push_ns_scope(&child_attrs);
2345 let qn = self.qname_of_element(&child_name)?;
2346 if qn.namespace.as_deref() == Some(XS) {
2347 self.check_annotation_pos(
2348 &qn.local, &mut seen_anno, &mut seen_other, "simpleType",
2349 )?;
2350 let local = qn.local.as_ref();
2351 if matches!(local, "restriction" | "list" | "union")
2352 && saw_derivation
2353 {
2354 return Err(self.err(
2355 "<xs:simpleType> must have exactly one of \
2356 <xs:restriction>, <xs:list>, or <xs:union>",
2357 ));
2358 }
2359 match local {
2360 "restriction" => {
2361 saw_derivation = true;
2362 let (b, f, ws, v, a) = self.parse_simple_restriction(&child_attrs)?;
2363 builtin = b; facets = f; whitespace = ws; variety = v;
2364 assertions = a;
2365 }
2366 "list" => {
2367 saw_derivation = true;
2368 variety = super::types::Variety::List {
2369 item_type: self.parse_list_body(&child_attrs)?,
2370 };
2371 builtin = BuiltinType::String;
2376 whitespace = WhitespaceMode::Collapse;
2377 }
2378 "union" => {
2379 saw_derivation = true;
2380 variety = super::types::Variety::Union {
2381 members: self.parse_union_body(&child_attrs)?,
2382 };
2383 builtin = BuiltinType::String;
2384 whitespace = WhitespaceMode::Collapse;
2385 }
2386 "annotation" => self.parse_annotation_body(&child_attrs)?,
2387 other => return Err(self.err(format!(
2388 "<xs:{other}> is not allowed as a child of <xs:simpleType>"
2389 ))),
2390 }
2391 } else {
2392 self.skip_body()?;
2393 }
2394 self.pop_ns_scope();
2395 }
2396 EventInto::EndElement { .. } => break,
2397 EventInto::Eof => return Err(self.err("unexpected EOF in simpleType")),
2398 _ => {}
2399 }
2400 }
2401 if !saw_derivation {
2402 return Err(self.err(
2403 "<xs:simpleType> requires one of <xs:restriction>, <xs:list>, or <xs:union>",
2404 ));
2405 }
2406
2407 Ok(SimpleType {
2408 name, builtin, facets, whitespace, variety, final_,
2409 assertions,
2410 })
2411 }
2412
2413 fn parse_list_body(&mut self, attrs: &[Attr<'a>])
2417 -> Result<Arc<SimpleType>, SchemaCompileError>
2418 {
2419 let item_type_attr = self.attr(attrs, "itemType").map(|s| s.to_string());
2423 let mut nested: Option<SimpleType> = None;
2424 let mut seen_anno = false;
2425 let mut seen_other = false;
2426 loop {
2427 match self.next_event()? {
2428 EventInto::StartElement { name: child_name } => {
2429 let child_attrs = self.take_attrs()?;
2430 self.push_ns_scope(&child_attrs);
2431 let qn = self.qname_of_element(&child_name)?;
2432 if qn.namespace.as_deref() == Some(XS) {
2433 self.check_annotation_pos(
2434 &qn.local, &mut seen_anno, &mut seen_other, "list",
2435 )?;
2436 match qn.local.as_ref() {
2437 "simpleType" => {
2438 if nested.is_some() {
2439 return Err(self.err(
2440 "<xs:list> may have at most one inline <xs:simpleType>",
2441 ));
2442 }
2443 if item_type_attr.is_some() {
2444 return Err(self.err(
2445 "<xs:list> cannot have both itemType= and an inline <xs:simpleType>",
2446 ));
2447 }
2448 nested = Some(self.parse_simple_type_body(&child_attrs)?);
2449 }
2450 "annotation" => self.parse_annotation_body(&child_attrs)?,
2451 other => return Err(self.err(format!(
2452 "<xs:{other}> is not allowed as a child of <xs:list>"
2453 ))),
2454 }
2455 } else {
2456 self.skip_body()?;
2457 }
2458 self.pop_ns_scope();
2459 }
2460 EventInto::EndElement { .. } => break,
2461 EventInto::Eof => return Err(self.err("unexpected EOF in <xs:list>")),
2462 _ => {}
2463 }
2464 }
2465 if let Some(t) = nested {
2466 return Ok(Arc::new(t));
2467 }
2468 let item = item_type_attr.ok_or_else(||
2469 self.err("<xs:list> needs itemType= or a nested <xs:simpleType>"))?;
2470 let qn = self.parse_qname(&item, false)?;
2471 if let Some(TypeRef::Simple(st)) = self.builder.types.get(&qn) {
2475 if matches!(st.variety, super::types::Variety::List { .. }) {
2476 return Err(self.err(format!(
2477 "<xs:list itemType={item:?}>: itemType must be atomic or union, not a list"
2478 )));
2479 }
2480 if st.final_.contains(super::schema::BlockSet::LIST) {
2481 return Err(self.err(format!(
2482 "<xs:list itemType={item:?}>: base simple type's `final` disallows list derivation"
2483 )));
2484 }
2485 }
2486 if let Some(TypeRef::Complex(_)) = self.builder.types.get(&qn) {
2487 return Err(self.err(format!(
2488 "<xs:list itemType={item:?}>: itemType must be a simple type"
2489 )));
2490 }
2491 Ok(self.simple_type_for(qn))
2492 }
2493
2494 fn parse_union_body(&mut self, attrs: &[Attr<'a>])
2499 -> Result<Vec<Arc<SimpleType>>, SchemaCompileError>
2500 {
2501 let mut members: Vec<Arc<SimpleType>> = Vec::new();
2502 if let Some(list) = self.attr(attrs, "memberTypes") {
2503 for token in list.split_whitespace() {
2504 let qn = self.parse_qname(token, false)?;
2505 if let Some(TypeRef::Complex(_)) = self.builder.types.get(&qn) {
2507 return Err(self.err(format!(
2508 "<xs:union memberTypes={list:?}>: {token:?} is not a simple type"
2509 )));
2510 }
2511 if let Some(TypeRef::Simple(st)) = self.builder.types.get(&qn) {
2512 if st.final_.contains(super::schema::BlockSet::UNION) {
2513 return Err(self.err(format!(
2514 "<xs:union memberTypes={list:?}>: {token:?}'s `final` \
2515 disallows union derivation"
2516 )));
2517 }
2518 }
2519 if qn.namespace.as_deref() == Some(XS)
2520 && qn.local.as_ref() != "anySimpleType"
2521 && BuiltinType::from_name(&qn.local).is_none()
2522 {
2523 return Err(self.err(format!(
2524 "<xs:union memberTypes={list:?}>: {token:?} is not a built-in XSD type"
2525 )));
2526 }
2527 members.push(self.simple_type_for(qn));
2528 }
2529 }
2530 let mut seen_anno = false;
2532 let mut seen_other = false;
2533 loop {
2534 match self.next_event()? {
2535 EventInto::StartElement { name: child_name } => {
2536 let child_attrs = self.take_attrs()?;
2537 self.push_ns_scope(&child_attrs);
2538 let qn = self.qname_of_element(&child_name)?;
2539 if qn.namespace.as_deref() == Some(XS) {
2540 self.check_annotation_pos(
2541 &qn.local, &mut seen_anno, &mut seen_other, "union",
2542 )?;
2543 match qn.local.as_ref() {
2544 "simpleType" => {
2545 let st = self.parse_simple_type_body(&child_attrs)?;
2546 members.push(Arc::new(st));
2547 }
2548 "annotation" => self.parse_annotation_body(&child_attrs)?,
2549 other => return Err(self.err(format!(
2550 "<xs:{other}> is not allowed as a child of <xs:union>"
2551 ))),
2552 }
2553 } else {
2554 self.skip_body()?;
2555 }
2556 self.pop_ns_scope();
2557 }
2558 EventInto::EndElement { .. } => break,
2559 EventInto::Eof => return Err(self.err("unexpected EOF in <xs:union>")),
2560 _ => {}
2561 }
2562 }
2563 if members.is_empty() {
2564 return Err(self.err(
2565 "<xs:union> needs memberTypes= or at least one nested <xs:simpleType>"
2566 ));
2567 }
2568 Ok(members)
2569 }
2570
2571 fn parse_simple_restriction(&mut self, attrs: &[Attr<'a>])
2574 -> Result<(BuiltinType, FacetSet, WhitespaceMode, super::types::Variety,
2575 Vec<super::schema::Assertion>), SchemaCompileError>
2576 {
2577 let mut base_builtin = BuiltinType::String;
2605 let mut whitespace = WhitespaceMode::Preserve;
2606 let mut facets = FacetSet::default();
2607 let mut variety: super::types::Variety = super::types::Variety::Atomic;
2608 let mut inherited = false;
2609 let mut has_named_base = false;
2610 let mut pending_forward_base: Option<QName> = None;
2611 let mut assertions: Vec<super::schema::Assertion> = Vec::new();
2616 if let Some(base_qn) = self.attr(attrs, "base") {
2617 has_named_base = true;
2618 let qn = self.parse_qname(base_qn, false)?;
2619 if !self.in_redefine
2624 && self.simple_type_in_flight.as_ref() == Some(&qn)
2625 {
2626 return Err(self.err(format!(
2627 "<xs:simpleType name={:?}><xs:restriction base={:?}>: \
2628 a simple type cannot restrict itself (circular definition)",
2629 qn.local, qn.local,
2630 )));
2631 }
2632 self.last_simple_restriction_base = Some(qn.clone());
2635 if qn.namespace.as_deref() == Some(XS) {
2636 if qn.local.as_ref() == "anyType" {
2642 return Err(self.err(
2643 "<xs:restriction base=\"xs:anyType\"> is not allowed in a simpleType",
2644 ));
2645 }
2646 if qn.local.as_ref() == "anySimpleType" {
2647 return Err(self.err(
2648 "<xs:restriction base=\"xs:anySimpleType\">: anySimpleType is \
2649 the ultimate ancestor of all simple types and cannot itself \
2650 be restricted (XSD §3.16.7)",
2651 ));
2652 }
2653 match BuiltinType::from_name(&qn.local) {
2654 Some(b) => {
2655 if b.is_xsd11_only()
2660 && !matches!(self.builder.effective_version, SchemaVersion::Xsd11)
2661 {
2662 return Err(self.err(format!(
2663 "xs:{} is an XSD 1.1 built-in — set \
2664 SchemaOptions::version to Xsd11, or to Auto with \
2665 vc:minVersion=\"1.1\" on <xs:schema>",
2666 qn.local,
2667 )));
2668 }
2669 base_builtin = b;
2670 }
2671 None => return Err(self.err(format!(
2672 "<xs:restriction base={base_qn:?}>: {base_qn:?} is not a built-in XSD type"
2673 ))),
2674 }
2675 } else if let Some(TypeRef::Complex(_)) = self.builder.types.get(&qn) {
2676 return Err(self.err(format!(
2677 "<xs:restriction base={base_qn:?}> in a simpleType must reference a simpleType, not a complexType"
2678 )));
2679 } else if let Some(TypeRef::Simple(st)) = self.builder.types.get(&qn) {
2680 if st.final_.contains(super::schema::BlockSet::RESTRICTION) {
2681 return Err(self.err(format!(
2682 "<xs:restriction base={base_qn:?}>: base simple type's \
2683 `final` disallows restriction"
2684 )));
2685 }
2686 base_builtin = st.builtin;
2687 facets = st.facets.clone();
2688 whitespace = st.whitespace;
2689 variety = st.variety.clone();
2690 inherited = true;
2691 } else if qn.namespace.as_deref() != self.current_target_ns.as_deref()
2692 && !import_covers(&self.builder.imported_namespaces,
2693 qn.namespace.as_deref())
2694 {
2695 return Err(self.err(format!(
2702 "<xs:restriction base={base_qn:?}>: namespace {:?} is not the \
2703 schema's targetNamespace and was not brought in by <xs:import>",
2704 qn.namespace.as_deref().unwrap_or(""),
2705 )));
2706 } else {
2707 pending_forward_base = Some(qn.clone());
2714 }
2715 }
2716 if !inherited {
2717 whitespace = base_builtin.default_whitespace();
2718 }
2719 let mut base_facet_count = facets.facets.len();
2720
2721 loop {
2722 match self.next_event()? {
2723 EventInto::StartElement { name } => {
2724 let f_attrs = self.take_attrs()?;
2725 self.push_ns_scope(&f_attrs);
2726 let fqn = self.qname_of_element(&name)?;
2727 if fqn.namespace.as_deref() == Some(XS) {
2728 let v = self.attr(&f_attrs, "value");
2729 match (fqn.local.as_ref(), v) {
2730 ("length", Some(v)) => facets.push(Facet::Length(v.parse().map_err(|e|
2731 self.err(format!("length facet: {e}"))
2732 )?)),
2733 ("minLength", Some(v)) => facets.push(Facet::MinLength(v.parse().map_err(|e|
2734 self.err(format!("minLength facet: {e}"))
2735 )?)),
2736 ("maxLength", Some(v)) => facets.push(Facet::MaxLength(v.parse().map_err(|e|
2737 self.err(format!("maxLength facet: {e}"))
2738 )?)),
2739 ("pattern", Some(v)) => {
2740 let p = super::regex::Pattern::compile(v).map_err(|e|
2741 self.err(format!("pattern facet: {e}"))
2742 )?;
2743 facets.push(Facet::Pattern(p));
2744 }
2745 ("enumeration", Some(v)) => {
2746 super::types::SimpleType::of_builtin(base_builtin)
2750 .validate(v)
2751 .map_err(|e| self.err(format!(
2752 "enumeration value {v:?} not in base type's value space: {}",
2753 e.message,
2754 )))?;
2755 if let Some(Facet::Enumeration(opts)) = facets.facets.last_mut() {
2757 opts.push(v.to_owned());
2758 } else {
2759 facets.push(Facet::Enumeration(vec![v.to_owned()]));
2760 }
2761 }
2762 ("whiteSpace", Some(v)) => {
2763 let new_ws = match v {
2764 "preserve" => WhitespaceMode::Preserve,
2765 "replace" => WhitespaceMode::Replace,
2766 "collapse" => WhitespaceMode::Collapse,
2767 other => return Err(self.err(format!(
2768 "invalid whiteSpace value: {other:?}"
2769 ))),
2770 };
2771 let base_ws = whitespace;
2780 let allowed = matches!(
2781 (base_ws, new_ws),
2782 (WhitespaceMode::Preserve, _)
2783 | (WhitespaceMode::Replace, WhitespaceMode::Replace | WhitespaceMode::Collapse)
2784 | (WhitespaceMode::Collapse, WhitespaceMode::Collapse)
2785 );
2786 if !allowed {
2787 return Err(self.err(format!(
2788 "whiteSpace={v:?} is not a valid restriction of the base whitespace mode"
2789 )));
2790 }
2791 whitespace = new_ws;
2792 }
2793 ("minInclusive", Some(v)) => {
2794 self.validate_bound_against_base(v, base_builtin, "minInclusive")?;
2795 facets.push(Facet::MinInclusive(parse_bound(v, base_builtin)?));
2796 }
2797 ("maxInclusive", Some(v)) => {
2798 self.validate_bound_against_base(v, base_builtin, "maxInclusive")?;
2799 facets.push(Facet::MaxInclusive(parse_bound(v, base_builtin)?));
2800 }
2801 ("minExclusive", Some(v)) => {
2802 self.validate_bound_against_base(v, base_builtin, "minExclusive")?;
2803 facets.push(Facet::MinExclusive(parse_bound(v, base_builtin)?));
2804 }
2805 ("maxExclusive", Some(v)) => {
2806 self.validate_bound_against_base(v, base_builtin, "maxExclusive")?;
2807 facets.push(Facet::MaxExclusive(parse_bound(v, base_builtin)?));
2808 }
2809 ("totalDigits", Some(v)) => {
2810 let n: u32 = v.parse().map_err(|e|
2811 self.err(format!("totalDigits: {e}"))
2812 )?;
2813 if n == 0 {
2814 return Err(self.err(
2815 "totalDigits value must be ≥ 1 (XSD §4.3.11)"
2816 ));
2817 }
2818 facets.push(Facet::TotalDigits(n));
2819 }
2820 ("fractionDigits", Some(v)) => {
2821 let n: u32 = v.parse().map_err(|e|
2822 self.err(format!("fractionDigits: {e}"))
2823 )?;
2824 if base_builtin.is_integer_family() && n != 0 {
2829 return Err(self.err(format!(
2830 "fractionDigits ({n}) cannot be nonzero on a derivation \
2831 of xs:integer (fixed at 0)"
2832 )));
2833 }
2834 facets.push(Facet::FractionDigits(n));
2835 }
2836 ("annotation", _) => {
2837 self.parse_annotation_body(&f_attrs)?;
2838 self.pop_ns_scope();
2839 continue;
2840 }
2841 ("explicitTimezone", Some(v)) => {
2842 if !matches!(self.builder.effective_version,
2846 SchemaVersion::Xsd11)
2847 {
2848 return Err(self.err(
2849 "<xs:explicitTimezone> is an XSD 1.1 facet — \
2850 set SchemaOptions::version to Xsd11, or to Auto \
2851 with vc:minVersion=\"1.1\" on <xs:schema>",
2852 ));
2853 }
2854 use super::facets::TimezoneRequirement as TR;
2855 let req = match v {
2856 "required" => TR::Required,
2857 "prohibited" => TR::Prohibited,
2858 "optional" => TR::Optional,
2859 other => return Err(self.err(format!(
2860 "<xs:explicitTimezone value={other:?}>: must be \
2861 \"required\", \"prohibited\", or \"optional\""
2862 ))),
2863 };
2864 facets.push(Facet::ExplicitTimezone(req));
2865 }
2866 ("length", None) | ("minLength", None) | ("maxLength", None)
2867 | ("pattern", None) | ("enumeration", None) | ("whiteSpace", None)
2868 | ("minInclusive", None) | ("maxInclusive", None)
2869 | ("minExclusive", None) | ("maxExclusive", None)
2870 | ("totalDigits", None) | ("fractionDigits", None)
2871 | ("explicitTimezone", None) => {
2872 return Err(self.err(format!(
2873 "<xs:{}> facet requires a 'value' attribute", fqn.local
2874 )));
2875 }
2876 ("simpleType", _) => {
2877 if has_named_base {
2884 return Err(self.err(
2885 "<xs:restriction> cannot combine base= with an inline <xs:simpleType>",
2886 ));
2887 }
2888 if inherited {
2889 return Err(self.err(
2890 "<xs:restriction> may have at most one inline <xs:simpleType>",
2891 ));
2892 }
2893 let inline_base = self.parse_simple_type_body(&f_attrs)?;
2894 base_builtin = inline_base.builtin;
2895 facets = inline_base.facets.clone();
2896 whitespace = inline_base.whitespace;
2897 variety = inline_base.variety.clone();
2898 inherited = true;
2899 base_facet_count = facets.facets.len();
2900 self.pop_ns_scope();
2901 continue;
2902 }
2903 ("assertion", _) => {
2904 assertions.extend(self.parse_assertion_body(&f_attrs)?);
2911 self.pop_ns_scope();
2912 continue;
2913 }
2914 (other, _) => {
2915 return Err(self.err(format!(
2916 "<xs:{other}> is not a valid facet or child of <xs:restriction> (simpleType)"
2917 )));
2918 }
2919 }
2920 }
2921 self.parse_anno_only_body(fqn.local.as_ref())?;
2924 self.pop_ns_scope();
2925 }
2926 EventInto::EndElement { .. } => break,
2927 EventInto::Eof => return Err(self.err("unexpected EOF in restriction")),
2928 _ => {}
2929 }
2930 }
2931 if !has_named_base && !inherited {
2932 return Err(self.err(
2933 "<xs:restriction> needs either a base= attribute or an inline <xs:simpleType>",
2934 ));
2935 }
2936 prune_replaced_bounds(&mut facets, base_facet_count);
2942 self.validate_facet_set(&facets)?;
2943 self.check_facet_tightening(&facets.facets[..base_facet_count], &facets.facets[base_facet_count..])?;
2948 self.check_facet_applicability(&facets.facets[base_facet_count..], &variety)?;
2953 if let Some(base_qn) = pending_forward_base {
2958 let derived = facets.facets[base_facet_count..].to_vec();
2959 if !derived.is_empty() {
2960 self.builder.pending_simple_facet_checks.push((base_qn, derived));
2961 }
2962 }
2963 Ok((base_builtin, facets, whitespace, variety, assertions))
2964 }
2965
2966 fn check_facet_applicability(
2967 &self,
2968 derived: &[Facet],
2969 variety: &super::types::Variety,
2970 ) -> Result<(), SchemaCompileError> {
2971 use super::types::Variety;
2972 for f in derived {
2973 let allowed = match (variety, f) {
2974 (Variety::List { .. }, Facet::Length(_) | Facet::MinLength(_) | Facet::MaxLength(_)
2975 | Facet::Pattern(_) | Facet::Enumeration(_)) => true,
2976 (Variety::Union { .. }, Facet::Pattern(_) | Facet::Enumeration(_)) => true,
2977 (Variety::Atomic, _) => true,
2978 _ => false,
2980 };
2981 if !allowed {
2982 let kind = match variety {
2983 Variety::List { .. } => "list",
2984 Variety::Union { .. } => "union",
2985 Variety::Atomic => "atomic",
2986 };
2987 let facet_name = match f {
2988 Facet::Length(_) => "length",
2989 Facet::MinLength(_) => "minLength",
2990 Facet::MaxLength(_) => "maxLength",
2991 Facet::Pattern(_) => "pattern",
2992 Facet::Enumeration(_) => "enumeration",
2993 Facet::MinInclusive(_) => "minInclusive",
2994 Facet::MaxInclusive(_) => "maxInclusive",
2995 Facet::MinExclusive(_) => "minExclusive",
2996 Facet::MaxExclusive(_) => "maxExclusive",
2997 Facet::TotalDigits(_) => "totalDigits",
2998 Facet::FractionDigits(_) => "fractionDigits",
2999 Facet::ExplicitTimezone(_) => "explicitTimezone",
3000 };
3001 return Err(self.err(format!(
3002 "facet <xs:{facet_name}> is not applicable to a {kind} simple type"
3003 )));
3004 }
3005 }
3006 Ok(())
3007 }
3008
3009 fn check_facet_tightening(
3012 &self, base: &[Facet], derived: &[Facet],
3013 ) -> Result<(), SchemaCompileError> {
3014 check_facet_tightening_pure(base, derived).map_err(|m| self.err(m))
3015 }
3016
3017 fn validate_facet_set(&self, facets: &FacetSet) -> Result<(), SchemaCompileError> {
3030 let mut length: Option<usize> = None;
3031 let mut min_length: Option<usize> = None;
3032 let mut max_length: Option<usize> = None;
3033 let mut min_inclusive: Option<&Bound> = None;
3034 let mut min_exclusive: Option<&Bound> = None;
3035 let mut max_inclusive: Option<&Bound> = None;
3036 let mut max_exclusive: Option<&Bound> = None;
3037 let mut total_digits: Option<u32> = None;
3038 let mut fraction_digits: Option<u32> = None;
3039 for f in &facets.facets {
3040 match f {
3041 Facet::Length(n) => length = Some(*n),
3042 Facet::MinLength(n) => min_length = Some(*n),
3043 Facet::MaxLength(n) => max_length = Some(*n),
3044 Facet::MinInclusive(b) => min_inclusive = Some(b),
3045 Facet::MinExclusive(b) => min_exclusive = Some(b),
3046 Facet::MaxInclusive(b) => max_inclusive = Some(b),
3047 Facet::MaxExclusive(b) => max_exclusive = Some(b),
3048 Facet::TotalDigits(n) => total_digits = Some(*n),
3049 Facet::FractionDigits(n) => fraction_digits = Some(*n),
3050 _ => {}
3051 }
3052 }
3053 if length.is_some() && (min_length.is_some() || max_length.is_some()) {
3054 return Err(self.err(
3055 "length facet cannot co-occur with minLength or maxLength (XSD §4.3.1)",
3056 ));
3057 }
3058 if let (Some(lo), Some(hi)) = (min_length, max_length) {
3059 if lo > hi {
3060 return Err(self.err(format!(
3061 "minLength ({lo}) > maxLength ({hi}) (XSD §4.3.2)"
3062 )));
3063 }
3064 }
3065 if min_inclusive.is_some() && min_exclusive.is_some() {
3066 return Err(self.err(
3067 "minInclusive and minExclusive are mutually exclusive (XSD §4.3.9)",
3068 ));
3069 }
3070 if max_inclusive.is_some() && max_exclusive.is_some() {
3071 return Err(self.err(
3072 "maxInclusive and maxExclusive are mutually exclusive (XSD §4.3.7)",
3073 ));
3074 }
3075 for (lo, hi, lo_name, hi_name) in [
3076 (min_inclusive, max_inclusive, "minInclusive", "maxInclusive"),
3077 (min_inclusive, max_exclusive, "minInclusive", "maxExclusive"),
3078 (min_exclusive, max_inclusive, "minExclusive", "maxInclusive"),
3079 (min_exclusive, max_exclusive, "minExclusive", "maxExclusive"),
3080 ] {
3081 if let (Some(lo), Some(hi)) = (lo, hi) {
3082 if compare_bounds(lo, hi).map(|o| o.is_gt()).unwrap_or(false) {
3083 return Err(self.err(format!(
3084 "{lo_name} > {hi_name} (XSD §4.3.x)"
3085 )));
3086 }
3087 }
3088 }
3089 if let (Some(fd), Some(td)) = (fraction_digits, total_digits) {
3090 if fd > td {
3091 return Err(self.err(format!(
3092 "fractionDigits ({fd}) > totalDigits ({td}) (XSD §4.3.12)"
3093 )));
3094 }
3095 }
3096 Ok(())
3097 }
3098
3099 fn validate_bound_against_base(
3100 &self, raw: &str, builtin: BuiltinType, facet: &str,
3101 ) -> Result<(), SchemaCompileError> {
3102 super::types::SimpleType::of_builtin(builtin)
3103 .validate(raw)
3104 .map_err(|e| self.err(format!(
3105 "{facet} value {raw:?} not in base type's value space: {}",
3106 e.message,
3107 )))?;
3108 Ok(())
3109 }
3110
3111 fn parse_top_complex_type(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
3114 if self.attr(attrs, "name").is_none() {
3116 return Err(self.err(
3117 "top-level <xs:complexType> requires a 'name' attribute",
3118 ));
3119 }
3120 let ct = self.parse_complex_type_body_inner(attrs, true)?;
3121 if let Some(name) = &ct.name {
3122 if !self.in_redefine && self.builder.types.contains_key(name) {
3127 return Err(self.err(format!(
3128 "duplicate top-level type definition {:?} \
3129 (a type with this name is already declared)",
3130 name.local,
3131 )));
3132 }
3133 self.builder.types.insert(name.clone(), TypeRef::Complex(Arc::new(ct)));
3134 }
3135 Ok(())
3136 }
3137
3138 fn parse_complex_type_body(&mut self, attrs: &[Attr<'a>])
3139 -> Result<ComplexType, SchemaCompileError>
3140 {
3141 self.parse_complex_type_body_inner(attrs, false)
3142 }
3143
3144 fn parse_complex_type_body_inner(&mut self, attrs: &[Attr<'a>], allow_name: bool)
3145 -> Result<ComplexType, SchemaCompileError>
3146 {
3147 if !allow_name && self.attr(attrs, "name").is_some() {
3148 return Err(self.err(
3149 "inline <xs:complexType> must not have a 'name' attribute (XSD §3.4.2)",
3150 ));
3151 }
3152 let name = self.attr(attrs, "name").map(|n| QName {
3153 namespace: self.current_target_ns.clone(),
3154 local: Arc::from(n),
3155 });
3156 let abstract_ = self.parse_xsd_bool(attrs, "abstract")?.unwrap_or(false);
3157 let mixed_attr = self.parse_xsd_bool(attrs, "mixed")?.unwrap_or(false);
3158 let ct_mask = BlockSet::RESTRICTION | BlockSet::EXTENSION;
3164 let block = match self.attr(attrs, "block") {
3165 Some(_) => parse_ct_derivation_set(self.attr(attrs, "block"), "block")?,
3166 None => self.block_default & ct_mask,
3167 };
3168 let final_ = match self.attr(attrs, "final") {
3169 Some(_) => parse_ct_derivation_set(self.attr(attrs, "final"), "final")?,
3170 None => self.final_default & ct_mask,
3171 };
3172
3173 let mut content = ContentModel::Empty;
3174 let mut attr_uses = Vec::new();
3175 let mut any_attr = None;
3176 let mut derivation: Option<Derivation> = None;
3177 let mut mixed = mixed_attr;
3178 let mut pending_ag_refs: Vec<QName> = Vec::new();
3179 let mut assertions: Vec<super::schema::Assertion> = Vec::new();
3180 let mut seen_anno = false;
3181 let mut seen_other = false;
3182 let mut saw_derived_content = false;
3193 let mut saw_model_group = false;
3194 let mut saw_any_attribute = false;
3195
3196 loop {
3197 match self.next_event()? {
3198 EventInto::StartElement { name: child } => {
3199 let child_attrs = self.take_attrs()?;
3200 self.push_ns_scope(&child_attrs);
3201 let qn = self.qname_of_element(&child)?;
3202 if qn.namespace.as_deref() == Some(XS) {
3203 self.check_annotation_pos(
3204 &qn.local, &mut seen_anno, &mut seen_other, "complexType",
3205 )?;
3206 let local = qn.local.as_ref();
3207 if saw_derived_content && local != "annotation" {
3208 return Err(self.err(format!(
3209 "<xs:complexType> with <xs:simpleContent>/<xs:complexContent> \
3210 cannot have <xs:{local}> as a sibling",
3211 )));
3212 }
3213 match local {
3214 "sequence" | "choice" | "all" => {
3215 if saw_model_group || saw_any_attribute
3216 || !attr_uses.is_empty()
3217 {
3218 return Err(self.err(
3219 "<xs:complexType> body: model group must precede \
3220 attribute / attributeGroup / anyAttribute, and \
3221 only one model group is allowed",
3222 ));
3223 }
3224 saw_model_group = true;
3225 let kind = match qn.local.as_ref() {
3226 "sequence" => GroupKind::Sequence,
3227 "choice" => GroupKind::Choice,
3228 _ => GroupKind::All,
3229 };
3230 let particle = self.parse_group_body(kind, &child_attrs)?;
3231 content = ContentModel::Complex { root: particle, mixed };
3232 }
3233 "group" => {
3234 if saw_model_group || saw_any_attribute
3235 || !attr_uses.is_empty()
3236 {
3237 return Err(self.err(
3238 "<xs:complexType> body: model group must precede \
3239 attribute / attributeGroup / anyAttribute, and \
3240 only one model group is allowed",
3241 ));
3242 }
3243 saw_model_group = true;
3244 let r = self.attr(&child_attrs, "ref").ok_or_else(|| self.err(
3252 "<xs:group> inside <xs:complexType> must use ref= \
3253 (nested group definitions are not allowed)",
3254 ))?;
3255 {
3256 let ref_qn = self.parse_qname(r, false)?;
3257 let g_min = parse_min_occurs(self.attr(&child_attrs, "minOccurs"))?;
3258 let g_max = parse_max_occurs(self.attr(&child_attrs, "maxOccurs"))?;
3259 check_occurs(g_min, g_max)?;
3260 content = ContentModel::Complex {
3261 root: Particle {
3262 min_occurs: g_min,
3263 max_occurs: g_max,
3264 term: Term::GroupRef(ref_qn),
3265 },
3266 mixed,
3267 };
3268 }
3269 self.skip_body()?;
3270 }
3271 "attribute" => {
3272 if saw_any_attribute {
3273 return Err(self.err(
3274 "<xs:attribute> cannot follow <xs:anyAttribute> in <xs:complexType>",
3275 ));
3276 }
3277 let au = self.parse_local_attribute_use(&child_attrs)?;
3278 attr_uses.push(au);
3279 }
3280 "attributeGroup" => {
3281 if saw_any_attribute {
3282 return Err(self.err(
3283 "<xs:attributeGroup> cannot follow <xs:anyAttribute> in <xs:complexType>",
3284 ));
3285 }
3286 let r = self.attr(&child_attrs, "ref").ok_or_else(|| self.err(
3287 "<xs:attributeGroup> inside <xs:complexType> must use ref= \
3288 (nested attributeGroup definitions are not allowed)",
3289 ))?;
3290 let qn = self.parse_qname(r, false)?;
3291 match self.builder.attr_groups.get(&qn) {
3292 Some(ag) => {
3293 for au in &ag.attributes {
3294 attr_uses.push(au.clone());
3295 }
3296 any_attr = merge_any_intersect(any_attr, ag.any.clone());
3300 }
3301 None => pending_ag_refs.push(qn),
3302 }
3303 self.parse_anno_only_body("attributeGroup")?;
3306 }
3307 "anyAttribute" => {
3308 if saw_any_attribute {
3309 return Err(self.err(
3310 "<xs:complexType> body: at most one <xs:anyAttribute>",
3311 ));
3312 }
3313 saw_any_attribute = true;
3314 check_no_occurs(&child_attrs, "anyAttribute")?;
3315 any_attr = Some(self.parse_wildcard(&child_attrs)?);
3316 self.parse_anno_only_body("anyAttribute")?;
3317 }
3318 "complexContent" | "simpleContent" => {
3319 if saw_model_group || saw_any_attribute
3320 || !attr_uses.is_empty()
3321 {
3322 return Err(self.err(format!(
3323 "<xs:{local}> cannot co-occur with model group, \
3324 attribute, attributeGroup, or anyAttribute in <xs:complexType>",
3325 )));
3326 }
3327 saw_derived_content = true;
3328 let (deriv, inner_content, inner_attrs, inner_any, inner_mixed, inner_pending) =
3329 self.parse_derived_content(&child_attrs, qn.local.as_ref() == "simpleContent")?;
3330 derivation = deriv;
3331 content = inner_content;
3332 attr_uses.extend(inner_attrs);
3333 if inner_any.is_some() { any_attr = inner_any; }
3334 mixed = inner_mixed.unwrap_or(mixed);
3335 if let ContentModel::Complex { mixed: ref mut m, .. } = content {
3342 *m = mixed;
3343 }
3344 pending_ag_refs.extend(inner_pending);
3345 }
3346 "annotation" => self.parse_annotation_body(&child_attrs)?,
3347 "assert" => assertions.extend(self.parse_assertion_body(&child_attrs)?),
3351 other => return Err(self.err(format!(
3352 "<xs:{other}> is not allowed as a child of <xs:complexType>"
3353 ))),
3354 }
3355 } else {
3356 self.skip_body()?;
3357 }
3358 self.pop_ns_scope();
3359 }
3360 EventInto::EndElement { .. } => break,
3361 EventInto::Eof => return Err(self.err("unexpected EOF in complexType")),
3362 _ => {}
3363 }
3364 }
3365 let mut seen_attr_names: HashSet<QName> = HashSet::new();
3370 for au in &attr_uses {
3371 if !seen_attr_names.insert(au.decl.name.clone()) {
3372 return Err(self.err(format!(
3373 "<xs:complexType{}> declares attribute {:?} more than once",
3374 name.as_ref().map(|n| format!(" name={:?}", n.local)).unwrap_or_default(),
3375 au.decl.name.local,
3376 )));
3377 }
3378 }
3379 let id_count = attr_uses.iter().filter(|au| {
3385 matches!(au.decl.type_def.builtin, BuiltinType::Id)
3386 }).count();
3387 if id_count > 1 {
3388 return Err(self.err(format!(
3389 "<xs:complexType{}> declares {id_count} attributes of type xs:ID; \
3390 at most one is allowed (XSD §3.4.6)",
3391 name.as_ref().map(|n| format!(" name={:?}", n.local)).unwrap_or_default(),
3392 )));
3393 }
3394
3395 let content = if mixed && matches!(content, ContentModel::Empty) {
3402 ContentModel::Complex {
3403 root: Particle {
3404 min_occurs: 1,
3405 max_occurs: MaxOccurs::Bounded(1),
3406 term: Term::Group {
3407 kind: GroupKind::Sequence,
3408 particles: Arc::from(Vec::<Particle>::new()),
3409 },
3410 },
3411 mixed: true,
3412 }
3413 } else {
3414 content
3415 };
3416
3417 Ok(ComplexType {
3418 name,
3419 derivation,
3420 content,
3421 matcher: std::sync::OnceLock::new(),
3422 attributes: attr_uses,
3423 any_attribute: any_attr,
3424 abstract_,
3425 block,
3426 final_,
3427 pending_attribute_group_refs: pending_ag_refs,
3428 assertions,
3429 })
3430 }
3431
3432 fn parse_derived_content(
3435 &mut self,
3436 outer_attrs: &[Attr<'a>],
3437 is_simple_content: bool,
3438 ) -> Result<
3439 (Option<Derivation>, ContentModel, Vec<AttributeUse>, Option<Wildcard>, Option<bool>, Vec<QName>),
3440 SchemaCompileError,
3441 > {
3442 let mut deriv: Option<Derivation> = None;
3443 let mut content = ContentModel::Empty;
3444 let mut attrs = Vec::new();
3445 let mut any = None;
3446 let mut mixed: Option<bool> = if is_simple_content {
3450 None
3451 } else {
3452 self.parse_xsd_bool(outer_attrs, "mixed")?
3453 };
3454 let mut pending_ag_refs: Vec<QName> = Vec::new();
3455 let parent = if is_simple_content { "simpleContent" } else { "complexContent" };
3456 let mut seen_anno = false;
3460 let mut seen_other = false;
3461 let mut saw_derivation = false;
3462
3463 loop {
3464 match self.next_event()? {
3465 EventInto::StartElement { name } => {
3466 let inner_attrs = self.take_attrs()?;
3467 self.push_ns_scope(&inner_attrs);
3468 let qn = self.qname_of_element(&name)?;
3469 if qn.namespace.as_deref() == Some(XS) {
3470 self.check_annotation_pos(
3471 &qn.local, &mut seen_anno, &mut seen_other, parent,
3472 )?;
3473 let local = qn.local.as_ref();
3474 match local {
3475 "restriction" | "extension" => {
3476 if saw_derivation {
3477 return Err(self.err(format!(
3478 "<xs:{parent}> must contain exactly one \
3479 <xs:restriction> or <xs:extension>",
3480 )));
3481 }
3482 saw_derivation = true;
3483 let method = if local == "restriction" {
3484 DerivationMethod::Restriction
3485 } else { DerivationMethod::Extension };
3486 let base = self.attr(&inner_attrs, "base")
3487 .ok_or_else(|| self.err(format!(
3488 "missing 'base' on <xs:{local}>"
3489 )))?;
3490 let base_qn = self.parse_qname(base, false)?;
3491 if is_simple_content
3495 && base_qn.namespace.as_deref() == Some(XS)
3496 && base_qn.local.as_ref() == "anyType"
3497 {
3498 return Err(self.err(
3499 "<xs:simpleContent> cannot derive from xs:anyType \
3500 (it has complex content, not simple)",
3501 ));
3502 }
3503 if is_simple_content
3512 && matches!(method, DerivationMethod::Restriction)
3513 && base_qn.namespace.as_deref() == Some(XS)
3514 && base_qn.local.as_ref() != "anyType"
3515 {
3516 return Err(self.err(format!(
3517 "<xs:simpleContent><xs:restriction base={:?}> — \
3518 built-in xs:* types are simple types and cannot \
3519 be restricted via <xs:simpleContent> (use \
3520 <xs:extension>, or restrict via <xs:simpleType>)",
3521 format!("xs:{}", base_qn.local),
3522 )));
3523 }
3524 deriv = Some(Derivation {
3525 method,
3526 base: self.type_ref_for(base_qn),
3527 });
3528
3529 let (inner_content, inner_attrs2, inner_any, inner_mixed, inner_pending) =
3530 self.parse_derivation_body(is_simple_content, method)?;
3531 content = inner_content;
3532 attrs.extend(inner_attrs2);
3533 any = inner_any;
3534 if let Some(m) = inner_mixed { mixed = Some(m); }
3539 pending_ag_refs.extend(inner_pending);
3540 }
3541 "annotation" => self.parse_annotation_body(&inner_attrs)?,
3542 other => return Err(self.err(format!(
3543 "<xs:{other}> is not allowed as a child of <xs:{parent}>"
3544 ))),
3545 }
3546 } else {
3547 self.skip_body()?;
3548 }
3549 self.pop_ns_scope();
3550 }
3551 EventInto::EndElement { .. } => break,
3552 EventInto::Eof => return Err(self.err("unexpected EOF in derived content")),
3553 _ => {}
3554 }
3555 }
3556 if !saw_derivation {
3557 return Err(self.err(format!(
3558 "<xs:{parent}> must contain a <xs:restriction> or <xs:extension>"
3559 )));
3560 }
3561 Ok((deriv, content, attrs, any, mixed, pending_ag_refs))
3562 }
3563
3564 fn parse_derivation_body(
3565 &mut self,
3566 is_simple_content: bool,
3567 method: DerivationMethod,
3568 ) -> Result<(ContentModel, Vec<AttributeUse>, Option<Wildcard>, Option<bool>, Vec<QName>), SchemaCompileError>
3569 {
3570 let mut content = if is_simple_content {
3571 ContentModel::Simple(Arc::new(SimpleType::of_builtin(BuiltinType::String)))
3572 } else {
3573 ContentModel::Empty
3574 };
3575 let mut attrs = Vec::new();
3576 let mut any = None;
3577 let mixed = None;
3578 let mut pending_ag_refs: Vec<QName> = Vec::new();
3579 let mut saw_particle = false;
3583 let mut saw_any_attribute = false;
3584 let mut saw_inline_simple_type = false;
3585 let mut seen_anno = false;
3586 let mut seen_other = false;
3587
3588 loop {
3589 match self.next_event()? {
3590 EventInto::StartElement { name } => {
3591 let child_attrs = self.take_attrs()?;
3592 self.push_ns_scope(&child_attrs);
3593 let qn = self.qname_of_element(&name)?;
3594 if qn.namespace.as_deref() == Some(XS) {
3595 self.check_annotation_pos(
3596 &qn.local, &mut seen_anno, &mut seen_other,
3597 if is_simple_content { "simpleContent derivation" }
3598 else { "complexContent derivation" },
3599 )?;
3600 match qn.local.as_ref() {
3601 "sequence" | "choice" | "all" | "group" => {
3602 if is_simple_content {
3603 return Err(self.err(format!(
3604 "<xs:simpleContent>'s {} body has no place for an \
3605 <xs:{}> model group (simple content's body is text)",
3606 if method == DerivationMethod::Extension { "extension" }
3607 else { "restriction" },
3608 qn.local,
3609 )));
3610 }
3611 if saw_particle || saw_any_attribute || !attrs.is_empty() {
3612 return Err(self.err(
3613 "<xs:extension>/<xs:restriction> body: at most one \
3614 model-group particle, and it must precede attributes",
3615 ));
3616 }
3617 saw_particle = true;
3618 match qn.local.as_ref() {
3619 "group" => {
3620 let r = self.attr(&child_attrs, "ref").ok_or_else(|| self.err(
3621 "<xs:group> inside <xs:extension>/<xs:restriction> must use ref=",
3622 ))?;
3623 let ref_qn = self.parse_qname(r, false)?;
3624 let g_min = parse_min_occurs(self.attr(&child_attrs, "minOccurs"))?;
3625 let g_max = parse_max_occurs(self.attr(&child_attrs, "maxOccurs"))?;
3626 check_occurs(g_min, g_max)?;
3627 content = ContentModel::Complex {
3628 root: Particle {
3629 min_occurs: g_min,
3630 max_occurs: g_max,
3631 term: Term::GroupRef(ref_qn),
3632 },
3633 mixed: false,
3634 };
3635 self.skip_body()?;
3636 }
3637 _ => {
3638 let kind = match qn.local.as_ref() {
3639 "sequence" => GroupKind::Sequence,
3640 "choice" => GroupKind::Choice,
3641 _ => GroupKind::All,
3642 };
3643 let particle = self.parse_group_body(kind, &child_attrs)?;
3644 content = ContentModel::Complex { root: particle, mixed: false };
3645 }
3646 }
3647 }
3648 "attribute" => {
3649 if saw_any_attribute {
3650 return Err(self.err(
3651 "<xs:attribute> cannot follow <xs:anyAttribute>",
3652 ));
3653 }
3654 attrs.push(self.parse_local_attribute_use(&child_attrs)?);
3655 }
3656 "attributeGroup" => {
3657 if saw_any_attribute {
3658 return Err(self.err(
3659 "<xs:attributeGroup> cannot follow <xs:anyAttribute>",
3660 ));
3661 }
3662 let r = self.attr(&child_attrs, "ref").ok_or_else(|| self.err(
3663 "<xs:attributeGroup> inside <xs:extension>/<xs:restriction> \
3664 must use ref= (no nested definitions)",
3665 ))?;
3666 let qn = self.parse_qname(r, false)?;
3667 match self.builder.attr_groups.get(&qn) {
3668 Some(ag) => {
3669 for au in &ag.attributes {
3670 attrs.push(au.clone());
3671 }
3672 any = merge_any_intersect(any, ag.any.clone());
3673 }
3674 None => pending_ag_refs.push(qn),
3675 }
3676 self.parse_anno_only_body("attributeGroup")?;
3677 }
3678 "anyAttribute" => {
3679 if saw_any_attribute {
3680 return Err(self.err(
3681 "at most one <xs:anyAttribute> in this derivation body",
3682 ));
3683 }
3684 saw_any_attribute = true;
3685 check_no_occurs(&child_attrs, "anyAttribute")?;
3686 any = Some(self.parse_wildcard(&child_attrs)?);
3687 self.parse_anno_only_body("anyAttribute")?;
3688 }
3689 "annotation" => self.parse_annotation_body(&child_attrs)?,
3690 "simpleType" | "length" | "minLength" | "maxLength"
3706 | "minInclusive" | "minExclusive" | "maxInclusive"
3707 | "maxExclusive" | "totalDigits" | "fractionDigits"
3708 | "enumeration" | "pattern" | "whiteSpace"
3709 if is_simple_content
3710 && method == DerivationMethod::Restriction =>
3711 {
3712 if !attrs.is_empty() || saw_any_attribute {
3720 return Err(self.err(format!(
3721 "<xs:{}> in a <xs:simpleContent><xs:restriction> \
3722 must precede attribute declarations",
3723 qn.local,
3724 )));
3725 }
3726 if qn.local.as_ref() == "simpleType" {
3727 if saw_inline_simple_type {
3728 return Err(self.err(
3729 "<xs:simpleContent><xs:restriction> body \
3730 may have at most one inline <xs:simpleType>",
3731 ));
3732 }
3733 saw_inline_simple_type = true;
3734 }
3735 self.skip_body()?;
3736 }
3737 other => return Err(self.err(format!(
3738 "<xs:{other}> is not allowed in this derivation body"
3739 ))),
3740 }
3741 } else {
3742 self.skip_body()?;
3743 }
3744 self.pop_ns_scope();
3745 }
3746 EventInto::EndElement { .. } => break,
3747 EventInto::Eof => return Err(self.err("unexpected EOF in derivation body")),
3748 _ => {}
3749 }
3750 }
3751 Ok((content, attrs, any, mixed, pending_ag_refs))
3752 }
3753
3754 fn parse_group_body(&mut self, kind: GroupKind, attrs: &[Attr<'a>])
3757 -> Result<Particle, SchemaCompileError>
3758 {
3759 let min_occurs = parse_min_occurs(self.attr(attrs, "minOccurs"))?;
3760 let max_occurs = parse_max_occurs(self.attr(attrs, "maxOccurs"))?;
3761 check_occurs(min_occurs, max_occurs)?;
3762 if matches!(kind, GroupKind::All) {
3768 let strict_10 = !matches!(
3769 self.builder.effective_version, SchemaVersion::Xsd11
3770 );
3771 if strict_10 {
3772 if min_occurs > 1 {
3773 return Err(self.err(
3774 "<xs:all> minOccurs must be 0 or 1 (XSD 1.0 §3.8.6) — \
3775 set SchemaOptions::version to Xsd11 to relax",
3776 ));
3777 }
3778 if max_occurs != MaxOccurs::Bounded(1) {
3779 return Err(self.err(
3780 "<xs:all> maxOccurs must be exactly 1 (XSD 1.0 §3.8.6) — \
3781 set SchemaOptions::version to Xsd11 to relax",
3782 ));
3783 }
3784 }
3785 }
3786 let parent_name = match kind {
3787 GroupKind::Sequence => "sequence",
3788 GroupKind::Choice => "choice",
3789 GroupKind::All => "all",
3790 };
3791 if self.attr(attrs, "name").is_some() {
3795 return Err(self.err(format!(
3796 "<xs:{parent_name}> does not take a 'name' attribute"
3797 )));
3798 }
3799 let mut particles = Vec::new();
3800 let mut seen_anno = false;
3801 let mut seen_other = false;
3802 loop {
3803 match self.next_event()? {
3804 EventInto::StartElement { name } => {
3805 let child_attrs = self.take_attrs()?;
3806 self.push_ns_scope(&child_attrs);
3807 let qn = self.qname_of_element(&name)?;
3808 if qn.namespace.as_deref() == Some(XS) {
3809 self.check_annotation_pos(
3810 &qn.local, &mut seen_anno, &mut seen_other, parent_name,
3811 )?;
3812 if matches!(kind, GroupKind::All)
3816 && !matches!(qn.local.as_ref(), "element" | "annotation")
3817 {
3818 return Err(self.err(format!(
3819 "<xs:all> body may only contain <xs:element> children, found <xs:{}>",
3820 qn.local,
3821 )));
3822 }
3823 match qn.local.as_ref() {
3824 "element" => {
3825 let p = self.parse_local_element_particle(&child_attrs)?;
3826 if matches!(kind, GroupKind::All)
3830 && !matches!(
3831 self.builder.effective_version,
3832 SchemaVersion::Xsd11
3833 )
3834 && !matches!(p.max_occurs, MaxOccurs::Bounded(0)
3835 | MaxOccurs::Bounded(1))
3836 {
3837 return Err(self.err(
3838 "<xs:all> element particle must have maxOccurs ∈ {0,1} \
3839 (XSD 1.0 §3.8.6 cos-all-particle) — set \
3840 SchemaOptions::version to Xsd11 to relax",
3841 ));
3842 }
3843 particles.push(p);
3844 }
3845 "sequence" | "choice" | "all" => {
3846 let inner_kind = match qn.local.as_ref() {
3847 "sequence" => GroupKind::Sequence,
3848 "choice" => GroupKind::Choice,
3849 _ => GroupKind::All,
3850 };
3851 particles.push(self.parse_group_body(inner_kind, &child_attrs)?);
3852 }
3853 "group" => {
3854 let r = self.attr(&child_attrs, "ref").ok_or_else(|| self.err(
3855 "<xs:group> inside a model group must use ref= \
3856 (nested group definitions are not allowed)",
3857 ))?;
3858 let ref_qn = self.parse_qname(r, false)?;
3859 let g_min = parse_min_occurs(self.attr(&child_attrs, "minOccurs"))?;
3860 let g_max = parse_max_occurs(self.attr(&child_attrs, "maxOccurs"))?;
3861 check_occurs(g_min, g_max)?;
3862 particles.push(Particle {
3863 min_occurs: g_min,
3864 max_occurs: g_max,
3865 term: Term::GroupRef(ref_qn),
3866 });
3867 self.skip_body()?;
3868 }
3869 "any" => {
3870 let any_min = parse_min_occurs(self.attr(&child_attrs, "minOccurs"))?;
3871 let any_max = parse_max_occurs(self.attr(&child_attrs, "maxOccurs"))?;
3872 check_occurs(any_min, any_max)?;
3873 particles.push(Particle {
3874 min_occurs: any_min,
3875 max_occurs: any_max,
3876 term: Term::Wildcard(self.parse_wildcard(&child_attrs)?),
3877 });
3878 self.parse_anno_only_body("any")?;
3879 }
3880 "annotation" => self.parse_annotation_body(&child_attrs)?,
3881 other => return Err(self.err(format!(
3882 "<xs:{other}> is not allowed as a child of <xs:{parent_name}>"
3883 ))),
3884 }
3885 } else {
3886 self.skip_body()?;
3887 }
3888 self.pop_ns_scope();
3889 }
3890 EventInto::EndElement { .. } => break,
3891 EventInto::Eof => return Err(self.err("unexpected EOF in particle group")),
3892 _ => {}
3893 }
3894 }
3895
3896 if matches!(kind, GroupKind::All) {
3900 let mut seen: HashSet<QName> = HashSet::new();
3901 for p in &particles {
3902 if let Term::Element(decl) = &p.term {
3903 if !seen.insert(decl.name.clone()) {
3904 return Err(self.err(format!(
3905 "<xs:all>: duplicate element {:?} — an all-group's \
3906 particles must have distinct names (XSD §3.8.6 \
3907 cos-all-particle)",
3908 decl.name.local,
3909 )));
3910 }
3911 }
3912 }
3913 }
3914
3915 Ok(Particle {
3916 min_occurs,
3917 max_occurs,
3918 term: Term::Group { kind, particles: particles.into() },
3919 })
3920 }
3921
3922 fn parse_local_element_particle(&mut self, attrs: &[Attr<'a>])
3928 -> Result<Particle, SchemaCompileError>
3929 {
3930 let min_occurs = parse_min_occurs(self.attr(attrs, "minOccurs"))?;
3931 let max_occurs = parse_max_occurs(self.attr(attrs, "maxOccurs"))?;
3932 check_occurs(min_occurs, max_occurs)?;
3933 for forbidden in ["abstract", "final", "substitutionGroup"] {
3939 if self.attr(attrs, forbidden).is_some() {
3940 return Err(self.err(format!(
3941 "<xs:element {forbidden}=...> is only valid on top-level element declarations"
3942 )));
3943 }
3944 }
3945 self.check_known_attrs(attrs, &[
3949 "id", "name", "ref", "form", "type", "default", "fixed",
3950 "nillable", "minOccurs", "maxOccurs", "block",
3951 ], "element")?;
3952
3953 if let Some(r) = self.attr(attrs, "ref") {
3959 for forbidden in ["name", "form", "type", "default", "fixed", "nillable", "block"] {
3960 if self.attr(attrs, forbidden).is_some() {
3961 return Err(self.err(format!(
3962 "<xs:element ref=...> cannot also carry '{forbidden}'"
3963 )));
3964 }
3965 }
3966 let qn = self.parse_qname(r, false)?;
3967 self.builder.pending_element_refs.push(qn.clone());
3968 let placeholder = Arc::new(ElementDecl {
3970 name: qn.clone(),
3971 type_def: TypeRef::Simple(Arc::new(SimpleType::of_builtin(BuiltinType::String))),
3972 nillable: false,
3973 default: None,
3974 fixed: None,
3975 abstract_: false,
3976 substitution_group: None,
3977 block: BlockSet::default(),
3978 final_: BlockSet::default(),
3979 identity: Vec::new(),
3980 });
3981 self.parse_anno_only_body("element")?;
3985 return Ok(Particle { min_occurs, max_occurs, term: Term::Element(placeholder) });
3986 }
3987
3988 let name = self.attr(attrs, "name").ok_or_else(||
3994 self.err("local <xs:element> needs name or ref")
3995 )?.to_owned();
3996 let form = match self.attr(attrs, "form") {
3997 Some(raw) => Form::parse(raw).ok_or_else(|| self.err(format!(
3998 "<xs:element form={raw:?}>: must be \"qualified\" or \"unqualified\""
3999 )))?,
4000 None => self.element_form_default,
4001 };
4002 if self.attr(attrs, "default").is_some() && self.attr(attrs, "fixed").is_some() {
4004 return Err(self.err(
4005 "<xs:element> may have either default= or fixed=, not both"
4006 ));
4007 }
4008 let qn = QName {
4009 namespace: match form {
4010 Form::Qualified => self.current_target_ns.clone(),
4011 Form::Unqualified => None,
4012 },
4013 local: Arc::from(name.as_str()),
4014 };
4015 let (inline, identity) = self.parse_inline_type(attrs)?;
4016 if self.attr(attrs, "type").is_some() && inline.is_some() {
4017 return Err(self.err(
4018 "<xs:element> may have either type= or an inline type body, not both"
4019 ));
4020 }
4021 let type_def = match self.attr(attrs, "type") {
4022 Some(t) => {
4023 let type_qn = self.parse_qname(t, false)?;
4024 self.type_ref_for(type_qn)
4025 }
4026 None => inline.unwrap_or_else(any_type_ref),
4027 };
4028 let block = match self.attr(attrs, "block") {
4032 Some(_) => parse_block_set(self.attr(attrs, "block"))?,
4033 None => self.block_default,
4034 };
4035 let decl = Arc::new(ElementDecl {
4036 name: qn,
4037 type_def,
4038 nillable: self.parse_xsd_bool(attrs, "nillable")?.unwrap_or(false),
4039 default: self.attr(attrs, "default").map(|s| s.to_owned()),
4040 fixed: self.attr(attrs, "fixed").map(|s| s.to_owned()),
4041 abstract_: false,
4042 substitution_group: None,
4043 block,
4044 final_: BlockSet::default(),
4045 identity,
4046 });
4047 Ok(Particle { min_occurs, max_occurs, term: Term::Element(decl) })
4048 }
4049
4050 fn parse_local_attribute_use(&mut self, attrs: &[Attr<'a>])
4051 -> Result<AttributeUse, SchemaCompileError>
4052 {
4053 self.check_known_attrs(attrs, &[
4055 "id", "name", "ref", "type", "use", "default", "fixed", "form",
4056 ], "attribute")?;
4057 let use_kind = match self.attr(attrs, "use") {
4058 Some("required") => AttributeUseKind::Required,
4059 Some("prohibited") => AttributeUseKind::Prohibited,
4060 Some("optional") => AttributeUseKind::Optional,
4061 None => AttributeUseKind::Optional,
4062 Some(other) => return Err(self.err(format!(
4063 "<xs:attribute use={other:?}>: must be \"required\", \"optional\", or \"prohibited\""
4064 ))),
4065 };
4066 if self.attr(attrs, "default").is_some()
4070 && !matches!(use_kind, AttributeUseKind::Optional)
4071 {
4072 return Err(self.err(
4073 "<xs:attribute default=...> requires use=\"optional\"",
4074 ));
4075 }
4076
4077 if let Some(r) = self.attr(attrs, "ref") {
4079 for forbidden in ["name", "form", "type"] {
4084 if self.attr(attrs, forbidden).is_some() {
4085 return Err(self.err(format!(
4086 "<xs:attribute ref=...> cannot also carry '{forbidden}'"
4087 )));
4088 }
4089 }
4090 let qn = self.parse_qname(r, false)?;
4091 let use_fixed = self.attr(attrs, "fixed").map(|s| s.to_owned());
4096 if let Some(use_fixed_v) = use_fixed.as_deref() {
4097 if let Some(decl) = self.builder.attributes.get(&qn) {
4098 if let Some(decl_fixed) = decl.fixed.as_deref() {
4099 if decl_fixed != use_fixed_v {
4100 return Err(self.err(format!(
4101 "<xs:attribute ref={r:?} fixed={use_fixed_v:?}>: \
4102 referenced declaration has fixed={decl_fixed:?}; \
4103 a ref-form use cannot change the fixed value"
4104 )));
4105 }
4106 }
4107 }
4108 }
4109 self.builder.pending_attribute_refs.push(qn.clone());
4110 let placeholder = Arc::new(AttributeDecl {
4111 name: qn,
4112 type_def: Arc::new(SimpleType::of_builtin(BuiltinType::String)),
4113 default: self.attr(attrs, "default").map(|s| s.to_owned()),
4114 fixed: use_fixed,
4115 inheritable: false,
4122 });
4123 self.parse_anno_only_body("attribute")?;
4125 return Ok(AttributeUse {
4126 use_kind,
4127 decl: placeholder,
4128 default: None,
4129 fixed: None,
4130 });
4131 }
4132
4133 let name = self.attr(attrs, "name").ok_or_else(||
4134 self.err("local <xs:attribute> needs name or ref")
4135 )?.to_owned();
4136 if name == "xmlns" {
4137 return Err(self.err(
4138 "<xs:attribute name=\"xmlns\"> is reserved by the Namespaces in XML spec",
4139 ));
4140 }
4141 let form = match self.attr(attrs, "form") {
4142 Some(raw) => Form::parse(raw).ok_or_else(|| self.err(format!(
4143 "<xs:attribute form={raw:?}>: must be \"qualified\" or \"unqualified\""
4144 )))?,
4145 None => self.attribute_form_default,
4146 };
4147 if self.attr(attrs, "default").is_some() && self.attr(attrs, "fixed").is_some() {
4148 return Err(self.err(
4149 "<xs:attribute> may have either default= or fixed=, not both"
4150 ));
4151 }
4152 let qn = QName {
4153 namespace: match form {
4154 Form::Qualified => self.current_target_ns.clone(),
4155 Form::Unqualified => None,
4156 },
4157 local: Arc::from(name.as_str()),
4158 };
4159 check_xsi_attribute_name(&qn).map_err(|m| self.err(m))?;
4160 let inline = self.parse_inline_simple_type(attrs)?;
4161 if self.attr(attrs, "type").is_some() && inline.is_some() {
4162 return Err(self.err(
4163 "<xs:attribute> may have either type= or an inline <xs:simpleType>, not both"
4164 ));
4165 }
4166 let st = match self.attr(attrs, "type") {
4167 Some(t) => {
4168 let type_qn = self.parse_qname(t, false)?;
4169 self.simple_type_for(type_qn)
4170 }
4171 None => Arc::new(inline.unwrap_or_else(|| SimpleType::of_builtin(BuiltinType::String))),
4172 };
4173 let decl = Arc::new(AttributeDecl {
4174 name: qn,
4175 type_def: st,
4176 default: self.attr(attrs, "default").map(|s| s.to_owned()),
4177 fixed: self.attr(attrs, "fixed").map(|s| s.to_owned()),
4178 inheritable: self.parse_inheritable(attrs)?,
4179 });
4180 Ok(AttributeUse { use_kind, decl, default: None, fixed: None })
4181 }
4182
4183 fn parse_top_attribute_group(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
4184 let name = match self.attr(attrs, "name") {
4188 Some(n) => QName {
4189 namespace: self.current_target_ns.clone(),
4190 local: Arc::from(n),
4191 },
4192 None => return Err(self.err(
4193 "top-level <xs:attributeGroup> requires a 'name' attribute",
4194 )),
4195 };
4196 if !self.in_redefine && self.builder.attr_groups.contains_key(&name) {
4197 return Err(self.err(format!(
4198 "duplicate <xs:attributeGroup name={:?}> in target namespace",
4199 name.local,
4200 )));
4201 }
4202 let mut uses = Vec::new();
4203 let mut any = None;
4204 let mut local_refs: Vec<QName> = Vec::new();
4205 let mut seen_anno = false;
4206 let mut seen_other = false;
4207 let mut seen_any_attribute = false;
4208 loop {
4209 match self.next_event()? {
4210 EventInto::StartElement { name: child } => {
4211 let cattrs = self.take_attrs()?;
4212 self.push_ns_scope(&cattrs);
4213 let qn = self.qname_of_element(&child)?;
4214 if qn.namespace.as_deref() == Some(XS) {
4215 self.check_annotation_pos(
4216 &qn.local, &mut seen_anno, &mut seen_other, "attributeGroup",
4217 )?;
4218 match qn.local.as_ref() {
4219 "attribute" => {
4220 if seen_any_attribute {
4221 return Err(self.err(
4222 "<xs:attribute> cannot follow <xs:anyAttribute> in <xs:attributeGroup>",
4223 ));
4224 }
4225 uses.push(self.parse_local_attribute_use(&cattrs)?);
4226 }
4227 "attributeGroup" => {
4228 if seen_any_attribute {
4229 return Err(self.err(
4230 "<xs:attributeGroup> cannot follow <xs:anyAttribute> in <xs:attributeGroup>",
4231 ));
4232 }
4233 let r = self.attr(&cattrs, "ref").ok_or_else(|| self.err(
4234 "<xs:attributeGroup> inside another attributeGroup must use ref= \
4235 (nested definitions are not allowed)",
4236 ))?;
4237 let rqn = self.parse_qname(r, false)?;
4238 self.builder.pending_ag_refs_in_ag.push(rqn.clone());
4239 local_refs.push(rqn.clone());
4240 if Some(&rqn) == self.builder.redefining_ag_name.as_ref() {
4241 self.builder.redefining_ag_saw_self_ref = true;
4242 }
4243 if let Some(ag) = self.builder.attr_groups.get(&rqn) {
4244 for au in &ag.attributes {
4245 uses.push(au.clone());
4246 }
4247 any = merge_any_intersect(any, ag.any.clone());
4248 }
4249 self.parse_anno_only_body("attributeGroup")?;
4250 }
4251 "anyAttribute" => {
4252 if seen_any_attribute {
4253 return Err(self.err(
4254 "<xs:attributeGroup> body: at most one <xs:anyAttribute>",
4255 ));
4256 }
4257 seen_any_attribute = true;
4258 check_no_occurs(&cattrs, "anyAttribute")?;
4259 any = Some(self.parse_wildcard(&cattrs)?);
4260 self.parse_anno_only_body("anyAttribute")?;
4261 }
4262 "annotation" => self.parse_annotation_body(&cattrs)?,
4263 other => return Err(self.err(format!(
4264 "<xs:{other}> is not allowed as a child of <xs:attributeGroup>"
4265 ))),
4266 }
4267 } else { self.skip_body()?; }
4268 self.pop_ns_scope();
4269 }
4270 EventInto::EndElement { .. } => break,
4271 EventInto::Eof => return Err(self.err("unexpected EOF in attributeGroup")),
4272 _ => {}
4273 }
4274 }
4275 if !self.in_redefine {
4281 self.builder.ag_refs_by_owner.insert(name.clone(), local_refs);
4282 }
4283 self.builder.attr_groups.insert(name.clone(), Arc::new(AttributeGroup {
4284 name, attributes: uses, any,
4285 }));
4286 Ok(())
4287 }
4288
4289 fn parse_top_group(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
4290 if self.attr(attrs, "ref").is_some() {
4295 return Err(self.err(
4296 "<xs:group ref=...> is only valid inside a complexType / model-group, \
4297 not at schema top level",
4298 ));
4299 }
4300 for forbidden in ["minOccurs", "maxOccurs"] {
4303 if self.attr(attrs, forbidden).is_some() {
4304 return Err(self.err(format!(
4305 "top-level <xs:group> does not take '{forbidden}'"
4306 )));
4307 }
4308 }
4309 let name = match self.attr(attrs, "name") {
4310 Some(n) => QName {
4311 namespace: self.current_target_ns.clone(),
4312 local: Arc::from(n),
4313 },
4314 None => return Err(self.err(
4315 "top-level <xs:group> requires a 'name' attribute",
4316 )),
4317 };
4318 if !self.in_redefine && self.builder.model_groups.contains_key(&name) {
4319 return Err(self.err(format!(
4320 "duplicate <xs:group name={:?}> in target namespace",
4321 name.local,
4322 )));
4323 }
4324 let mut particle: Option<Particle> = None;
4325 let mut seen_anno = false;
4326 let mut seen_other = false;
4327 loop {
4328 match self.next_event()? {
4329 EventInto::StartElement { name: child } => {
4330 let cattrs = self.take_attrs()?;
4331 self.push_ns_scope(&cattrs);
4332 let qn = self.qname_of_element(&child)?;
4333 if qn.namespace.as_deref() == Some(XS) {
4334 self.check_annotation_pos(
4335 &qn.local, &mut seen_anno, &mut seen_other, "group",
4336 )?;
4337 match qn.local.as_ref() {
4338 "sequence" | "choice" | "all" => {
4339 if particle.is_some() {
4340 return Err(self.err(
4341 "<xs:group> must contain exactly one of \
4342 <xs:sequence>, <xs:choice>, or <xs:all>",
4343 ));
4344 }
4345 let kind = match qn.local.as_ref() {
4346 "sequence" => GroupKind::Sequence,
4347 "choice" => GroupKind::Choice,
4348 _ => GroupKind::All,
4349 };
4350 particle = Some(self.parse_group_body(kind, &cattrs)?);
4351 }
4352 "annotation" => self.parse_annotation_body(&cattrs)?,
4353 other => return Err(self.err(format!(
4354 "<xs:{other}> is not allowed as a child of <xs:group>"
4355 ))),
4356 }
4357 } else { self.skip_body()?; }
4358 self.pop_ns_scope();
4359 }
4360 EventInto::EndElement { .. } => break,
4361 EventInto::Eof => return Err(self.err("unexpected EOF in group")),
4362 _ => {}
4363 }
4364 }
4365 if let Some(p) = particle {
4366 self.builder.model_groups.insert(name.clone(), Arc::new(ModelGroup { name, particle: p }));
4367 }
4368 Ok(())
4369 }
4370
4371 fn parse_top_notation(&mut self, attrs: &[Attr<'a>]) -> Result<(), SchemaCompileError> {
4372 self.check_known_attrs(attrs, &["id", "name", "public", "system"], "notation")?;
4375 let name_raw = self.attr(attrs, "name")
4376 .ok_or_else(|| self.err("<xs:notation> requires a 'name' attribute"))?;
4377 super::types::SimpleType::of_builtin(super::types::BuiltinType::NCName)
4378 .validate(name_raw)
4379 .map_err(|e| self.err(format!(
4380 "<xs:notation name={name_raw:?}> must be an NCName: {}", e.message,
4381 )))?;
4382 let public_id = self.attr(attrs, "public").map(|s| s.to_owned());
4383 let system_id = self.attr(attrs, "system").map(|s| s.to_owned());
4384 if public_id.is_none() && system_id.is_none() {
4385 return Err(self.err(
4386 "<xs:notation> requires at least one of 'public' or 'system'"
4387 ));
4388 }
4389 let name = QName {
4390 namespace: self.current_target_ns.clone(),
4391 local: Arc::from(name_raw),
4392 };
4393 if !self.in_redefine && self.builder.notations.contains_key(&name) {
4394 return Err(self.err(format!(
4395 "duplicate <xs:notation name={name_raw:?}> in target namespace"
4396 )));
4397 }
4398 self.parse_anno_only_body("notation")?;
4399 self.builder.notations.insert(name.clone(), Arc::new(NotationDecl {
4400 name, public_id, system_id,
4401 }));
4402 Ok(())
4403 }
4404
4405}
4406
4407fn resolve_simple_member_placeholders(types: &mut std::collections::HashMap<QName, TypeRef>) {
4439 use super::types::Variety;
4440 let resolve = |m: &Arc<super::types::SimpleType>,
4441 snap: &std::collections::HashMap<QName, TypeRef>|
4442 -> Arc<super::types::SimpleType> {
4443 if let Some(qn) = resolve_typeref_to_qname(&TypeRef::Simple(m.clone())) {
4444 if let Some(TypeRef::Simple(real)) = snap.get(&qn) {
4445 return real.clone();
4446 }
4447 }
4448 m.clone()
4449 };
4450 for _ in 0..8 {
4451 let snapshot = types.clone();
4452 let mut changed = false;
4453 for tr in types.values_mut() {
4454 let TypeRef::Simple(st) = tr else { continue };
4455 let new_variety = match &st.variety {
4456 Variety::Union { members } => Variety::Union {
4457 members: members.iter().map(|m| resolve(m, &snapshot)).collect(),
4458 },
4459 Variety::List { item_type } => Variety::List {
4460 item_type: resolve(item_type, &snapshot),
4461 },
4462 Variety::Atomic => continue,
4463 };
4464 let mut new_st = (**st).clone();
4465 new_st.variety = new_variety;
4466 *st = Arc::new(new_st);
4467 changed = true;
4468 }
4469 if !changed { break; }
4470 }
4471}
4472
4473fn merge_extension_chains(
4474 types: &mut HashMap<QName, TypeRef>,
4475) -> Result<(), SchemaCompileError> {
4476 let names: Vec<QName> = types.keys().cloned().collect();
4477 let mut merged: HashSet<QName> = HashSet::new();
4478 let mut merging: HashSet<QName> = HashSet::new();
4479 for name in &names {
4480 merge_one_extension(name, types, &mut merged, &mut merging)?;
4481 }
4482 Ok(())
4483}
4484
4485fn merge_one_extension(
4486 name: &QName,
4487 types: &mut HashMap<QName, TypeRef>,
4488 merged: &mut HashSet<QName>,
4489 merging: &mut HashSet<QName>,
4490) -> Result<(), SchemaCompileError> {
4491 if merged.contains(name) { return Ok(()); }
4492 if !merging.insert(name.clone()) {
4493 return Err(SchemaCompileError::msg(format!(
4494 "cyclic complex-type derivation involving {}", name
4495 )));
4496 }
4497
4498 let current = types.get(name).cloned();
4500 if let Some(TypeRef::Complex(ct)) = current {
4501 if let Some(d) = &ct.derivation {
4502 if d.method == DerivationMethod::Extension {
4503 let base_ct: Option<Arc<ComplexType>> = match &d.base {
4513 TypeRef::Complex(c) => Some(c.clone()),
4514 _ => {
4515 if let Some(base_qn) = resolve_typeref_to_qname(&d.base) {
4516 merge_one_extension(&base_qn, types, merged, merging)?;
4517 match types.get(&base_qn) {
4518 Some(TypeRef::Complex(c)) => Some(c.clone()),
4519 _ => None,
4520 }
4521 } else { None }
4522 }
4523 };
4524 if let Some(base_ct) = base_ct {
4525 let new_ct = compose_extension(&base_ct, &ct);
4526 types.insert(name.clone(), TypeRef::Complex(Arc::new(new_ct)));
4527 } else if matches!(ct.content, ContentModel::Simple(_)) {
4528 let base_simple: Option<Arc<SimpleType>> = match &d.base {
4536 TypeRef::Simple(st) if st.name.as_deref()
4537 .map(|n| !n.starts_with("UNRESOLVED:"))
4538 .unwrap_or(true) => Some(st.clone()),
4539 TypeRef::Simple(_) => {
4540 resolve_typeref_to_qname(&d.base)
4541 .and_then(|qn| match types.get(&qn) {
4542 Some(TypeRef::Simple(s)) => Some(s.clone()),
4543 _ => None,
4544 })
4545 }
4546 TypeRef::Complex(_) => None,
4547 };
4548 if let Some(base_simple) = base_simple {
4549 let new_ct = ComplexType {
4550 name: ct.name.clone(),
4551 derivation: ct.derivation.clone(),
4552 content: ContentModel::Simple(base_simple),
4553 matcher: std::sync::OnceLock::new(),
4554 attributes: ct.attributes.clone(),
4555 any_attribute: ct.any_attribute.clone(),
4556 abstract_: ct.abstract_,
4557 block: ct.block,
4558 final_: ct.final_,
4559 pending_attribute_group_refs: ct.pending_attribute_group_refs.clone(),
4560 assertions: ct.assertions.clone(),
4561 };
4562 types.insert(name.clone(), TypeRef::Complex(Arc::new(new_ct)));
4563 }
4564 }
4565 }
4566 }
4567 }
4568
4569 merged.insert(name.clone());
4570 merging.remove(name);
4571 Ok(())
4572}
4573
4574fn merge_restriction_attributes(
4591 types: &mut HashMap<QName, TypeRef>,
4592 elements: &mut HashMap<QName, Arc<ElementDecl>>,
4593) {
4594 use super::types::DerivationMethod;
4595
4596 fn resolved_base<'a>(
4597 d: &super::types::Derivation,
4598 types: &'a HashMap<QName, TypeRef>,
4599 ) -> Option<Arc<ComplexType>> {
4600 match &d.base {
4601 TypeRef::Complex(c) => Some(c.clone()),
4602 _ => resolve_typeref_to_qname(&d.base)
4603 .and_then(|qn| match types.get(&qn) {
4604 Some(TypeRef::Complex(c)) => Some(c.clone()),
4605 _ => None,
4606 }),
4607 }
4608 }
4609
4610 fn merge_one(ct: &ComplexType, base: &ComplexType) -> ComplexType {
4611 use super::schema::{AttributeUseKind, AttributeUse};
4612 let mut merged: Vec<AttributeUse> = ct.attributes.clone();
4613 for b_au in &base.attributes {
4614 if merged.iter().any(|a| a.decl.name == b_au.decl.name) {
4620 continue;
4621 }
4622 if b_au.use_kind == AttributeUseKind::Prohibited {
4623 continue;
4624 }
4625 merged.push(b_au.clone());
4626 }
4627 let any_attribute = ct.any_attribute.clone().or_else(|| base.any_attribute.clone());
4630 ComplexType {
4631 name: ct.name.clone(),
4632 derivation: ct.derivation.clone(),
4633 content: ct.content.clone(),
4634 matcher: std::sync::OnceLock::new(),
4635 attributes: merged,
4636 any_attribute,
4637 abstract_: ct.abstract_,
4638 block: ct.block,
4639 final_: ct.final_,
4640 pending_attribute_group_refs: ct.pending_attribute_group_refs.clone(),
4641 assertions: ct.assertions.clone(),
4642 }
4643 }
4644
4645 let names: Vec<QName> = types.keys().cloned().collect();
4646 for name in names {
4647 let Some(TypeRef::Complex(ct)) = types.get(&name).cloned() else { continue };
4648 let Some(d) = &ct.derivation else { continue };
4649 if d.method != DerivationMethod::Restriction { continue; }
4650 let Some(base) = resolved_base(d, types) else { continue };
4651 let merged = merge_one(&ct, &base);
4652 types.insert(name, TypeRef::Complex(Arc::new(merged)));
4653 }
4654
4655 let elem_names: Vec<QName> = elements.keys().cloned().collect();
4658 for ename in elem_names {
4659 let Some(decl) = elements.get(&ename).cloned() else { continue };
4660 let TypeRef::Complex(ct) = &decl.type_def else { continue };
4661 if ct.name.is_some() { continue; }
4662 let Some(d) = &ct.derivation else { continue };
4663 if d.method != DerivationMethod::Restriction { continue; }
4664 let Some(base) = resolved_base(d, types) else { continue };
4665 let merged = merge_one(ct, &base);
4666 let new_decl = ElementDecl {
4667 name: decl.name.clone(),
4668 type_def: TypeRef::Complex(Arc::new(merged)),
4669 nillable: decl.nillable,
4670 default: decl.default.clone(),
4671 fixed: decl.fixed.clone(),
4672 abstract_: decl.abstract_,
4673 substitution_group: decl.substitution_group.clone(),
4674 identity: decl.identity.clone(),
4675 block: decl.block,
4676 final_: decl.final_,
4677 };
4678 elements.insert(ename, Arc::new(new_decl));
4679 }
4680}
4681
4682fn merge_inline_extension_in_elements(
4683 elements: &mut HashMap<QName, Arc<ElementDecl>>,
4684 types: &HashMap<QName, TypeRef>,
4685) {
4686 let names: Vec<QName> = elements.keys().cloned().collect();
4687 for name in names {
4688 let Some(decl) = elements.get(&name).cloned() else { continue };
4689 let TypeRef::Complex(ct) = &decl.type_def else { continue };
4690 if ct.name.is_some() { continue; }
4692 let Some(d) = &ct.derivation else { continue };
4693 if d.method != DerivationMethod::Extension { continue; }
4694 let base_ct: Option<Arc<ComplexType>> = match &d.base {
4695 TypeRef::Complex(c) => Some(c.clone()),
4696 _ => resolve_typeref_to_qname(&d.base)
4697 .and_then(|qn| types.get(&qn).cloned())
4698 .and_then(|tr| match tr {
4699 TypeRef::Complex(c) => Some(c),
4700 _ => None,
4701 }),
4702 };
4703 let merged = if let Some(base_ct) = base_ct {
4704 compose_extension(&base_ct, ct)
4705 } else if matches!(ct.content, ContentModel::Simple(_)) {
4706 let base_simple: Option<Arc<SimpleType>> = match &d.base {
4712 TypeRef::Simple(st) if st.name.as_deref()
4713 .map(|n| !n.starts_with("UNRESOLVED:"))
4714 .unwrap_or(true) => Some(st.clone()),
4715 TypeRef::Simple(_) => resolve_typeref_to_qname(&d.base)
4716 .and_then(|qn| match types.get(&qn) {
4717 Some(TypeRef::Simple(s)) => Some(s.clone()),
4718 _ => None,
4719 }),
4720 TypeRef::Complex(_) => None,
4721 };
4722 let Some(base_simple) = base_simple else { continue };
4723 ComplexType {
4724 name: ct.name.clone(),
4725 derivation: ct.derivation.clone(),
4726 content: ContentModel::Simple(base_simple),
4727 matcher: std::sync::OnceLock::new(),
4728 attributes: ct.attributes.clone(),
4729 any_attribute: ct.any_attribute.clone(),
4730 final_: ct.final_,
4731 block: ct.block,
4732 abstract_: ct.abstract_,
4733 pending_attribute_group_refs: ct.pending_attribute_group_refs.clone(),
4734 assertions: ct.assertions.clone(),
4735 }
4736 } else { continue };
4737 let new_decl = ElementDecl {
4738 name: decl.name.clone(),
4739 type_def: TypeRef::Complex(Arc::new(merged)),
4740 nillable: decl.nillable,
4741 default: decl.default.clone(),
4742 fixed: decl.fixed.clone(),
4743 abstract_: decl.abstract_,
4744 substitution_group: decl.substitution_group.clone(),
4745 identity: decl.identity.clone(),
4746 block: decl.block,
4747 final_: decl.final_,
4748 };
4749 elements.insert(name, Arc::new(new_decl));
4750 }
4751}
4752
4753fn check_derivation_content_kind(
4757 types: &HashMap<QName, TypeRef>,
4758) -> Result<(), SchemaCompileError> {
4759 for (name, tr) in types {
4760 let TypeRef::Complex(ct) = tr else { continue };
4761 let Some(deriv) = ct.derivation.as_ref() else { continue };
4762 let derived_is_simple = matches!(ct.content, ContentModel::Simple(_));
4767 let derived_is_complex = matches!(ct.content, ContentModel::Complex { .. });
4768 if derived_is_simple && deriv.method == DerivationMethod::Restriction {
4769 let base_is_complex = match &deriv.base {
4770 TypeRef::Complex(_) => true,
4771 TypeRef::Simple(_) => match resolve_typeref_to_qname(&deriv.base) {
4772 Some(qn) => matches!(types.get(&qn), Some(TypeRef::Complex(_))),
4773 None => false, },
4775 };
4776 if !base_is_complex {
4777 return Err(SchemaCompileError::msg(format!(
4778 "<xs:complexType name={:?}>: <xs:simpleContent><xs:restriction> \
4779 base must be a complex type with simple content, not a simple type",
4780 name.local,
4781 )));
4782 }
4783 }
4784 let base_ct = match &deriv.base {
4786 TypeRef::Complex(c) => Some(c.clone()),
4787 TypeRef::Simple(_) => match resolve_typeref_to_qname(&deriv.base) {
4788 Some(qn) => match types.get(&qn) {
4789 Some(TypeRef::Complex(c)) => Some(c.clone()),
4790 _ => None,
4791 },
4792 None => None,
4793 },
4794 };
4795 if derived_is_complex {
4800 let base_is_simple = match &deriv.base {
4801 TypeRef::Simple(st) => match resolve_typeref_to_qname(&deriv.base) {
4802 Some(qn) if qn.namespace.as_deref() == Some(QName::XSD_NS) => {
4803 BuiltinType::from_name(&qn.local).is_some()
4807 }
4808 Some(qn) => matches!(types.get(&qn), Some(TypeRef::Simple(_))),
4809 None => st.name.is_none(),
4813 },
4814 _ => false,
4815 };
4816 if base_is_simple {
4817 return Err(SchemaCompileError::msg(format!(
4818 "<xs:complexType name={:?}>: <xs:complexContent> base must be a \
4819 complex type, not a simple type",
4820 name.local,
4821 )));
4822 }
4823 }
4824 let Some(base_ct) = base_ct else { continue };
4825 let base_is_simple = matches!(base_ct.content, ContentModel::Simple(_));
4826 let base_is_complex = matches!(base_ct.content, ContentModel::Complex { .. });
4827 if derived_is_complex && base_is_simple {
4828 return Err(SchemaCompileError::msg(format!(
4829 "<xs:complexType name={:?}>: complexContent derivation cannot \
4830 have a simpleContent base",
4831 name.local,
4832 )));
4833 }
4834 if derived_is_simple && base_is_complex {
4835 return Err(SchemaCompileError::msg(format!(
4836 "<xs:complexType name={:?}>: simpleContent derivation cannot \
4837 have a complexContent base",
4838 name.local,
4839 )));
4840 }
4841 }
4842 Ok(())
4843}
4844
4845fn check_complex_type_final(
4846 types: &HashMap<QName, TypeRef>,
4847 elements: &HashMap<QName, Arc<ElementDecl>>,
4848) -> Result<(), SchemaCompileError> {
4849 use super::types::DerivationMethod;
4850 fn check_one(
4851 ct: &ComplexType,
4852 types: &HashMap<QName, TypeRef>,
4853 label: &str,
4854 ) -> Result<(), SchemaCompileError> {
4855 let Some(d) = &ct.derivation else { return Ok(()) };
4856 let base_ct: Option<Arc<ComplexType>> = match &d.base {
4857 TypeRef::Complex(c) => Some(c.clone()),
4858 TypeRef::Simple(_) => resolve_typeref_to_qname(&d.base)
4859 .and_then(|qn| match types.get(&qn) {
4860 Some(TypeRef::Complex(c)) => Some(c.clone()),
4861 _ => None,
4862 }),
4863 };
4864 let Some(base_ct) = base_ct else { return Ok(()) };
4865 let blocked = match d.method {
4866 DerivationMethod::Restriction => base_ct.final_.contains(BlockSet::RESTRICTION),
4867 DerivationMethod::Extension => base_ct.final_.contains(BlockSet::EXTENSION),
4868 };
4869 if blocked {
4870 return Err(SchemaCompileError::msg(format!(
4871 "{label}: base complex type's `final` disallows {} derivation",
4872 match d.method {
4873 DerivationMethod::Restriction => "restriction",
4874 DerivationMethod::Extension => "extension",
4875 },
4876 )));
4877 }
4878 Ok(())
4879 }
4880 for (name, tr) in types {
4881 if let TypeRef::Complex(ct) = tr {
4882 let label = format!("<xs:complexType name={:?}>", name.local);
4883 check_one(ct, types, &label)?;
4884 }
4885 }
4886 for (name, decl) in elements {
4887 if let TypeRef::Complex(ct) = &decl.type_def {
4888 let label = format!("<xs:element name={:?}>'s inline type", name.local);
4889 check_one(ct, types, &label)?;
4890 }
4891 }
4892 Ok(())
4893}
4894
4895fn check_complex_mixed_consistency(
4896 types: &HashMap<QName, TypeRef>,
4897 elements: &HashMap<QName, Arc<ElementDecl>>,
4898) -> Result<(), SchemaCompileError> {
4899 fn mixed_of(c: &ContentModel) -> Option<bool> {
4900 match c {
4901 ContentModel::Complex { mixed, .. } => Some(*mixed),
4902 _ => None,
4903 }
4904 }
4905 fn check_one(
4906 ct: &ComplexType,
4907 types: &HashMap<QName, TypeRef>,
4908 label: &str,
4909 ) -> Result<(), SchemaCompileError> {
4910 let Some(d) = &ct.derivation else { return Ok(()) };
4911 let Some(d_mixed) = mixed_of(&ct.content) else { return Ok(()) };
4912 let base_ct: Option<Arc<ComplexType>> = match &d.base {
4913 TypeRef::Complex(c) => Some(c.clone()),
4914 TypeRef::Simple(_) => resolve_typeref_to_qname(&d.base)
4915 .and_then(|qn| match types.get(&qn) {
4916 Some(TypeRef::Complex(c)) => Some(c.clone()),
4917 _ => None,
4918 }),
4919 };
4920 let Some(base_ct) = base_ct else { return Ok(()) };
4921 let Some(b_mixed) = mixed_of(&base_ct.content) else { return Ok(()) };
4922 let bad = match d.method {
4923 super::types::DerivationMethod::Extension => b_mixed != d_mixed,
4925 super::types::DerivationMethod::Restriction => !b_mixed && d_mixed,
4928 };
4929 if bad {
4930 return Err(SchemaCompileError::msg(format!(
4931 "{label}: complexContent {} cannot change mixed from {b_mixed} to {d_mixed}",
4932 match d.method {
4933 super::types::DerivationMethod::Extension => "extension",
4934 super::types::DerivationMethod::Restriction => "restriction",
4935 },
4936 )));
4937 }
4938 Ok(())
4939 }
4940 for (name, tr) in types {
4941 if let TypeRef::Complex(ct) = tr {
4942 let label = format!("<xs:complexType name={:?}>", name.local);
4943 check_one(ct, types, &label)?;
4944 }
4945 }
4946 for (name, decl) in elements {
4947 if let TypeRef::Complex(ct) = &decl.type_def {
4948 let label = format!("<xs:element name={:?}>'s inline type", name.local);
4949 check_one(ct, types, &label)?;
4950 }
4951 }
4952 Ok(())
4953}
4954
4955fn ns_constraint_subset(
4956 derived: &super::schema::NamespaceConstraint,
4957 base: &super::schema::NamespaceConstraint,
4958) -> bool {
4959 use super::schema::NamespaceConstraint::*;
4960 match (derived, base) {
4961 (_, Any) => true,
4962 (Any, _) => false,
4963 (Other, Other) => true,
4964 (Other, _) => false,
4965 (List(d), Other) => d.iter().all(|e| e.is_some()),
4966 (List(d), List(b)) => d.iter().all(|d|
4967 b.iter().any(|b| match (d, b) {
4968 (None, None) => true,
4969 (Some(x), Some(y)) => x == y,
4970 _ => false,
4971 })
4972 ),
4973 }
4974}
4975
4976fn wildcard_allows_ns(
4977 c: &super::schema::NamespaceConstraint,
4978 ns: Option<&str>,
4979) -> bool {
4980 use super::schema::NamespaceConstraint::*;
4981 match c {
4982 Any => true,
4983 Other => ns.is_some(),
4984 List(entries) => entries.iter().any(|e| match (e, ns) {
4985 (None, None) => true,
4986 (Some(u), Some(n)) => u.as_ref() == n,
4987 _ => false,
4988 }),
4989 }
4990}
4991
4992fn process_strictness(w: &super::schema::Wildcard) -> u8 {
4993 use super::schema::ProcessContents::*;
4994 match w.process_contents { Strict => 2, Lax => 1, Skip => 0 }
4995}
4996
4997fn check_complex_restriction_attributes(
4998 types: &HashMap<QName, TypeRef>,
4999 elements: &HashMap<QName, Arc<ElementDecl>>,
5000) -> Result<(), SchemaCompileError> {
5001 use super::schema::AttributeUse;
5002 use super::types::DerivationMethod;
5003
5004 fn resolve_base<'a>(
5005 d: &'a super::types::Derivation,
5006 types: &'a HashMap<QName, TypeRef>,
5007 ) -> Option<&'a ComplexType> {
5008 match &d.base {
5009 TypeRef::Complex(c) => Some(c.as_ref()),
5010 _ => resolve_typeref_to_qname(&d.base).and_then(|qn| match types.get(&qn) {
5011 Some(TypeRef::Complex(c)) => Some(c.as_ref()),
5012 _ => None,
5013 }),
5014 }
5015 }
5016
5017 fn check_one(
5018 ct: &ComplexType,
5019 types: &HashMap<QName, TypeRef>,
5020 label: &str,
5021 ) -> Result<(), SchemaCompileError> {
5022 let Some(d) = &ct.derivation else { return Ok(()); };
5023 if d.method != DerivationMethod::Restriction { return Ok(()); }
5024 let Some(base) = resolve_base(d, types) else { return Ok(()); };
5025
5026 let find_au = |name: &QName, attrs: &[AttributeUse]| -> Option<AttributeUse> {
5027 attrs.iter().find(|au| &au.decl.name == name).cloned()
5028 };
5029
5030 match (&base.any_attribute, &ct.any_attribute) {
5035 (None, Some(_)) => {
5036 return Err(SchemaCompileError::msg(format!(
5037 "{label}: invalid restriction of base — base has no \
5038 <xs:anyAttribute> but the derived type adds one (restriction \
5039 can only tighten, not introduce, attribute wildcards)"
5040 )));
5041 }
5042 (Some(b_any), Some(d_any)) => {
5043 if !ns_constraint_subset(&d_any.namespaces, &b_any.namespaces) {
5044 return Err(SchemaCompileError::msg(format!(
5045 "{label}: invalid restriction of base — derived \
5046 <xs:anyAttribute> namespace is not a subset of base's"
5047 )));
5048 }
5049 if process_strictness(d_any) < process_strictness(b_any) {
5050 return Err(SchemaCompileError::msg(format!(
5051 "{label}: invalid restriction of base — derived \
5052 <xs:anyAttribute> processContents relaxes the base's"
5053 )));
5054 }
5055 }
5056 _ => {}
5057 }
5058 let base_attr_names: std::collections::HashSet<&QName> =
5061 base.attributes.iter().map(|au| &au.decl.name).collect();
5062 for au_d in &ct.attributes {
5063 if au_d.use_kind == AttributeUseKind::Prohibited { continue; }
5064 if base_attr_names.contains(&au_d.decl.name) { continue; }
5065 let Some(b_any) = &base.any_attribute else {
5066 return Err(SchemaCompileError::msg(format!(
5067 "{label}: invalid restriction of base — derived adds \
5068 attribute {:?} not present in the base, but the base \
5069 has no <xs:anyAttribute> to license it",
5070 au_d.decl.name.local,
5071 )));
5072 };
5073 if !wildcard_allows_ns(&b_any.namespaces, au_d.decl.name.namespace.as_deref()) {
5074 return Err(SchemaCompileError::msg(format!(
5075 "{label}: invalid restriction of base — derived adds \
5076 attribute {:?} (namespace {:?}) which the base's \
5077 <xs:anyAttribute> namespace set doesn't allow",
5078 au_d.decl.name.local, au_d.decl.name.namespace.as_deref().unwrap_or(""),
5079 )));
5080 }
5081 }
5082
5083 for au_b in &base.attributes {
5084 if au_b.use_kind == AttributeUseKind::Prohibited { continue; }
5085 let au_r = find_au(&au_b.decl.name, &ct.attributes);
5086
5087 if au_b.use_kind == AttributeUseKind::Required {
5092 match au_r.as_ref().map(|x| x.use_kind) {
5093 Some(AttributeUseKind::Required) => {}
5094 Some(other) => {
5095 return Err(SchemaCompileError::msg(format!(
5096 "{label}: invalid restriction of base — attribute {:?} \
5097 is `required` in the base but `{:?}` in the derived type",
5098 au_b.decl.name.local, other,
5099 )));
5100 }
5101 None => {
5102 return Err(SchemaCompileError::msg(format!(
5103 "{label}: invalid restriction of base — attribute {:?} \
5104 is `required` in the base but absent in the derived type",
5105 au_b.decl.name.local,
5106 )));
5107 }
5108 }
5109 }
5110
5111 let base_fixed = au_b.fixed.as_deref().or(au_b.decl.fixed.as_deref());
5115 if let Some(bf) = base_fixed {
5116 if let Some(au_r) = au_r.as_ref() {
5117 let r_fixed = au_r.fixed.as_deref().or(au_r.decl.fixed.as_deref());
5118 let r_default = au_r.default.as_deref().or(au_r.decl.default.as_deref());
5119 match (r_fixed, r_default) {
5120 (Some(rf), _) if rf != bf => {
5121 return Err(SchemaCompileError::msg(format!(
5122 "{label}: invalid restriction of base — attribute {:?} \
5123 fixed value {:?} differs from base fixed {:?}",
5124 au_b.decl.name.local, rf, bf,
5125 )));
5126 }
5127 (None, Some(_)) => {
5128 return Err(SchemaCompileError::msg(format!(
5129 "{label}: invalid restriction of base — attribute {:?} \
5130 has `fixed={:?}` in the base; the derived may not \
5131 replace it with `default=`",
5132 au_b.decl.name.local, bf,
5133 )));
5134 }
5135 _ => {}
5136 }
5137 }
5138 }
5139 }
5140 Ok(())
5141 }
5142
5143 for (name, tr) in types {
5144 if let TypeRef::Complex(ct) = tr {
5145 let label = format!("<xs:complexType name={:?}>", name.local);
5146 check_one(ct, types, &label)?;
5147 }
5148 }
5149 for (name, decl) in elements {
5150 if let TypeRef::Complex(ct) = &decl.type_def {
5151 let label = format!("<xs:element name={:?}>'s inline type", name.local);
5152 check_one(ct, types, &label)?;
5153 }
5154 }
5155 Ok(())
5156}
5157
5158fn check_type_refs_collide(
5159 types: &HashMap<QName, TypeRef>,
5160 attributes: &HashMap<QName, Arc<AttributeDecl>>,
5161 attr_groups: &HashMap<QName, Arc<AttributeGroup>>,
5162 elements: &HashMap<QName, Arc<ElementDecl>>,
5163) -> Result<(), SchemaCompileError> {
5164 fn check_typeref(
5165 tr: &TypeRef,
5166 owner: &str,
5167 types: &HashMap<QName, TypeRef>,
5168 attributes: &HashMap<QName, Arc<AttributeDecl>>,
5169 attr_groups: &HashMap<QName, Arc<AttributeGroup>>,
5170 elements: &HashMap<QName, Arc<ElementDecl>>,
5171 ) -> Result<(), SchemaCompileError> {
5172 let Some(qn) = resolve_typeref_to_qname(tr) else { return Ok(()) };
5176 if types.contains_key(&qn) { return Ok(()) }
5177 let kind = if attributes.contains_key(&qn) { Some("an attribute") }
5178 else if attr_groups.contains_key(&qn) { Some("an attributeGroup") }
5179 else if elements.contains_key(&qn) { Some("an element") }
5180 else { None };
5181 match kind {
5182 Some(k) => Err(SchemaCompileError::msg(format!(
5183 "{owner}: type={:?} resolves to {k}, not a type",
5184 qn.local,
5185 ))),
5186 None => Err(SchemaCompileError::msg(format!(
5190 "{owner}: undefined type {:?} \
5191 (no <xs:simpleType> or <xs:complexType> with this name; \
5192 check that any <xs:include>/<xs:import> schemaLocation \
5193 was loadable)",
5194 qn.local,
5195 ))),
5196 }
5197 }
5198 fn walk_complex(
5199 ct: &ComplexType,
5200 types: &HashMap<QName, TypeRef>,
5201 attributes: &HashMap<QName, Arc<AttributeDecl>>,
5202 attr_groups: &HashMap<QName, Arc<AttributeGroup>>,
5203 elements: &HashMap<QName, Arc<ElementDecl>>,
5204 visited: &mut std::collections::HashSet<*const ComplexType>,
5205 ) -> Result<(), SchemaCompileError> {
5206 if !visited.insert(ct as *const _) { return Ok(()); }
5207 if let Some(deriv) = ct.derivation.as_ref() {
5212 let label = format!("<xs:complexType name={:?}> base",
5213 ct.name.as_ref().map(|n| &*n.local).unwrap_or("<anonymous>"));
5214 check_typeref(&deriv.base, &label,
5215 types, attributes, attr_groups, elements)?;
5216 }
5217 for au in &ct.attributes {
5218 check_typeref(&TypeRef::Simple(au.decl.type_def.clone()),
5219 &format!("<xs:attribute name={:?}>", au.decl.name.local),
5220 types, attributes, attr_groups, elements)?;
5221 }
5222 if let ContentModel::Complex { root, .. } = &ct.content {
5223 walk_particle(root, types, attributes, attr_groups, elements, visited)?;
5224 }
5225 Ok(())
5226 }
5227 fn walk_particle(
5228 p: &super::schema::Particle,
5229 types: &HashMap<QName, TypeRef>,
5230 attributes: &HashMap<QName, Arc<AttributeDecl>>,
5231 attr_groups: &HashMap<QName, Arc<AttributeGroup>>,
5232 elements: &HashMap<QName, Arc<ElementDecl>>,
5233 visited: &mut std::collections::HashSet<*const ComplexType>,
5234 ) -> Result<(), SchemaCompileError> {
5235 use super::schema::Term;
5236 match &p.term {
5237 Term::Element(e) => {
5238 check_typeref(&e.type_def, &format!("<xs:element name={:?}>", e.name.local),
5239 types, attributes, attr_groups, elements)?;
5240 if let TypeRef::Complex(ct) = &e.type_def {
5241 walk_complex(ct, types, attributes, attr_groups, elements, visited)?;
5242 }
5243 }
5244 Term::Group { particles, .. } => {
5245 for child in particles.iter() {
5246 walk_particle(child, types, attributes, attr_groups, elements, visited)?;
5247 }
5248 }
5249 _ => {}
5250 }
5251 Ok(())
5252 }
5253
5254 let mut visited: std::collections::HashSet<*const ComplexType> = std::collections::HashSet::new();
5255 for (qn, decl) in elements {
5256 let owner = format!("<xs:element name={:?}>", qn.local);
5257 check_typeref(&decl.type_def, &owner, types, attributes, attr_groups, elements)?;
5258 if let TypeRef::Complex(ct) = &decl.type_def {
5259 walk_complex(ct, types, attributes, attr_groups, elements, &mut visited)?;
5260 }
5261 }
5262 for (qn, attr) in attributes {
5263 let owner = format!("<xs:attribute name={:?}>", qn.local);
5264 check_typeref(&TypeRef::Simple(attr.type_def.clone()), &owner,
5265 types, attributes, attr_groups, elements)?;
5266 }
5267 for ct in types.values().filter_map(|t| match t {
5268 TypeRef::Complex(c) => Some(c),
5269 _ => None,
5270 }) {
5271 walk_complex(ct, types, attributes, attr_groups, elements, &mut visited)?;
5272 }
5273 Ok(())
5274}
5275
5276fn check_element_refs(
5277 refs: &[QName],
5278 elements: &HashMap<QName, Arc<ElementDecl>>,
5279 types: &HashMap<QName, TypeRef>,
5280 attributes: &HashMap<QName, Arc<AttributeDecl>>,
5281 attr_groups: &HashMap<QName, Arc<AttributeGroup>>,
5282 target_ns: Option<&str>,
5283 imports: &HashSet<Option<Arc<str>>>,
5284) -> Result<(), SchemaCompileError> {
5285 for ref_qn in refs {
5286 if elements.contains_key(ref_qn) { continue; }
5287 let collision = if types.contains_key(ref_qn) {
5288 Some("a type")
5289 } else if attributes.contains_key(ref_qn) {
5290 Some("an attribute")
5291 } else if attr_groups.contains_key(ref_qn) {
5292 Some("an attributeGroup")
5293 } else {
5294 None
5295 };
5296 if let Some(kind) = collision {
5297 return Err(SchemaCompileError::msg(format!(
5298 "<xs:element ref={:?}> resolves to {kind}, not an element",
5299 ref_qn.local,
5300 )));
5301 }
5302 if ref_qn.namespace.as_deref() != target_ns
5306 && !import_covers(imports, ref_qn.namespace.as_deref())
5307 {
5308 return Err(SchemaCompileError::msg(format!(
5309 "<xs:element ref={:?}>: namespace {:?} is not the schema's \
5310 targetNamespace and was not brought in by <xs:import> (XSD §3.3.6 \
5311 src-resolve)",
5312 ref_qn.local, ref_qn.namespace.as_deref().unwrap_or(""),
5313 )));
5314 }
5315 if ref_qn.namespace.as_deref() == target_ns {
5319 return Err(SchemaCompileError::msg(format!(
5320 "<xs:element ref={:?}>: no top-level <xs:element name={:?}> \
5321 declaration in this schema",
5322 ref_qn.local, ref_qn.local,
5323 )));
5324 }
5325 }
5326 Ok(())
5327}
5328
5329fn check_redefined_attribute_groups(
5330 pending: &[(QName, Arc<AttributeGroup>, Arc<AttributeGroup>, bool)],
5331 types: &HashMap<QName, TypeRef>,
5332) -> Result<(), SchemaCompileError> {
5333 for (name, new_ag, original, saw_self_ref) in pending {
5334 if *saw_self_ref { continue; }
5341 for new_use in &new_ag.attributes {
5342 let orig_use = original.attributes.iter()
5343 .find(|u| u.decl.name == new_use.decl.name);
5344 let Some(orig_use) = orig_use else {
5345 return Err(SchemaCompileError::msg(format!(
5346 "<xs:redefine><xs:attributeGroup name={:?}>: attribute {:?} \
5347 is not present in the original attribute group — a redefining \
5348 body without a self-reference must be a valid restriction \
5349 (XSD §4.2.2 src-redefine)",
5350 name.local, new_use.decl.name.local,
5351 )));
5352 };
5353 if matches!(orig_use.use_kind, AttributeUseKind::Required)
5357 && matches!(new_use.use_kind,
5358 AttributeUseKind::Optional | AttributeUseKind::Prohibited)
5359 {
5360 return Err(SchemaCompileError::msg(format!(
5361 "<xs:redefine><xs:attributeGroup name={:?}>: attribute {:?} \
5362 was required in the original; the redefining body cannot \
5363 relax it to {:?}",
5364 name.local, new_use.decl.name.local, new_use.use_kind,
5365 )));
5366 }
5367 let _ = types;
5373 if matches!(orig_use.use_kind, AttributeUseKind::Prohibited)
5376 && !matches!(new_use.use_kind, AttributeUseKind::Prohibited)
5377 {
5378 return Err(SchemaCompileError::msg(format!(
5379 "<xs:redefine><xs:attributeGroup name={:?}>: attribute {:?} \
5380 was prohibited in the original; the redefining body cannot \
5381 relax that to {:?}",
5382 name.local, new_use.decl.name.local, new_use.use_kind,
5383 )));
5384 }
5385 }
5386 for orig_use in &original.attributes {
5391 if !matches!(orig_use.use_kind, AttributeUseKind::Required) { continue; }
5392 if !new_ag.attributes.iter().any(|u|
5393 u.decl.name == orig_use.decl.name
5394 && matches!(u.use_kind, AttributeUseKind::Required))
5395 {
5396 return Err(SchemaCompileError::msg(format!(
5397 "<xs:redefine><xs:attributeGroup name={:?}>: required attribute \
5398 {:?} is missing in the redefining body — a non-self-reference \
5399 redefine cannot drop required attributes",
5400 name.local, orig_use.decl.name.local,
5401 )));
5402 }
5403 }
5404 }
5405 Ok(())
5406}
5407
5408
5409fn check_pending_simple_facet_tightening(
5416 pending: &[(QName, Vec<Facet>)],
5417 types: &HashMap<QName, TypeRef>,
5418) -> Result<(), SchemaCompileError> {
5419 for (base_qn, derived) in pending {
5420 let Some(tr) = types.get(base_qn) else {
5421 return Err(SchemaCompileError::msg(format!(
5422 "<xs:restriction base={:?}>: undefined simple type",
5423 base_qn.local,
5424 )));
5425 };
5426 let base_st = match tr {
5427 TypeRef::Simple(st) => st.clone(),
5428 TypeRef::Complex(_) => return Err(SchemaCompileError::msg(format!(
5429 "<xs:restriction base={:?}> in a simpleType must reference a \
5430 simpleType, not a complexType",
5431 base_qn.local,
5432 ))),
5433 };
5434 let mut reparsed: Vec<Facet> = Vec::with_capacity(derived.len());
5440 for f in derived {
5441 reparsed.push(reparse_bound_facet(f, base_st.builtin)?);
5442 }
5443 check_facet_tightening_pure(&base_st.facets.facets, &reparsed).map_err(|m| {
5444 SchemaCompileError::msg(format!(
5445 "<xs:restriction base={:?}>: {m}", base_qn.local,
5446 ))
5447 })?;
5448 }
5449 Ok(())
5450}
5451
5452fn reparse_bound_facet(f: &Facet, builtin: BuiltinType) -> Result<Facet, SchemaCompileError> {
5453 fn reparse(b: &Bound, builtin: BuiltinType) -> Result<Bound, SchemaCompileError> {
5454 match b {
5455 Bound::Value(super::types::Value::String(s)) => parse_bound(s, builtin),
5456 _ => Ok(b.clone()),
5457 }
5458 }
5459 Ok(match f {
5460 Facet::MinInclusive(b) => Facet::MinInclusive(reparse(b, builtin)?),
5461 Facet::MaxInclusive(b) => Facet::MaxInclusive(reparse(b, builtin)?),
5462 Facet::MinExclusive(b) => Facet::MinExclusive(reparse(b, builtin)?),
5463 Facet::MaxExclusive(b) => Facet::MaxExclusive(reparse(b, builtin)?),
5464 other => other.clone(),
5465 })
5466}
5467
5468fn check_facet_tightening_pure(base: &[Facet], derived: &[Facet]) -> Result<(), String> {
5473 fn pick<'a, T, F>(slice: &'a [Facet], f: F) -> Option<&'a T>
5474 where F: Fn(&'a Facet) -> Option<&'a T> {
5475 slice.iter().rev().find_map(f)
5476 }
5477 let base_length = pick(base, |f| if let Facet::Length(n) = f { Some(n) } else { None });
5478 let base_min_len = pick(base, |f| if let Facet::MinLength(n) = f { Some(n) } else { None });
5479 let base_max_len = pick(base, |f| if let Facet::MaxLength(n) = f { Some(n) } else { None });
5480 let base_min_incl = pick(base, |f| if let Facet::MinInclusive(b) = f { Some(b) } else { None });
5481 let base_max_incl = pick(base, |f| if let Facet::MaxInclusive(b) = f { Some(b) } else { None });
5482 let base_min_excl = pick(base, |f| if let Facet::MinExclusive(b) = f { Some(b) } else { None });
5483 let base_max_excl = pick(base, |f| if let Facet::MaxExclusive(b) = f { Some(b) } else { None });
5484 let base_total_d = pick(base, |f| if let Facet::TotalDigits(n) = f { Some(n) } else { None });
5485 let base_frac_d = pick(base, |f| if let Facet::FractionDigits(n) = f { Some(n) } else { None });
5486 for f in derived {
5487 match f {
5488 Facet::Length(n) => {
5489 if let Some(b) = base_length {
5490 if n != b {
5491 return Err(format!("restriction length ({n}) must equal base length ({b})"));
5492 }
5493 }
5494 if let Some(b) = base_min_len {
5495 if (*n as usize) < (*b) {
5496 return Err(format!("restriction length ({n}) is below base minLength ({b})"));
5497 }
5498 }
5499 if let Some(b) = base_max_len {
5500 if (*n as usize) > (*b) {
5501 return Err(format!("restriction length ({n}) exceeds base maxLength ({b})"));
5502 }
5503 }
5504 }
5505 Facet::MinLength(n) => {
5506 if let Some(b) = base_min_len {
5507 if n < b {
5508 return Err(format!("restriction minLength ({n}) is below base minLength ({b})"));
5509 }
5510 }
5511 if let Some(b) = base_length {
5512 if (*n as u32) != (*b as u32) {
5513 return Err(format!("restriction minLength ({n}) is inconsistent with base length ({b})"));
5514 }
5515 }
5516 }
5517 Facet::MaxLength(n) => {
5518 if let Some(b) = base_max_len {
5519 if n > b {
5520 return Err(format!("restriction maxLength ({n}) exceeds base maxLength ({b})"));
5521 }
5522 }
5523 if let Some(b) = base_length {
5524 if (*n as u32) != (*b as u32) {
5525 return Err(format!("restriction maxLength ({n}) is inconsistent with base length ({b})"));
5526 }
5527 }
5528 }
5529 Facet::MinInclusive(d) => {
5530 if let Some(b) = base_min_incl {
5531 if compare_bounds(d, b).map(|o| o.is_lt()).unwrap_or(false) {
5532 return Err("restriction minInclusive is below the base's min bound".into());
5533 }
5534 }
5535 if let Some(b) = base_min_excl {
5536 if compare_bounds(d, b).map(|o| !o.is_gt()).unwrap_or(false) {
5540 return Err("restriction minInclusive is at or below the base's minExclusive bound".into());
5541 }
5542 }
5543 if let Some(b) = base_max_incl {
5544 if compare_bounds(d, b).map(|o| o.is_gt()).unwrap_or(false) {
5545 return Err("restriction minInclusive exceeds the base's max bound".into());
5546 }
5547 }
5548 if let Some(b) = base_max_excl {
5549 if compare_bounds(d, b).map(|o| !o.is_lt()).unwrap_or(false) {
5552 return Err("restriction minInclusive is at or above the base's maxExclusive bound".into());
5553 }
5554 }
5555 }
5556 Facet::MinExclusive(d) => {
5557 for b in base_min_incl.into_iter().chain(base_min_excl) {
5558 if compare_bounds(d, b).map(|o| o.is_lt()).unwrap_or(false) {
5559 return Err("restriction minExclusive is below the base's min bound".into());
5560 }
5561 }
5562 for b in base_max_incl.into_iter().chain(base_max_excl) {
5563 if compare_bounds(d, b).map(|o| o.is_ge()).unwrap_or(false) {
5564 return Err("restriction minExclusive is at or above the base's max bound".into());
5565 }
5566 }
5567 }
5568 Facet::MaxInclusive(d) => {
5569 if let Some(b) = base_max_incl {
5570 if compare_bounds(d, b).map(|o| o.is_gt()).unwrap_or(false) {
5571 return Err("restriction maxInclusive exceeds the base's max bound".into());
5572 }
5573 }
5574 if let Some(b) = base_max_excl {
5575 if compare_bounds(d, b).map(|o| !o.is_lt()).unwrap_or(false) {
5579 return Err("restriction maxInclusive is at or above the base's maxExclusive bound".into());
5580 }
5581 }
5582 for b in base_min_incl.into_iter().chain(base_min_excl) {
5583 if compare_bounds(d, b).map(|o| o.is_lt()).unwrap_or(false) {
5584 return Err("restriction maxInclusive is below the base's min bound".into());
5585 }
5586 }
5587 }
5588 Facet::MaxExclusive(d) => {
5589 for b in base_max_incl.into_iter().chain(base_max_excl) {
5590 if compare_bounds(d, b).map(|o| o.is_gt()).unwrap_or(false) {
5591 return Err("restriction maxExclusive exceeds the base's max bound".into());
5592 }
5593 }
5594 for b in base_min_incl.into_iter().chain(base_min_excl) {
5595 if compare_bounds(d, b).map(|o| o.is_le()).unwrap_or(false) {
5596 return Err("restriction maxExclusive is at or below the base's min bound".into());
5597 }
5598 }
5599 }
5600 Facet::TotalDigits(n) => {
5601 if let Some(b) = base_total_d {
5602 if n > b {
5603 return Err(format!("restriction totalDigits ({n}) exceeds base totalDigits ({b})"));
5604 }
5605 }
5606 }
5607 Facet::FractionDigits(n) => {
5608 if let Some(b) = base_frac_d {
5609 if n > b {
5610 return Err(format!("restriction fractionDigits ({n}) exceeds base fractionDigits ({b})"));
5611 }
5612 }
5613 }
5614 _ => {}
5615 }
5616 }
5617 Ok(())
5618}
5619
5620fn import_covers(imports: &HashSet<Option<Arc<str>>>, ns: Option<&str>) -> bool {
5621 match ns {
5622 None => imports.iter().any(|entry| entry.is_none()),
5623 Some(s) => imports.iter().any(|entry| entry.as_deref() == Some(s)),
5624 }
5625}
5626
5627fn check_id_typed_element_value_constraints(
5633 elements: &HashMap<QName, Arc<ElementDecl>>,
5634 types: &HashMap<QName, TypeRef>,
5635) -> Result<(), SchemaCompileError> {
5636 fn id_typed_simple(st: &super::types::SimpleType, types: &HashMap<QName, TypeRef>) -> bool {
5637 if matches!(st.builtin, BuiltinType::Id) { return true; }
5638 if let Some(name) = &st.name {
5645 if let Some(rest) = name.strip_prefix("UNRESOLVED:") {
5646 let qn = if let Some(rest) = rest.strip_prefix('{') {
5647 if let Some(end) = rest.find('}') {
5648 let ns = &rest[..end];
5649 let local = &rest[end + 1..];
5650 QName::new(if ns.is_empty() { None } else { Some(ns) }, local)
5651 } else { QName::new(None, rest) }
5652 } else { QName::new(None, rest) };
5653 if let Some(TypeRef::Simple(real)) = types.get(&qn) {
5654 return id_typed_simple(real, types);
5655 }
5656 }
5657 }
5658 false
5659 }
5660 for decl in elements.values() {
5661 if decl.default.is_none() && decl.fixed.is_none() { continue; }
5662 if let TypeRef::Simple(st) = &decl.type_def {
5663 if id_typed_simple(st, types) {
5664 return Err(SchemaCompileError::msg(format!(
5665 "<xs:element name={:?}> of type xs:ID (or derived) cannot have \
5666 a default or fixed value (XSD §3.3.6)",
5667 decl.name.local,
5668 )));
5669 }
5670 }
5671 }
5672 Ok(())
5673}
5674
5675fn check_element_decls_consistent(
5681 types: &HashMap<QName, TypeRef>,
5682 elements: &HashMap<QName, Arc<ElementDecl>>,
5683) -> Result<(), SchemaCompileError> {
5684 fn typerefs_compatible(a: &TypeRef, b: &TypeRef) -> bool {
5685 match (a, b) {
5686 (TypeRef::Simple(x), TypeRef::Simple(y)) => {
5687 if Arc::ptr_eq(x, y) { return true; }
5688 if x.name.is_none() && y.name.is_none()
5692 && x.builtin == y.builtin
5693 && matches!(x.variety, super::types::Variety::Atomic)
5694 && matches!(y.variety, super::types::Variety::Atomic)
5695 {
5696 return true;
5697 }
5698 x.name.is_some() && x.name == y.name
5699 }
5700 (TypeRef::Complex(x), TypeRef::Complex(y)) => Arc::ptr_eq(x, y)
5701 || (x.name.is_some() && x.name == y.name),
5702 _ => false,
5703 }
5704 }
5705 fn walk(
5706 p: &super::schema::Particle,
5707 seen: &mut HashMap<QName, TypeRef>,
5708 owner: &str,
5709 ) -> Result<(), SchemaCompileError> {
5710 match &p.term {
5711 super::schema::Term::Element(decl) => {
5712 if let Some(prev) = seen.get(&decl.name) {
5713 if !typerefs_compatible(prev, &decl.type_def) {
5714 return Err(SchemaCompileError::msg(format!(
5715 "{owner}: element {:?} appears twice in the content \
5716 model with different types (XSD §3.8.6 Element \
5717 Declarations Consistent)",
5718 decl.name.local,
5719 )));
5720 }
5721 } else {
5722 seen.insert(decl.name.clone(), decl.type_def.clone());
5723 }
5724 }
5725 super::schema::Term::Group { particles, .. } => {
5726 for c in particles.iter() { walk(c, seen, owner)?; }
5727 }
5728 super::schema::Term::Wildcard(_)
5729 | super::schema::Term::GroupRef(_) => {}
5730 }
5731 Ok(())
5732 }
5733 let check_complex = |ct: &ComplexType| -> Result<(), SchemaCompileError> {
5734 if let ContentModel::Complex { root, .. } = &ct.content {
5735 let mut seen: HashMap<QName, TypeRef> = HashMap::new();
5736 let owner = format!("<xs:complexType name={:?}>",
5737 ct.name.as_ref().map(|n| &*n.local).unwrap_or("<anonymous>"));
5738 walk(root, &mut seen, &owner)?;
5739 }
5740 Ok(())
5741 };
5742 for tr in types.values() {
5743 if let TypeRef::Complex(ct) = tr { check_complex(ct)?; }
5744 }
5745 for decl in elements.values() {
5746 if let TypeRef::Complex(ct) = &decl.type_def { check_complex(ct)?; }
5747 }
5748 Ok(())
5749}
5750
5751fn check_substitution_group_typing(
5752 elements: &HashMap<QName, Arc<ElementDecl>>,
5753 types: &HashMap<QName, TypeRef>,
5754) -> Result<(), SchemaCompileError> {
5755 fn is_any_type(tr: &TypeRef) -> bool {
5756 matches!(tr, TypeRef::Complex(ct)
5757 if ct.name.as_ref()
5758 .map(|n| n.namespace.as_deref() == Some(QName::XSD_NS)
5759 && n.local.as_ref() == "anyType")
5760 .unwrap_or(false))
5761 }
5762 for sub in elements.values() {
5763 let Some(head_qn) = &sub.substitution_group else { continue };
5764 let Some(head) = elements.get(head_qn) else { continue };
5765
5766 if is_any_type(&sub.type_def) {
5773 continue;
5774 }
5775
5776 let used = super::dfa::derivation_methods_between(
5777 &sub.type_def, &head.type_def, types,
5778 );
5779 let Some(used) = used else {
5780 return Err(SchemaCompileError::msg(format!(
5781 "<xs:element name={:?} substitutionGroup={:?}>: \
5782 substituting element's type does not derive from the head's type",
5783 sub.name.local, head_qn.local,
5784 )));
5785 };
5786
5787 let head_type_final = match &head.type_def {
5791 TypeRef::Complex(ct) => ct.final_,
5792 TypeRef::Simple(_) => BlockSet::default(),
5793 };
5794 let blocked = head.final_ | head_type_final;
5795 let forbidden = used & blocked & (BlockSet::RESTRICTION | BlockSet::EXTENSION);
5796 if !forbidden.is_empty() {
5797 let label = if forbidden.contains(BlockSet::RESTRICTION) && forbidden.contains(BlockSet::EXTENSION) {
5798 "restriction and extension"
5799 } else if forbidden.contains(BlockSet::RESTRICTION) {
5800 "restriction"
5801 } else {
5802 "extension"
5803 };
5804 return Err(SchemaCompileError::msg(format!(
5805 "<xs:element name={:?} substitutionGroup={:?}>: \
5806 head element's `final` disallows {label}-based substitution",
5807 sub.name.local, head_qn.local,
5808 )));
5809 }
5810 }
5811 Ok(())
5812}
5813
5814fn check_substitution_group_heads(
5815 elements: &HashMap<QName, Arc<ElementDecl>>,
5816) -> Result<(), SchemaCompileError> {
5817 for decl in elements.values() {
5818 let Some(head) = &decl.substitution_group else { continue };
5819 if !elements.contains_key(head) {
5820 return Err(SchemaCompileError::msg(format!(
5821 "<xs:element name={:?} substitutionGroup={:?}>: \
5822 the head element is not declared",
5823 decl.name.local, head.local,
5824 )));
5825 }
5826 }
5827 for decl in elements.values() {
5831 let mut seen: HashSet<QName> = HashSet::new();
5832 let mut cur = decl.clone();
5833 loop {
5834 let Some(head_qn) = &cur.substitution_group else { break };
5835 if !seen.insert(cur.name.clone()) {
5836 return Err(SchemaCompileError::msg(format!(
5837 "<xs:element name={:?}>: substitution-group chain is cyclic \
5838 (eventually revisits {:?}); per XSD §3.3.6 cos-equiv-class-correct \
5839 the substitution graph must be a forest",
5840 decl.name.local, cur.name.local,
5841 )));
5842 }
5843 if head_qn == &cur.name {
5844 return Err(SchemaCompileError::msg(format!(
5845 "<xs:element name={:?}>: cannot substitute for itself",
5846 cur.name.local,
5847 )));
5848 }
5849 let Some(next) = elements.get(head_qn) else { break };
5850 cur = next.clone();
5851 }
5852 }
5853 Ok(())
5854}
5855
5856fn check_xsi_attribute_name(qn: &QName) -> Result<(), String> {
5862 match qn.namespace.as_deref() {
5863 Some("http://www.w3.org/2001/XMLSchema-instance") => Err(format!(
5864 "<xs:attribute name={:?}> in the XML Schema Instance namespace is not allowed",
5865 qn.local,
5866 )),
5867 _ => Ok(()),
5868 }
5869}
5870
5871fn check_attribute_group_cycles(
5872 edges: &HashMap<QName, Vec<QName>>,
5873) -> Result<(), SchemaCompileError> {
5874 enum Color { White, Gray, Black }
5875 let mut color: HashMap<&QName, Color> = edges.keys().map(|k| (k, Color::White)).collect();
5876 fn dfs<'a>(
5877 node: &'a QName,
5878 edges: &'a HashMap<QName, Vec<QName>>,
5879 color: &mut HashMap<&'a QName, Color>,
5880 ) -> Result<(), QName> {
5881 color.insert(node, Color::Gray);
5882 if let Some(refs) = edges.get(node) {
5883 for r in refs {
5884 let next_key = edges.keys().find(|k| *k == r);
5886 let Some(next) = next_key else { continue };
5887 match color.get(next) {
5888 Some(Color::Gray) => return Err(node.clone()),
5889 Some(Color::Black) => {}
5890 Some(Color::White) | None => dfs(next, edges, color)?,
5891 }
5892 }
5893 }
5894 color.insert(node, Color::Black);
5895 Ok(())
5896 }
5897 let names: Vec<&QName> = edges.keys().collect();
5898 for n in names {
5899 if matches!(color.get(n), Some(Color::White)) {
5900 if let Err(cyc) = dfs(n, edges, &mut color) {
5901 return Err(SchemaCompileError::msg(format!(
5902 "cyclic <xs:attributeGroup> reference involving {:?} \
5903 (XSD §3.6.6 src-attribute-group-cyclic)",
5904 cyc.local,
5905 )));
5906 }
5907 }
5908 }
5909 Ok(())
5910}
5911
5912fn check_ag_refs_in_ag(
5913 refs: &[QName],
5914 attr_groups: &HashMap<QName, Arc<AttributeGroup>>,
5915 types: &HashMap<QName, TypeRef>,
5916 elements: &HashMap<QName, Arc<ElementDecl>>,
5917 attributes: &HashMap<QName, Arc<AttributeDecl>>,
5918) -> Result<(), SchemaCompileError> {
5919 for ref_qn in refs {
5920 if attr_groups.contains_key(ref_qn) { continue; }
5921 let collision = if types.contains_key(ref_qn) {
5922 Some("a type")
5923 } else if elements.contains_key(ref_qn) {
5924 Some("an element")
5925 } else if attributes.contains_key(ref_qn) {
5926 Some("an attribute")
5927 } else {
5928 None
5929 };
5930 if let Some(kind) = collision {
5931 return Err(SchemaCompileError::msg(format!(
5932 "<xs:attributeGroup ref={:?}> resolves to {kind}, not an attributeGroup",
5933 ref_qn.local,
5934 )));
5935 }
5936 }
5937 Ok(())
5938}
5939
5940fn check_attribute_refs(
5941 refs: &[QName],
5942 attributes: &HashMap<QName, Arc<AttributeDecl>>,
5943 attr_groups: &HashMap<QName, Arc<AttributeGroup>>,
5944 types: &HashMap<QName, TypeRef>,
5945 elements: &HashMap<QName, Arc<ElementDecl>>,
5946 target_ns: Option<&str>,
5947 imports: &HashSet<Option<Arc<str>>>,
5948) -> Result<(), SchemaCompileError> {
5949 for ref_qn in refs {
5950 if attributes.contains_key(ref_qn) { continue; }
5951 let collision = if attr_groups.contains_key(ref_qn) {
5952 Some("an attributeGroup")
5953 } else if types.contains_key(ref_qn) {
5954 Some("a type")
5955 } else if elements.contains_key(ref_qn) {
5956 Some("an element")
5957 } else {
5958 None
5959 };
5960 if let Some(kind) = collision {
5961 return Err(SchemaCompileError::msg(format!(
5962 "<xs:attribute ref={:?}> resolves to {kind}, not an attribute",
5963 ref_qn.local,
5964 )));
5965 }
5966 if ref_qn.namespace.as_deref() != target_ns
5969 && !import_covers(imports, ref_qn.namespace.as_deref())
5970 {
5971 return Err(SchemaCompileError::msg(format!(
5972 "<xs:attribute ref={:?}>: namespace {:?} is not the schema's \
5973 targetNamespace and was not brought in by <xs:import> (XSD §3.2.3 \
5974 src-resolve)",
5975 ref_qn.local, ref_qn.namespace.as_deref().unwrap_or(""),
5976 )));
5977 }
5978 if ref_qn.namespace.as_deref() == target_ns {
5982 return Err(SchemaCompileError::msg(format!(
5983 "<xs:attribute ref={:?}>: no top-level <xs:attribute name={:?}> \
5984 declaration in this schema",
5985 ref_qn.local, ref_qn.local,
5986 )));
5987 }
5988 }
5989 Ok(())
5990}
5991
5992fn check_attribute_group_ref_kinds(
5993 types: &HashMap<QName, TypeRef>,
5994 elements: &HashMap<QName, Arc<ElementDecl>>,
5995 attr_groups: &HashMap<QName, Arc<AttributeGroup>>,
5996 attributes: &HashMap<QName, Arc<AttributeDecl>>,
5997) -> Result<(), SchemaCompileError> {
5998 let check_refs = |refs: &[QName], owner: &str| -> Result<(), SchemaCompileError> {
5999 for ref_qn in refs {
6000 if attr_groups.contains_key(ref_qn) { continue; }
6007 let collision = if types.contains_key(ref_qn) {
6008 Some("a type")
6009 } else if elements.contains_key(ref_qn) {
6010 Some("an element")
6011 } else if attributes.contains_key(ref_qn) {
6012 Some("an attribute")
6013 } else {
6014 None
6015 };
6016 if let Some(kind) = collision {
6017 return Err(SchemaCompileError::msg(format!(
6018 "<xs:attributeGroup ref={:?}> in {owner} resolves to {kind}, \
6019 not an attributeGroup",
6020 ref_qn.local,
6021 )));
6022 }
6023 }
6024 Ok(())
6025 };
6026 for (name, tr) in types {
6027 if let TypeRef::Complex(ct) = tr {
6028 check_refs(&ct.pending_attribute_group_refs, &format!("complex type {:?}", name.local))?;
6029 }
6030 }
6031 for (name, decl) in elements {
6032 if let TypeRef::Complex(ct) = &decl.type_def {
6033 check_refs(&ct.pending_attribute_group_refs, &format!("element {:?}", name.local))?;
6034 }
6035 }
6036 Ok(())
6037}
6038
6039fn check_element_value_constraints(
6040 types: &HashMap<QName, TypeRef>,
6041 elements: &HashMap<QName, Arc<ElementDecl>>,
6042) -> Result<(), SchemaCompileError> {
6043 for decl in elements.values() {
6044 let Some(v) = decl.default.as_deref().or(decl.fixed.as_deref()) else { continue };
6045 let resolved: Option<TypeRef> = match &decl.type_def {
6048 TypeRef::Complex(_) => Some(decl.type_def.clone()),
6049 TypeRef::Simple(_) => match resolve_typeref_to_qname(&decl.type_def) {
6050 Some(qn) => types.get(&qn).cloned().or_else(|| Some(decl.type_def.clone())),
6051 None => Some(decl.type_def.clone()),
6052 },
6053 };
6054 let Some(resolved) = resolved else { continue };
6055 let allowed = match &resolved {
6056 TypeRef::Simple(_) => true,
6057 TypeRef::Complex(ct) => match &ct.content {
6058 ContentModel::Simple(_) => true,
6059 ContentModel::Complex { mixed, .. } => *mixed,
6060 ContentModel::Empty => false,
6061 },
6062 };
6063 if !allowed {
6064 return Err(SchemaCompileError::msg(format!(
6065 "<xs:element name={:?}> with element-only or empty content cannot \
6066 have a default/fixed value of {v:?} (XSD §3.3.3)",
6067 decl.name.local,
6068 )));
6069 }
6070 let simple = match &resolved {
6074 TypeRef::Simple(st) => Some(st.clone()),
6075 TypeRef::Complex(ct) => match &ct.content {
6076 ContentModel::Simple(st) => Some(st.clone()),
6077 _ => None,
6078 },
6079 };
6080 if let Some(st) = simple {
6081 if let Err(e) = st.validate(v) {
6082 return Err(SchemaCompileError::msg(format!(
6083 "<xs:element name={:?}> default/fixed value {v:?} is not \
6084 valid for its type: {}",
6085 decl.name.local, e.message,
6086 )));
6087 }
6088 }
6089 }
6090 Ok(())
6091}
6092
6093fn check_keyref_refer(
6094 elements: &HashMap<QName, Arc<ElementDecl>>,
6095) -> Result<(), SchemaCompileError> {
6096 use super::identity::ConstraintKind;
6097 fn walk_particle(p: &super::schema::Particle, visit: &mut dyn FnMut(&ElementDecl)) {
6100 match &p.term {
6101 super::schema::Term::Element(decl) => {
6102 visit(decl);
6103 if let TypeRef::Complex(ct) = &decl.type_def {
6104 if let super::schema::ContentModel::Complex { root, .. } = &ct.content {
6105 walk_particle(root, visit);
6106 }
6107 }
6108 }
6109 super::schema::Term::Group { particles, .. } => {
6110 for p in particles.iter() { walk_particle(p, visit); }
6111 }
6112 _ => {}
6113 }
6114 }
6115 fn for_every_decl(
6116 elements: &HashMap<QName, Arc<ElementDecl>>,
6117 mut visit: impl FnMut(&ElementDecl),
6118 ) {
6119 for top in elements.values() {
6120 visit(top);
6121 if let TypeRef::Complex(ct) = &top.type_def {
6122 if let super::schema::ContentModel::Complex { root, .. } = &ct.content {
6123 walk_particle(root, &mut visit);
6124 }
6125 }
6126 }
6127 }
6128
6129 let mut keys: HashMap<QName, usize> = HashMap::new();
6132 for_every_decl(elements, |decl| {
6133 for ic in &decl.identity {
6134 if matches!(ic.kind, ConstraintKind::Key | ConstraintKind::Unique) {
6135 keys.insert(ic.name.clone(), ic.fields.len());
6136 }
6137 }
6138 });
6139 let mut dangling: Option<(QName, QName, usize, Option<usize>)> = None;
6143 for_every_decl(elements, |decl| {
6144 if dangling.is_some() { return; }
6145 for ic in &decl.identity {
6146 if !matches!(ic.kind, ConstraintKind::KeyRef) { continue; }
6147 let Some(refer) = ic.refer.as_ref() else { continue };
6148 match keys.get(refer) {
6149 None => {
6150 dangling = Some((ic.name.clone(), refer.clone(), ic.fields.len(), None));
6151 return;
6152 }
6153 Some(&refer_fields) if ic.fields.len() != refer_fields => {
6154 dangling = Some((ic.name.clone(), refer.clone(), ic.fields.len(),
6155 Some(refer_fields)));
6156 return;
6157 }
6158 _ => {}
6159 }
6160 }
6161 });
6162 if let Some((name, refer, df, rf)) = dangling {
6163 return match rf {
6164 None => Err(SchemaCompileError::msg(format!(
6165 "<xs:keyref name={:?} refer={:?}>: \
6166 the referenced key/unique is not declared",
6167 name.local, refer.local,
6168 ))),
6169 Some(rf) => Err(SchemaCompileError::msg(format!(
6170 "<xs:keyref name={:?} refer={:?}>: declares {df} \
6171 <xs:field> child(ren), but the referenced key has {rf}",
6172 name.local, refer.local,
6173 ))),
6174 };
6175 }
6176 Ok(())
6177}
6178
6179fn check_attribute_type_kinds(
6180 types: &HashMap<QName, TypeRef>,
6181 attributes: &HashMap<QName, Arc<AttributeDecl>>,
6182 elements: &HashMap<QName, Arc<ElementDecl>>,
6183) -> Result<(), SchemaCompileError> {
6184 fn check_one(
6185 decl: &AttributeDecl,
6186 types: &HashMap<QName, TypeRef>,
6187 ) -> Result<(), SchemaCompileError> {
6188 let resolved_type: Arc<SimpleType> =
6189 if let Some(qn) = resolve_typeref_to_qname(&TypeRef::Simple(decl.type_def.clone())) {
6190 match types.get(&qn) {
6191 Some(TypeRef::Complex(_)) => return Err(SchemaCompileError::msg(format!(
6192 "<xs:attribute name={:?} type={:?}> — attribute type must be a simple type, not a complex type",
6193 decl.name.local, qn.local,
6194 ))),
6195 Some(TypeRef::Simple(real)) => real.clone(),
6196 None => decl.type_def.clone(),
6197 }
6198 } else {
6199 decl.type_def.clone()
6200 };
6201 if matches!(resolved_type.builtin, super::types::BuiltinType::Id)
6206 && (decl.default.is_some() || decl.fixed.is_some())
6207 {
6208 return Err(SchemaCompileError::msg(format!(
6209 "<xs:attribute name={:?}> of type xs:ID cannot have a default or fixed value",
6210 decl.name.local,
6211 )));
6212 }
6213 for (label, raw) in [
6216 ("default", decl.default.as_deref()),
6217 ("fixed", decl.fixed.as_deref()),
6218 ] {
6219 let Some(raw) = raw else { continue };
6220 if let Err(e) = resolved_type.validate(raw) {
6221 return Err(SchemaCompileError::msg(format!(
6222 "<xs:attribute name={:?} {label}={raw:?}> is not valid for its type: {}",
6223 decl.name.local, e.message,
6224 )));
6225 }
6226 }
6227 Ok(())
6228 }
6229 fn walk_complex(
6230 ct: &ComplexType,
6231 types: &HashMap<QName, TypeRef>,
6232 visited: &mut std::collections::HashSet<*const ComplexType>,
6233 ) -> Result<(), SchemaCompileError> {
6234 if !visited.insert(ct as *const _) {
6235 return Ok(());
6236 }
6237 for au in &ct.attributes {
6238 check_one(&au.decl, types)?;
6239 }
6240 if let ContentModel::Complex { root, .. } = &ct.content {
6241 walk_particle(root, types, visited)?;
6242 }
6243 Ok(())
6244 }
6245 fn walk_particle(
6246 p: &super::schema::Particle,
6247 types: &HashMap<QName, TypeRef>,
6248 visited: &mut std::collections::HashSet<*const ComplexType>,
6249 ) -> Result<(), SchemaCompileError> {
6250 use super::schema::Term;
6251 match &p.term {
6252 Term::Element(e) => {
6253 if let TypeRef::Complex(ct) = &e.type_def {
6254 walk_complex(ct, types, visited)?;
6255 }
6256 }
6257 Term::Group { particles, .. } => {
6258 for child in particles.iter() {
6259 walk_particle(child, types, visited)?;
6260 }
6261 }
6262 Term::Wildcard(_) | Term::GroupRef(_) => {}
6263 }
6264 Ok(())
6265 }
6266
6267 for decl in attributes.values() {
6268 check_one(decl, types)?;
6269 }
6270 let mut visited: std::collections::HashSet<*const ComplexType> = std::collections::HashSet::new();
6271 for ct in types.values().filter_map(|t| match t {
6272 TypeRef::Complex(c) => Some(c),
6273 _ => None,
6274 }) {
6275 walk_complex(ct, types, &mut visited)?;
6276 }
6277 for decl in elements.values() {
6278 if let TypeRef::Complex(ct) = &decl.type_def {
6279 walk_complex(ct, types, &mut visited)?;
6280 }
6281 }
6282 Ok(())
6283}
6284
6285fn resolve_typeref_to_qname(tr: &TypeRef) -> Option<QName> {
6286 if let TypeRef::Simple(st) = tr {
6287 if let Some(name) = &st.name {
6288 if let Some(rest) = name.strip_prefix("UNRESOLVED:") {
6289 if let Some(rest) = rest.strip_prefix('{') {
6292 if let Some(end) = rest.find('}') {
6293 let ns = &rest[..end];
6294 let local = &rest[end + 1..];
6295 return Some(QName::new(
6296 if ns.is_empty() { None } else { Some(ns) },
6297 local,
6298 ));
6299 }
6300 }
6301 return Some(QName::new(None, rest));
6302 }
6303 }
6304 }
6305 None
6306}
6307
6308fn merge_any_intersect(
6322 acc: Option<super::schema::Wildcard>,
6323 new: Option<super::schema::Wildcard>,
6324) -> Option<super::schema::Wildcard> {
6325 match (acc, new) {
6326 (None, x) | (x, None) => x,
6327 (Some(a), Some(b)) => intersect_wildcards(&a, &b),
6328 }
6329}
6330
6331fn intersect_wildcards(
6343 a: &super::schema::Wildcard, b: &super::schema::Wildcard,
6344) -> Option<super::schema::Wildcard> {
6345 use super::schema::{NamespaceConstraint, Wildcard};
6346 let namespaces = match (&a.namespaces, &b.namespaces) {
6347 (NamespaceConstraint::Any, x) | (x, NamespaceConstraint::Any) => x.clone(),
6348 (NamespaceConstraint::List(la), NamespaceConstraint::List(lb)) => {
6349 let common: Vec<Option<Arc<str>>> = la.iter()
6350 .filter(|x| lb.contains(x))
6351 .cloned()
6352 .collect();
6353 if common.is_empty() {
6354 NamespaceConstraint::List(Vec::new())
6357 } else {
6358 NamespaceConstraint::List(common)
6359 }
6360 }
6361 (NamespaceConstraint::Other, NamespaceConstraint::List(lb))
6362 | (NamespaceConstraint::List(lb), NamespaceConstraint::Other) => {
6363 let kept: Vec<Option<Arc<str>>> = lb.iter()
6369 .filter(|x| x.is_some())
6370 .cloned()
6371 .collect();
6372 NamespaceConstraint::List(kept)
6373 }
6374 (NamespaceConstraint::Other, NamespaceConstraint::Other) => {
6375 NamespaceConstraint::Other
6376 }
6377 };
6378 let process_contents = match (a.process_contents, b.process_contents) {
6381 (x, y) if x == y => x,
6382 (super::schema::ProcessContents::Strict, _)
6383 | (_, super::schema::ProcessContents::Strict) =>
6384 super::schema::ProcessContents::Strict,
6385 (super::schema::ProcessContents::Lax, _)
6386 | (_, super::schema::ProcessContents::Lax) =>
6387 super::schema::ProcessContents::Lax,
6388 _ => super::schema::ProcessContents::Skip,
6389 };
6390 Some(Wildcard {
6391 namespaces,
6392 process_contents,
6393 not_qnames: a.not_qnames.iter().chain(&b.not_qnames).cloned().collect(),
6394 not_namespaces: a.not_namespaces.iter().chain(&b.not_namespaces).cloned().collect(),
6395 not_qname_defined: a.not_qname_defined || b.not_qname_defined,
6396 not_qname_defined_sibling: a.not_qname_defined_sibling || b.not_qname_defined_sibling,
6397 })
6398}
6399
6400fn union_wildcards(a: &super::schema::Wildcard, b: &super::schema::Wildcard)
6401 -> super::schema::Wildcard
6402{
6403 use super::schema::{NamespaceConstraint, Wildcard};
6404 let namespaces = match (&a.namespaces, &b.namespaces) {
6405 (NamespaceConstraint::Any, _) | (_, NamespaceConstraint::Any) => NamespaceConstraint::Any,
6406 (NamespaceConstraint::Other, NamespaceConstraint::List(l))
6411 | (NamespaceConstraint::List(l), NamespaceConstraint::Other)
6412 if l.iter().any(|e| e.is_none()) =>
6413 NamespaceConstraint::Any,
6414 (NamespaceConstraint::Other, _) | (_, NamespaceConstraint::Other) => NamespaceConstraint::Other,
6415 (NamespaceConstraint::List(la), NamespaceConstraint::List(lb)) => {
6416 let mut combined: Vec<Option<Arc<str>>> = la.clone();
6417 for item in lb {
6418 if !combined.iter().any(|existing| existing == item) {
6419 combined.push(item.clone());
6420 }
6421 }
6422 NamespaceConstraint::List(combined)
6423 }
6424 };
6425 Wildcard {
6431 namespaces,
6432 process_contents: b.process_contents,
6433 not_qnames: b.not_qnames.clone(),
6434 not_namespaces: b.not_namespaces.clone(),
6435 not_qname_defined: b.not_qname_defined,
6436 not_qname_defined_sibling: b.not_qname_defined_sibling,
6437 }
6438}
6439
6440fn compose_extension(base: &ComplexType, derived: &ComplexType) -> ComplexType {
6443 use super::schema::{MaxOccurs, Term};
6444 let merged_content = match (&base.content, &derived.content) {
6445 (ContentModel::Empty, c) => c.clone(),
6446 (b, ContentModel::Empty) => b.clone(),
6447 (
6448 ContentModel::Complex { root: b_root, mixed: b_mixed },
6449 ContentModel::Complex { root: d_root, mixed: d_mixed },
6450 ) => ContentModel::Complex {
6451 root: Particle {
6452 min_occurs: 1,
6453 max_occurs: MaxOccurs::Bounded(1),
6454 term: Term::Group {
6455 kind: GroupKind::Sequence,
6456 particles: Arc::from(vec![b_root.clone(), d_root.clone()]),
6457 },
6458 },
6459 mixed: *b_mixed || *d_mixed,
6460 },
6461 (ContentModel::Simple(_), c) => c.clone(),
6466 (_, c) => c.clone(),
6467 };
6468
6469 let mut attrs: Vec<super::schema::AttributeUse> = base.attributes.clone();
6471 for d_au in &derived.attributes {
6472 let same_name = attrs.iter().position(|a| a.decl.name == d_au.decl.name);
6473 match same_name {
6474 Some(idx) => attrs[idx] = d_au.clone(),
6475 None => attrs.push(d_au.clone()),
6476 }
6477 }
6478
6479 let any_attribute = match (&base.any_attribute, &derived.any_attribute) {
6483 (Some(b), Some(d)) => Some(union_wildcards(b, d)),
6484 (Some(w), None) | (None, Some(w)) => Some(w.clone()),
6485 (None, None) => None,
6486 };
6487
6488 ComplexType {
6489 name: derived.name.clone(),
6490 derivation: derived.derivation.clone(),
6491 content: merged_content,
6492 matcher: std::sync::OnceLock::new(),
6493 attributes: attrs,
6494 any_attribute,
6495 abstract_: derived.abstract_,
6496 block: derived.block,
6497 final_: derived.final_,
6498 pending_attribute_group_refs: Vec::new(),
6499 assertions: derived.assertions.clone(),
6505 }
6506}
6507
6508fn flatten_nested_attribute_group_refs(
6541 groups: &mut HashMap<QName, Arc<AttributeGroup>>,
6542 refs_by_owner: &HashMap<QName, Vec<QName>>,
6543) {
6544 let max_rounds = groups.len() + 1;
6545 for _ in 0..max_rounds {
6546 let mut changed = false;
6547 let names: Vec<QName> = groups.keys().cloned().collect();
6548 for name in names {
6549 let Some(refs) = refs_by_owner.get(&name) else { continue };
6550 if refs.is_empty() { continue; }
6551 let Some(current) = groups.get(&name).cloned() else { continue };
6552 let mut attrs = current.attributes.clone();
6553 let mut any = current.any.clone();
6554 let mut grew = false;
6555 for ref_qn in refs {
6556 let Some(target) = groups.get(ref_qn) else { continue };
6557 for au in &target.attributes {
6558 let already = attrs.iter().any(|existing|
6563 existing.decl.name == au.decl.name
6564 && existing.use_kind == au.use_kind);
6565 if !already {
6566 attrs.push(au.clone());
6567 grew = true;
6568 }
6569 }
6570 any = merge_any_intersect(any, target.any.clone());
6571 }
6572 if grew {
6573 let new_ag = AttributeGroup {
6574 name: current.name.clone(),
6575 attributes: attrs,
6576 any,
6577 };
6578 groups.insert(name, Arc::new(new_ag));
6579 changed = true;
6580 }
6581 }
6582 if !changed { break; }
6583 }
6584}
6585
6586fn resolve_attribute_group_refs(
6587 types: &mut HashMap<QName, TypeRef>,
6588 elements: &mut HashMap<QName, Arc<ElementDecl>>,
6589 groups: &HashMap<QName, Arc<AttributeGroup>>,
6590) -> Result<(), SchemaCompileError> {
6591 let names: Vec<QName> = types.keys().cloned().collect();
6592 for name in names {
6593 if let Some(TypeRef::Complex(ct)) = types.get(&name) {
6594 let rewritten = rewrite_complex_for_ag_refs(ct, groups);
6595 types.insert(name, TypeRef::Complex(Arc::new(rewritten)));
6596 }
6597 }
6598
6599 let elem_names: Vec<QName> = elements.keys().cloned().collect();
6600 for ename in elem_names {
6601 if let Some(decl) = elements.get(&ename) {
6602 if let TypeRef::Complex(ct) = &decl.type_def {
6603 let rewritten = rewrite_complex_for_ag_refs(ct, groups);
6604 let new_decl = Arc::new(ElementDecl {
6605 name: decl.name.clone(),
6606 type_def: TypeRef::Complex(Arc::new(rewritten)),
6607 nillable: decl.nillable,
6608 default: decl.default.clone(),
6609 fixed: decl.fixed.clone(),
6610 abstract_: decl.abstract_,
6611 substitution_group: decl.substitution_group.clone(),
6612 block: decl.block,
6613 final_: decl.final_,
6614 identity: decl.identity.clone(),
6615 });
6616 elements.insert(ename, new_decl);
6617 }
6618 }
6619 }
6620 Ok(())
6621}
6622
6623fn rewrite_complex_for_ag_refs(
6627 ct: &ComplexType,
6628 groups: &HashMap<QName, Arc<AttributeGroup>>,
6629) -> ComplexType {
6630 let mut attributes = ct.attributes.clone();
6631 let mut any_attribute = ct.any_attribute.clone();
6632 for ref_qn in &ct.pending_attribute_group_refs {
6633 if let Some(ag) = groups.get(ref_qn) {
6634 for au in &ag.attributes {
6635 attributes.push(au.clone());
6636 }
6637 any_attribute = merge_any_intersect(any_attribute, ag.any.clone());
6640 }
6641 }
6642 let new_content = match &ct.content {
6643 ContentModel::Complex { root, mixed } => {
6644 ContentModel::Complex {
6645 root: rewrite_particle_for_ag_refs(root.clone(), groups),
6646 mixed: *mixed,
6647 }
6648 }
6649 other => other.clone(),
6650 };
6651 let new_derivation = ct.derivation.as_ref().map(|d| {
6656 let new_base = match &d.base {
6657 TypeRef::Complex(c) => TypeRef::Complex(Arc::new(rewrite_complex_for_ag_refs(c, groups))),
6658 other => other.clone(),
6659 };
6660 super::types::Derivation { method: d.method, base: new_base }
6661 });
6662 ComplexType {
6663 name: ct.name.clone(),
6664 derivation: new_derivation,
6665 content: new_content,
6666 matcher: std::sync::OnceLock::new(),
6667 attributes,
6668 any_attribute,
6669 abstract_: ct.abstract_,
6670 block: ct.block,
6671 final_: ct.final_,
6672 pending_attribute_group_refs: Vec::new(),
6673 assertions: ct.assertions.clone(),
6674 }
6675}
6676
6677fn rewrite_particle_for_ag_refs(
6678 p: Particle,
6679 groups: &HashMap<QName, Arc<AttributeGroup>>,
6680) -> Particle {
6681 let term = match p.term {
6682 Term::Element(decl) => {
6683 let new_decl = if let TypeRef::Complex(ct) = &decl.type_def {
6687 let new_ct = rewrite_complex_for_ag_refs(ct, groups);
6688 Arc::new(ElementDecl {
6689 name: decl.name.clone(),
6690 type_def: TypeRef::Complex(Arc::new(new_ct)),
6691 nillable: decl.nillable,
6692 default: decl.default.clone(),
6693 fixed: decl.fixed.clone(),
6694 abstract_: decl.abstract_,
6695 substitution_group: decl.substitution_group.clone(),
6696 block: decl.block,
6697 final_: decl.final_,
6698 identity: decl.identity.clone(),
6699 })
6700 } else {
6701 decl
6702 };
6703 Term::Element(new_decl)
6704 }
6705 Term::Group { kind, particles } => {
6706 let new_particles: Vec<Particle> = particles.iter()
6707 .cloned()
6708 .map(|p| rewrite_particle_for_ag_refs(p, groups))
6709 .collect();
6710 Term::Group { kind, particles: Arc::from(new_particles) }
6711 }
6712 other => other,
6713 };
6714 Particle { min_occurs: p.min_occurs, max_occurs: p.max_occurs, term }
6715}
6716
6717fn check_model_group_cycles(
6731 groups: &HashMap<QName, Arc<ModelGroup>>,
6732 redefined_groups: &HashSet<QName>,
6733) -> Result<(), SchemaCompileError> {
6734 fn walk(
6735 p: &Particle,
6736 groups: &HashMap<QName, Arc<ModelGroup>>,
6737 active: &mut Vec<QName>,
6738 redefined: &HashSet<QName>,
6739 ) -> Result<(), SchemaCompileError> {
6740 match &p.term {
6741 Term::GroupRef(name) => {
6742 if active.contains(name) {
6743 return Err(SchemaCompileError::msg(format!(
6744 "<xs:group name={:?}>: model-group definition is circular \
6745 — references itself without an intervening element \
6746 declaration (XSD §3.8.6 src-model-group)",
6747 name.local,
6748 )));
6749 }
6750 let Some(g) = groups.get(name) else { return Ok(()); };
6751 active.push(name.clone());
6752 walk(&g.particle, groups, active, redefined)?;
6753 active.pop();
6754 }
6755 Term::Group { particles, .. } => {
6756 for p in particles.iter() { walk(p, groups, active, redefined)?; }
6757 }
6758 Term::Element(_) | Term::Wildcard(_) => {}
6762 }
6763 Ok(())
6764 }
6765 for (name, g) in groups {
6766 if redefined_groups.contains(name) { continue; }
6770 let mut active = vec![name.clone()];
6771 walk(&g.particle, groups, &mut active, redefined_groups)?;
6772 }
6773 Ok(())
6774}
6775
6776fn resolve_group_refs(
6777 types: &mut HashMap<QName, TypeRef>,
6778 elements: &mut HashMap<QName, Arc<ElementDecl>>,
6779 groups: &HashMap<QName, Arc<ModelGroup>>,
6780) -> Result<(), SchemaCompileError> {
6781 let names: Vec<QName> = types.keys().cloned().collect();
6782 for name in names {
6783 if let Some(TypeRef::Complex(ct)) = types.get(&name) {
6784 if !content_has_group_ref(&ct.content) { continue; }
6785 let new_content = expand_group_refs_in_content(&ct.content, groups, 0)?;
6786 let new_ct = ComplexType {
6787 name: ct.name.clone(),
6788 derivation: ct.derivation.clone(),
6789 content: new_content,
6790 matcher: std::sync::OnceLock::new(),
6791 attributes: ct.attributes.clone(),
6792 any_attribute: ct.any_attribute.clone(),
6793 abstract_: ct.abstract_,
6794 block: ct.block,
6795 final_: ct.final_,
6796 pending_attribute_group_refs: ct.pending_attribute_group_refs.clone(),
6797 assertions: ct.assertions.clone(),
6798 };
6799 types.insert(name, TypeRef::Complex(Arc::new(new_ct)));
6800 }
6801 }
6802
6803 let elem_names: Vec<QName> = elements.keys().cloned().collect();
6804 for ename in elem_names {
6805 if let Some(decl) = elements.get(&ename) {
6806 if let TypeRef::Complex(ct) = &decl.type_def {
6807 if !content_has_group_ref(&ct.content) { continue; }
6808 let new_content = expand_group_refs_in_content(&ct.content, groups, 0)?;
6809 let new_ct = ComplexType {
6810 name: ct.name.clone(),
6811 derivation: ct.derivation.clone(),
6812 content: new_content,
6813 matcher: std::sync::OnceLock::new(),
6814 attributes: ct.attributes.clone(),
6815 any_attribute: ct.any_attribute.clone(),
6816 abstract_: ct.abstract_,
6817 block: ct.block,
6818 final_: ct.final_,
6819 pending_attribute_group_refs: ct.pending_attribute_group_refs.clone(),
6820 assertions: ct.assertions.clone(),
6821 };
6822 let new_decl = Arc::new(ElementDecl {
6823 name: decl.name.clone(),
6824 type_def: TypeRef::Complex(Arc::new(new_ct)),
6825 nillable: decl.nillable,
6826 default: decl.default.clone(),
6827 fixed: decl.fixed.clone(),
6828 abstract_: decl.abstract_,
6829 substitution_group: decl.substitution_group.clone(),
6830 block: decl.block,
6831 final_: decl.final_,
6832 identity: decl.identity.clone(),
6833 });
6834 elements.insert(ename, new_decl);
6835 }
6836 }
6837 }
6838 Ok(())
6839}
6840
6841fn content_has_group_ref(c: &ContentModel) -> bool {
6842 match c {
6843 ContentModel::Complex { root, .. } => particle_has_group_ref(root),
6844 _ => false,
6845 }
6846}
6847
6848fn particle_has_group_ref(p: &Particle) -> bool {
6849 match &p.term {
6850 Term::GroupRef(_) => true,
6851 Term::Group { particles, .. } => particles.iter().any(particle_has_group_ref),
6852 _ => false,
6853 }
6854}
6855
6856const MAX_GROUP_DEPTH: usize = 64;
6857
6858fn expand_group_refs_in_content(
6859 c: &ContentModel,
6860 groups: &HashMap<QName, Arc<ModelGroup>>,
6861 depth: usize,
6862) -> Result<ContentModel, SchemaCompileError> {
6863 expand_group_refs_in_content_inner(c, groups, depth, &mut HashSet::new())
6864}
6865
6866fn expand_group_refs_in_content_inner(
6867 c: &ContentModel,
6868 groups: &HashMap<QName, Arc<ModelGroup>>,
6869 depth: usize,
6870 active: &mut HashSet<QName>,
6871) -> Result<ContentModel, SchemaCompileError> {
6872 match c {
6873 ContentModel::Complex { root, mixed } => {
6874 let root = expand_group_refs_in_particle_inner(
6875 root.clone(), groups, depth, active,
6876 )?;
6877 Ok(ContentModel::Complex { root, mixed: *mixed })
6878 }
6879 other => Ok(other.clone()),
6880 }
6881}
6882
6883#[allow(dead_code)]
6884fn expand_group_refs_in_particle(
6885 p: Particle,
6886 groups: &HashMap<QName, Arc<ModelGroup>>,
6887 depth: usize,
6888) -> Result<Particle, SchemaCompileError> {
6889 expand_group_refs_in_particle_inner(p, groups, depth, &mut HashSet::new())
6890}
6891
6892fn expand_group_refs_in_particle_inner(
6900 p: Particle,
6901 groups: &HashMap<QName, Arc<ModelGroup>>,
6902 depth: usize,
6903 active: &mut HashSet<QName>,
6904) -> Result<Particle, SchemaCompileError> {
6905 if depth > MAX_GROUP_DEPTH {
6906 return Err(SchemaCompileError::msg(
6907 "model group reference chain exceeds depth limit (cycle?)"
6908 ));
6909 }
6910 let term = match p.term {
6911 Term::GroupRef(ref name) => {
6912 if active.contains(name) {
6913 return Ok(Particle {
6917 min_occurs: p.min_occurs,
6918 max_occurs: p.max_occurs,
6919 term: Term::GroupRef(name.clone()),
6920 });
6921 }
6922 let g = groups.get(name).ok_or_else(|| SchemaCompileError::msg(
6923 format!("<xs:group ref={name}> refers to an undeclared group")
6924 ))?;
6925 if matches!(g.particle.term, Term::Group { kind: GroupKind::All, .. })
6929 && (p.min_occurs > 1 || p.max_occurs != MaxOccurs::Bounded(1))
6930 {
6931 return Err(SchemaCompileError::msg(format!(
6932 "<xs:group ref={name}>: a reference to an <xs:all> group must \
6933 have minOccurs ∈ {{0,1}} and maxOccurs=1 (XSD §3.7.6 cos-all-limited)"
6934 )));
6935 }
6936 active.insert(name.clone());
6937 let expanded = expand_group_refs_in_particle_inner(
6938 g.particle.clone(), groups, depth + 1, active,
6939 )?;
6940 active.remove(name);
6941 expanded.term
6942 }
6943 Term::Group { kind, particles } => {
6944 let new_particles: Vec<Particle> = particles.iter()
6945 .cloned()
6946 .map(|p| expand_group_refs_in_particle_inner(p, groups, depth + 1, active))
6947 .collect::<Result<_, _>>()?;
6948 Term::Group { kind, particles: Arc::from(new_particles) }
6949 }
6950 Term::Element(decl) => {
6951 Term::Element(expand_group_refs_in_element_decl_inner(
6957 decl, groups, depth + 1, active,
6958 )?)
6959 }
6960 other => other,
6961 };
6962 Ok(Particle { min_occurs: p.min_occurs, max_occurs: p.max_occurs, term })
6963}
6964
6965#[allow(dead_code)]
6970fn expand_group_refs_in_element_decl(
6971 decl: Arc<ElementDecl>,
6972 groups: &HashMap<QName, Arc<ModelGroup>>,
6973 depth: usize,
6974) -> Result<Arc<ElementDecl>, SchemaCompileError> {
6975 expand_group_refs_in_element_decl_inner(decl, groups, depth, &mut HashSet::new())
6976}
6977
6978fn expand_group_refs_in_element_decl_inner(
6979 decl: Arc<ElementDecl>,
6980 groups: &HashMap<QName, Arc<ModelGroup>>,
6981 depth: usize,
6982 active: &mut HashSet<QName>,
6983) -> Result<Arc<ElementDecl>, SchemaCompileError> {
6984 let TypeRef::Complex(ct) = &decl.type_def else { return Ok(decl); };
6985 if !content_has_group_ref(&ct.content) { return Ok(decl); }
6986 let new_content = expand_group_refs_in_content_inner(&ct.content, groups, depth, active)?;
6987 let new_ct = ComplexType {
6988 name: ct.name.clone(),
6989 derivation: ct.derivation.clone(),
6990 content: new_content,
6991 matcher: std::sync::OnceLock::new(),
6992 attributes: ct.attributes.clone(),
6993 any_attribute: ct.any_attribute.clone(),
6994 abstract_: ct.abstract_,
6995 block: ct.block,
6996 final_: ct.final_,
6997 pending_attribute_group_refs: ct.pending_attribute_group_refs.clone(),
6998 assertions: ct.assertions.clone(),
6999 };
7000 Ok(Arc::new(ElementDecl {
7001 name: decl.name.clone(),
7002 type_def: TypeRef::Complex(Arc::new(new_ct)),
7003 nillable: decl.nillable,
7004 default: decl.default.clone(),
7005 fixed: decl.fixed.clone(),
7006 abstract_: decl.abstract_,
7007 substitution_group: decl.substitution_group.clone(),
7008 block: decl.block,
7009 final_: decl.final_,
7010 identity: decl.identity.clone(),
7011 }))
7012}
7013
7014fn resolve_element_refs(
7015 types: &mut HashMap<QName, TypeRef>,
7016 elements: &mut HashMap<QName, Arc<ElementDecl>>,
7017) {
7018 let snapshot: HashMap<QName, Arc<ElementDecl>> = elements.clone();
7021
7022 let names: Vec<QName> = types.keys().cloned().collect();
7023 for name in names {
7024 let needs_rewrite = match types.get(&name) {
7025 Some(TypeRef::Complex(ct)) => match &ct.content {
7026 ContentModel::Complex { root, .. } => particle_has_unresolved_ref(root, &snapshot),
7027 _ => false,
7028 },
7029 _ => false,
7030 };
7031 if !needs_rewrite { continue; }
7032 if let Some(TypeRef::Complex(ct)) = types.get(&name) {
7033 types.insert(name, TypeRef::Complex(Arc::new(rewrite_complex_type(ct, &snapshot))));
7034 }
7035 }
7036
7037 let elem_names: Vec<QName> = elements.keys().cloned().collect();
7040 for ename in elem_names {
7041 let needs_rewrite = match elements.get(&ename) {
7042 Some(decl) => match &decl.type_def {
7043 TypeRef::Complex(ct) => match &ct.content {
7044 ContentModel::Complex { root, .. } => particle_has_unresolved_ref(root, &snapshot),
7045 _ => false,
7046 },
7047 _ => false,
7048 },
7049 None => false,
7050 };
7051 if !needs_rewrite { continue; }
7052 if let Some(decl) = elements.get(&ename) {
7053 if let TypeRef::Complex(ct) = &decl.type_def {
7054 let new_ct = rewrite_complex_type(ct, &snapshot);
7055 let new_decl = Arc::new(ElementDecl {
7056 name: decl.name.clone(),
7057 type_def: TypeRef::Complex(Arc::new(new_ct)),
7058 nillable: decl.nillable,
7059 default: decl.default.clone(),
7060 fixed: decl.fixed.clone(),
7061 abstract_: decl.abstract_,
7062 substitution_group: decl.substitution_group.clone(),
7063 block: decl.block,
7064 final_: decl.final_,
7065 identity: decl.identity.clone(),
7066 });
7067 elements.insert(ename, new_decl);
7068 }
7069 }
7070 }
7071}
7072
7073fn rewrite_complex_type(
7079 ct: &ComplexType,
7080 elements: &HashMap<QName, Arc<ElementDecl>>,
7081) -> ComplexType {
7082 let new_content = match &ct.content {
7083 ContentModel::Complex { root, mixed } => {
7084 let rewritten = rewrite_particle_refs(root.clone(), elements);
7085 ContentModel::Complex { root: rewritten, mixed: *mixed }
7086 }
7087 other => other.clone(),
7088 };
7089 ComplexType {
7090 name: ct.name.clone(),
7091 derivation: ct.derivation.clone(),
7092 content: new_content,
7093 matcher: std::sync::OnceLock::new(),
7094 attributes: ct.attributes.clone(),
7095 any_attribute: ct.any_attribute.clone(),
7096 abstract_: ct.abstract_,
7097 block: ct.block,
7098 final_: ct.final_,
7099 pending_attribute_group_refs: ct.pending_attribute_group_refs.clone(),
7100 assertions: ct.assertions.clone(),
7101 }
7102}
7103
7104fn particle_has_unresolved_ref(
7105 p: &Particle,
7106 elements: &HashMap<QName, Arc<ElementDecl>>,
7107) -> bool {
7108 match &p.term {
7109 Term::Element(decl) => {
7110 elements.get(&decl.name)
7115 .map(|real| !Arc::ptr_eq(real, decl))
7116 .unwrap_or(false)
7117 }
7118 Term::Group { particles, .. } => {
7119 particles.iter().any(|p| particle_has_unresolved_ref(p, elements))
7120 }
7121 Term::Wildcard(_) => false,
7122 Term::GroupRef(_) => false,
7123 }
7124}
7125
7126fn rewrite_particle_refs(
7127 p: Particle,
7128 elements: &HashMap<QName, Arc<ElementDecl>>,
7129) -> Particle {
7130 let term = match p.term {
7131 Term::Element(decl) => {
7132 let real = elements.get(&decl.name).cloned().unwrap_or(decl);
7133 Term::Element(real)
7134 }
7135 Term::Group { kind, particles } => {
7136 let new_particles: Vec<Particle> = particles.iter()
7137 .cloned()
7138 .map(|p| rewrite_particle_refs(p, elements))
7139 .collect();
7140 Term::Group { kind, particles: Arc::from(new_particles) }
7141 }
7142 Term::Wildcard(w) => Term::Wildcard(w),
7143 Term::GroupRef(name) => Term::GroupRef(name),
7144 };
7145 Particle { min_occurs: p.min_occurs, max_occurs: p.max_occurs, term }
7146}
7147
7148fn walk_complex_for_matchers(
7152 ct: &Arc<ComplexType>,
7153 subs: &HashMap<QName, Vec<Arc<ElementDecl>>>,
7154 types: &HashMap<QName, TypeRef>,
7155 visited: &mut HashSet<usize>,
7156 target_ns: Option<&str>,
7157) -> Result<(), SchemaCompileError> {
7158 let ptr = Arc::as_ptr(ct) as usize;
7159 if !visited.insert(ptr) { return Ok(()); }
7160
7161 let matcher = super::dfa::build_matcher_with_target_ns(&ct.content, subs, types, target_ns)?;
7162 let _ = ct.matcher.set(matcher);
7163
7164 if let ContentModel::Complex { root, .. } = &ct.content {
7165 walk_particle_for_matchers(root, subs, types, visited, target_ns)?;
7166 }
7167 Ok(())
7168}
7169
7170fn walk_particle_for_matchers(
7171 p: &Particle,
7172 subs: &HashMap<QName, Vec<Arc<ElementDecl>>>,
7173 types: &HashMap<QName, TypeRef>,
7174 visited: &mut HashSet<usize>,
7175 target_ns: Option<&str>,
7176) -> Result<(), SchemaCompileError> {
7177 match &p.term {
7178 Term::Element(decl) => {
7179 if let TypeRef::Complex(ct) = &decl.type_def {
7180 walk_complex_for_matchers(ct, subs, types, visited, target_ns)?;
7181 }
7182 }
7183 Term::Group { particles, .. } => {
7184 for p in particles.iter() {
7185 walk_particle_for_matchers(p, subs, types, visited, target_ns)?;
7186 }
7187 }
7188 Term::Wildcard(_) => {}
7189 Term::GroupRef(_) => {
7190 }
7195 }
7196 Ok(())
7197}
7198
7199fn parse_max_occurs(s: Option<&str>) -> Result<MaxOccurs, SchemaCompileError> {
7200 match s {
7201 None => Ok(MaxOccurs::Bounded(1)),
7202 Some("unbounded") => Ok(MaxOccurs::Unbounded),
7203 Some(raw) => parse_occurs_int(raw, "maxOccurs").map(|n| match n {
7204 Some(n) => MaxOccurs::Bounded(n),
7209 None => MaxOccurs::Unbounded,
7210 }),
7211 }
7212}
7213
7214fn parse_min_occurs(s: Option<&str>) -> Result<u32, SchemaCompileError> {
7215 match s {
7216 None => Ok(1),
7217 Some(raw) => parse_occurs_int(raw, "minOccurs")?.ok_or_else(|| {
7218 SchemaCompileError::msg(format!(
7222 "minOccurs={raw:?} exceeds the maximum supported value"
7223 ))
7224 }),
7225 }
7226}
7227
7228fn parse_occurs_int(raw: &str, attr: &str) -> Result<Option<u32>, SchemaCompileError> {
7232 if raw.is_empty() || raw.bytes().any(|b| !b.is_ascii_digit()) {
7233 return Err(SchemaCompileError::msg(format!(
7234 "{attr}={raw:?} is not a non-negative integer or 'unbounded'"
7235 )));
7236 }
7237 match raw.parse::<u32>() {
7238 Ok(n) => Ok(Some(n)),
7239 Err(_) => Ok(None),
7240 }
7241}
7242
7243fn check_occurs(min: u32, max: MaxOccurs) -> Result<(), SchemaCompileError> {
7244 if let MaxOccurs::Bounded(m) = max {
7245 if min > m {
7246 return Err(SchemaCompileError::msg(format!(
7247 "minOccurs ({min}) > maxOccurs ({m})"
7248 )));
7249 }
7250 }
7251 Ok(())
7252}
7253
7254fn prune_replaced_bounds(facets: &mut FacetSet, base_count: usize) {
7262 let derived_has_min_incl = facets.facets[base_count..].iter()
7263 .any(|f| matches!(f, Facet::MinInclusive(_)));
7264 let derived_has_min_excl = facets.facets[base_count..].iter()
7265 .any(|f| matches!(f, Facet::MinExclusive(_)));
7266 let derived_has_max_incl = facets.facets[base_count..].iter()
7267 .any(|f| matches!(f, Facet::MaxInclusive(_)));
7268 let derived_has_max_excl = facets.facets[base_count..].iter()
7269 .any(|f| matches!(f, Facet::MaxExclusive(_)));
7270 let derived_has_length = facets.facets[base_count..].iter()
7271 .any(|f| matches!(f, Facet::Length(_)));
7272 let derived_has_minmax_length = facets.facets[base_count..].iter()
7273 .any(|f| matches!(f, Facet::MinLength(_) | Facet::MaxLength(_)));
7274
7275 let mut i = 0;
7276 facets.facets.retain(|f| {
7277 let inherited = i < base_count;
7278 i += 1;
7279 if !inherited { return true; }
7280 let drop = matches!(
7283 (f, derived_has_min_incl, derived_has_min_excl,
7284 derived_has_max_incl, derived_has_max_excl,
7285 derived_has_length, derived_has_minmax_length),
7286 (Facet::MinExclusive(_), true, _, _, _, _, _) |
7287 (Facet::MinInclusive(_), _, true, _, _, _, _) |
7288 (Facet::MaxExclusive(_), _, _, true, _, _, _) |
7289 (Facet::MaxInclusive(_), _, _, _, true, _, _) |
7290 (Facet::Length(_), _, _, _, _, _, true) |
7291 (Facet::MinLength(_), _, _, _, _, true, _) |
7292 (Facet::MaxLength(_), _, _, _, _, true, _)
7293 );
7294 !drop
7295 });
7296}
7297
7298fn parse_block_set(s: Option<&str>) -> Result<BlockSet, SchemaCompileError> {
7299 let Some(s) = s else { return Ok(BlockSet::default()); };
7300 if s == "#all" {
7301 return Ok(BlockSet::all());
7302 }
7303 let mut out = BlockSet::default();
7304 for tok in s.split_whitespace() {
7305 match tok {
7306 "restriction" => out |= BlockSet::RESTRICTION,
7307 "extension" => out |= BlockSet::EXTENSION,
7308 "substitution" => out |= BlockSet::SUBSTITUTION,
7309 "list" => out |= BlockSet::LIST,
7310 "union" => out |= BlockSet::UNION,
7311 other => return Err(SchemaCompileError::msg(format!(
7312 "block/final attribute: {other:?} is not a valid token \
7313 (expected 'restriction', 'extension', 'substitution', \
7314 'list', 'union', or '#all')"
7315 ))),
7316 }
7317 }
7318 Ok(out)
7319}
7320
7321fn parse_element_block_set(s: Option<&str>) -> Result<BlockSet, SchemaCompileError> {
7329 let Some(s) = s else { return Ok(BlockSet::default()); };
7330 if s == "#all" {
7331 return Ok(BlockSet::RESTRICTION | BlockSet::EXTENSION | BlockSet::SUBSTITUTION);
7332 }
7333 let mut out = BlockSet::default();
7334 for tok in s.split_whitespace() {
7335 match tok {
7336 "restriction" => out |= BlockSet::RESTRICTION,
7337 "extension" => out |= BlockSet::EXTENSION,
7338 "substitution" => out |= BlockSet::SUBSTITUTION,
7339 other => return Err(SchemaCompileError::msg(format!(
7340 "<xs:element block={s:?}>: {other:?} is not a valid value \
7341 (expected 'restriction', 'extension', 'substitution', or '#all')"
7342 ))),
7343 }
7344 }
7345 Ok(out)
7346}
7347
7348fn parse_ct_derivation_set(
7349 s: Option<&str>, attr: &str,
7350) -> Result<BlockSet, SchemaCompileError> {
7351 let Some(s) = s else { return Ok(BlockSet::default()); };
7352 if s == "#all" {
7353 return Ok(BlockSet::all());
7354 }
7355 let mut out = BlockSet::default();
7356 for tok in s.split_whitespace() {
7357 match tok {
7358 "restriction" => out |= BlockSet::RESTRICTION,
7359 "extension" => out |= BlockSet::EXTENSION,
7360 other => return Err(SchemaCompileError::msg(format!(
7361 "<xs:complexType {attr}={s:?}>: {other:?} is not a valid value \
7362 (expected 'restriction', 'extension', or '#all')"
7363 ))),
7364 }
7365 }
7366 Ok(out)
7367}
7368
7369fn check_no_occurs(attrs: &[Attr], element: &str) -> Result<(), SchemaCompileError> {
7373 for a in attrs {
7374 if matches!(a.name(), "minOccurs" | "maxOccurs") {
7375 return Err(SchemaCompileError::msg(format!(
7376 "<xs:{element} {}=...> is not allowed (only <xs:any> takes \
7377 minOccurs / maxOccurs)",
7378 a.name(),
7379 )));
7380 }
7381 }
7382 Ok(())
7383}
7384
7385fn parse_wildcard_attrs(
7386 attrs: &[Attr],
7387 target_ns: &Option<Arc<str>>,
7388 version: SchemaVersion,
7389 parse_qname: &mut dyn FnMut(&str) -> Result<QName, SchemaCompileError>,
7390) -> Result<Wildcard, SchemaCompileError> {
7391 let is_xsd11 = matches!(version, SchemaVersion::Xsd11);
7400 if !is_xsd11 {
7401 if let Some(a) = attrs.iter().find(|a| a.name() == "notQName" || a.name() == "notNamespace") {
7402 return Err(SchemaCompileError::msg(format!(
7403 "wildcard attribute {:?} is XSD 1.1 only — \
7404 set SchemaOptions::version to Xsd11, or to Auto with \
7405 vc:minVersion=\"1.1\" on <xs:schema>",
7406 a.name(),
7407 )));
7408 }
7409 }
7410 let mut not_qnames: Vec<QName> = Vec::new();
7419 let mut not_qname_defined = false;
7420 let mut not_qname_defined_sibling = false;
7421 if is_xsd11 {
7422 if let Some(a) = attrs.iter().find(|a| a.name() == "notQName") {
7423 for tok in a.value.as_ref().split_whitespace() {
7424 match tok {
7425 "##defined" => not_qname_defined = true,
7426 "##definedSibling" => not_qname_defined_sibling = true,
7427 qn => not_qnames.push(parse_qname(qn)?),
7428 }
7429 }
7430 }
7431 }
7432 let mut not_namespaces: Vec<Option<Arc<str>>> = Vec::new();
7436 if is_xsd11 {
7437 if let Some(a) = attrs.iter().find(|a| a.name() == "notNamespace") {
7438 for tok in a.value.as_ref().split_whitespace() {
7439 match tok {
7440 "##local" => not_namespaces.push(None),
7441 "##targetNamespace" => not_namespaces.push(target_ns.clone()),
7442 "##any" | "##other" => return Err(SchemaCompileError::msg(format!(
7443 "wildcard notNamespace token {tok:?} is only valid as the \
7444 sole value, not part of a list (XSD 1.1 §3.10.2)"
7445 ))),
7446 other if other.starts_with("##") => return Err(SchemaCompileError::msg(format!(
7447 "wildcard notNamespace token {other:?} is not a defined keyword"
7448 ))),
7449 other => not_namespaces.push(Some(Arc::from(other))),
7450 }
7451 }
7452 }
7453 }
7454 let ns_str = attrs.iter()
7455 .find(|a| a.name() == "namespace")
7456 .map(|a| a.value.as_ref())
7457 .unwrap_or("##any");
7458 let namespaces = match ns_str {
7463 "##any" => NamespaceConstraint::Any,
7464 "##other" => NamespaceConstraint::Other,
7465 list => {
7466 let mut out = Vec::new();
7467 for tok in list.split_whitespace() {
7468 match tok {
7469 "##any" | "##other" => return Err(SchemaCompileError::msg(format!(
7470 "wildcard namespace {tok:?} is only valid as the sole value, \
7471 not part of a list (XSD §3.10.2)"
7472 ))),
7473 "##local" => out.push(None),
7474 "##targetNamespace" => out.push(target_ns.clone()),
7475 other if other.starts_with("##") => return Err(SchemaCompileError::msg(format!(
7476 "wildcard namespace {other:?} is not a defined keyword \
7477 (expected '##any', '##other', '##local', or '##targetNamespace')"
7478 ))),
7479 other => out.push(Some(Arc::from(other))),
7480 }
7481 }
7482 NamespaceConstraint::List(out)
7483 }
7484 };
7485 let process_contents = match attrs.iter()
7486 .find(|a| a.name() == "processContents")
7487 .map(|a| a.value.as_ref())
7488 {
7489 Some("lax") => ProcessContents::Lax,
7490 Some("skip") => ProcessContents::Skip,
7491 Some("strict") => ProcessContents::Strict,
7492 None => ProcessContents::Strict,
7493 Some(other) => return Err(SchemaCompileError::msg(format!(
7494 "wildcard processContents={other:?}: must be 'lax', 'skip', or 'strict'"
7495 ))),
7496 };
7497 Ok(Wildcard {
7498 namespaces, process_contents,
7499 not_qnames, not_namespaces,
7500 not_qname_defined, not_qname_defined_sibling,
7501 })
7502}
7503
7504fn any_type_ref() -> TypeRef {
7511 let wildcard = Wildcard {
7512 namespaces: NamespaceConstraint::Any,
7513 process_contents: ProcessContents::Lax,
7514 not_qnames: Vec::new(),
7515 not_namespaces: Vec::new(),
7516 not_qname_defined: false,
7517 not_qname_defined_sibling: false,
7518 };
7519 let content = ContentModel::Complex {
7520 root: Particle {
7521 min_occurs: 0,
7522 max_occurs: MaxOccurs::Unbounded,
7523 term: Term::Wildcard(wildcard.clone()),
7524 },
7525 mixed: true,
7526 };
7527 TypeRef::Complex(Arc::new(ComplexType {
7528 name: Some(QName::xsd("anyType")),
7529 derivation: None,
7530 content,
7531 matcher: std::sync::OnceLock::new(),
7532 attributes: Vec::new(),
7533 any_attribute: Some(wildcard),
7534 abstract_: false,
7535 block: BlockSet::default(),
7536 final_: BlockSet::default(),
7537 pending_attribute_group_refs: Vec::new(),
7538 assertions: Vec::new(),
7539 }))
7540}
7541
7542fn parse_bound(s: &str, builtin: BuiltinType) -> Result<Bound, SchemaCompileError> {
7543 use BuiltinType::*;
7544 Ok(match builtin {
7545 Decimal => Bound::Decimal(s.parse().map_err(|e| SchemaCompileError::msg(format!("decimal bound: {e}")))?),
7546 Float => Bound::Float(s.parse().map_err(|e| SchemaCompileError::msg(format!("float bound: {e}")))?),
7547 Double => Bound::Double(s.parse().map_err(|e| SchemaCompileError::msg(format!("double bound: {e}")))?),
7548 Integer | Long | Int | Short | Byte
7549 | NonPositiveInteger | NegativeInteger
7550 | NonNegativeInteger | UnsignedInt | UnsignedShort | UnsignedByte
7551 | PositiveInteger | UnsignedLong
7552 => Bound::Int(s.parse().map_err(|e| SchemaCompileError::msg(format!("int bound: {e}")))?),
7553 DateTime | Date | Time | GYearMonth | GYear
7554 | GMonthDay | GDay | GMonth | Duration => {
7555 let v = super::types::SimpleType::of_builtin(builtin).validate(s)
7558 .map_err(|e| SchemaCompileError::msg(format!(
7559 "{builtin:?} bound {s:?}: {}", e.message
7560 )))?;
7561 Bound::Value(v)
7562 }
7563 _ => Bound::Value(super::types::Value::String(s.to_owned())),
7568 })
7569}
7570
7571fn compare_bounds(a: &Bound, b: &Bound) -> Option<std::cmp::Ordering> {
7579 use rust_decimal::Decimal;
7580 match (a, b) {
7581 (Bound::Int(x), Bound::Int(y)) => Some(x.cmp(y)),
7582 (Bound::Decimal(x), Bound::Decimal(y)) => Some(x.cmp(y)),
7583 (Bound::Float(x), Bound::Float(y)) => x.partial_cmp(y),
7584 (Bound::Double(x), Bound::Double(y)) => x.partial_cmp(y),
7585 (Bound::Int(x), Bound::Decimal(y)) => i128::try_from(*y).ok().map(|y| x.cmp(&y))
7586 .or_else(|| Decimal::from(*x).partial_cmp(y)),
7587 (Bound::Decimal(x), Bound::Int(y)) => Some(x.cmp(&Decimal::from(*y))),
7588 (Bound::Value(x), Bound::Value(y)) => super::facets::compare_values(x, y),
7592 _ => None,
7593 }
7594}
7595
7596#[cfg(test)]
7599mod tests {
7600 use super::*;
7601
7602 fn xsd_str(extra_decls: &str) -> String {
7603 format!(
7604 r#"<?xml version="1.0"?>
7605<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
7606 targetNamespace="urn:test"
7607 xmlns="urn:test">
7608{extra_decls}
7609</xs:schema>"#
7610 )
7611 }
7612
7613 #[test]
7614 fn compile_empty_schema() {
7615 let s = Schema::compile_str(&xsd_str("")).unwrap();
7616 assert_eq!(s.target_namespace(), Some("urn:test"));
7617 assert_eq!(s.elements().count(), 0);
7618 }
7619
7620 #[test]
7621 fn compile_single_element_with_builtin_type() {
7622 let s = Schema::compile_str(&xsd_str(
7623 r#"<xs:element name="age" type="xs:int"/>"#
7624 )).unwrap();
7625 let qn = QName::new(Some("urn:test"), "age");
7626 assert!(s.element(&qn).is_some());
7627 }
7628
7629 #[test]
7630 fn rejects_no_namespace_top_level_element() {
7631 let bad = r#"<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
7636 <element name="a" type="xs:string"/>
7637 </xs:schema>"#;
7638 let err = Schema::compile_str(bad)
7639 .expect_err("no-namespace top-level element must be rejected");
7640 assert!(err.to_string().to_lowercase().contains("namespace"),
7641 "error should name the namespace problem: {err}");
7642 }
7643
7644 #[test]
7645 fn compile_simple_type_with_facets() {
7646 let s = Schema::compile_str(&xsd_str(r#"
7647 <xs:simpleType name="ZipCode">
7648 <xs:restriction base="xs:string">
7649 <xs:pattern value="\d{5}(-\d{4})?"/>
7650 <xs:maxLength value="10"/>
7651 </xs:restriction>
7652 </xs:simpleType>
7653 "#)).unwrap();
7654 let qn = QName::new(Some("urn:test"), "ZipCode");
7655 let TypeRef::Simple(st) = s.type_def(&qn).unwrap() else { panic!() };
7656 assert_eq!(st.builtin, BuiltinType::String);
7657 assert!(st.facets.facets.iter().any(|f| matches!(f, Facet::Pattern { .. })));
7658 }
7659
7660 #[test]
7661 fn restriction_chain_collapses_user_base_to_builtin_and_inherits_facets() {
7662 let s = Schema::compile_str(&xsd_str(r#"
7669 <xs:simpleType name="Bounded">
7670 <xs:restriction base="xs:integer">
7671 <xs:minInclusive value="0"/>
7672 </xs:restriction>
7673 </xs:simpleType>
7674 <xs:simpleType name="Limited">
7675 <xs:restriction base="Bounded">
7676 <xs:maxInclusive value="100"/>
7677 </xs:restriction>
7678 </xs:simpleType>
7679 "#)).unwrap();
7680 let qn = QName::new(Some("urn:test"), "Limited");
7681 let TypeRef::Simple(st) = s.type_def(&qn).unwrap() else { panic!() };
7682 assert_eq!(st.builtin, BuiltinType::Integer,
7683 "user-defined base must collapse to the ultimate built-in");
7684
7685 let has_min = st.facets.facets.iter().any(|f|
7686 matches!(f, Facet::MinInclusive(_)));
7687 let has_max = st.facets.facets.iter().any(|f|
7688 matches!(f, Facet::MaxInclusive(_)));
7689 assert!(has_min && has_max,
7690 "derived type must inherit base's minInclusive AND keep its own maxInclusive");
7691
7692 assert!(st.validate("50").is_ok());
7695 assert!(st.validate("-5").is_err(),
7696 "minInclusive=0 from base must still reject negatives");
7697 assert!(st.validate("150").is_err(),
7698 "maxInclusive=100 from derived must still reject overflows");
7699 }
7700
7701 #[test]
7702 fn compile_complex_type_sequence() {
7703 let s = Schema::compile_str(&xsd_str(r#"
7704 <xs:complexType name="Person">
7705 <xs:sequence>
7706 <xs:element name="name" type="xs:string"/>
7707 <xs:element name="age" type="xs:int"/>
7708 </xs:sequence>
7709 </xs:complexType>
7710 "#)).unwrap();
7711 let qn = QName::new(Some("urn:test"), "Person");
7712 let TypeRef::Complex(ct) = s.type_def(&qn).unwrap() else { panic!() };
7713 match &ct.content {
7714 ContentModel::Complex { root: Particle { term: Term::Group { kind, particles }, .. }, .. } => {
7715 assert_eq!(*kind, GroupKind::Sequence);
7716 assert_eq!(particles.len(), 2);
7717 }
7718 _ => panic!("expected sequence"),
7719 }
7720 }
7721
7722 #[test]
7723 fn compile_complex_type_with_attributes() {
7724 let s = Schema::compile_str(&xsd_str(r#"
7725 <xs:complexType name="Item">
7726 <xs:sequence>
7727 <xs:element name="title" type="xs:string"/>
7728 </xs:sequence>
7729 <xs:attribute name="id" type="xs:int" use="required"/>
7730 <xs:attribute name="kind" type="xs:string"/>
7731 </xs:complexType>
7732 "#)).unwrap();
7733 let qn = QName::new(Some("urn:test"), "Item");
7734 let TypeRef::Complex(ct) = s.type_def(&qn).unwrap() else { panic!() };
7735 assert_eq!(ct.attributes.len(), 2);
7736 assert_eq!(ct.attributes[0].use_kind, AttributeUseKind::Required);
7737 assert_eq!(ct.attributes[1].use_kind, AttributeUseKind::Optional);
7738 }
7739
7740 #[test]
7741 fn compile_choice_and_all() {
7742 let s = Schema::compile_str(&xsd_str(r#"
7743 <xs:complexType name="Either">
7744 <xs:choice>
7745 <xs:element name="left" type="xs:int"/>
7746 <xs:element name="right" type="xs:string"/>
7747 </xs:choice>
7748 </xs:complexType>
7749 <xs:complexType name="Both">
7750 <xs:all>
7751 <xs:element name="a" type="xs:int"/>
7752 <xs:element name="b" type="xs:int"/>
7753 </xs:all>
7754 </xs:complexType>
7755 "#)).unwrap();
7756 let qn1 = QName::new(Some("urn:test"), "Either");
7757 if let TypeRef::Complex(ct) = s.type_def(&qn1).unwrap() {
7758 if let ContentModel::Complex { root: Particle { term: Term::Group { kind, .. }, .. }, .. } = &ct.content {
7759 assert_eq!(*kind, GroupKind::Choice);
7760 } else { panic!() }
7761 }
7762 let qn2 = QName::new(Some("urn:test"), "Both");
7763 if let TypeRef::Complex(ct) = s.type_def(&qn2).unwrap() {
7764 if let ContentModel::Complex { root: Particle { term: Term::Group { kind, .. }, .. }, .. } = &ct.content {
7765 assert_eq!(*kind, GroupKind::All);
7766 } else { panic!() }
7767 }
7768 }
7769
7770 #[test]
7771 fn compile_max_occurs_unbounded() {
7772 let s = Schema::compile_str(&xsd_str(r#"
7773 <xs:complexType name="Items">
7774 <xs:sequence>
7775 <xs:element name="item" type="xs:string" maxOccurs="unbounded"/>
7776 </xs:sequence>
7777 </xs:complexType>
7778 "#)).unwrap();
7779 let qn = QName::new(Some("urn:test"), "Items");
7780 if let TypeRef::Complex(ct) = s.type_def(&qn).unwrap() {
7781 if let ContentModel::Complex { root: Particle { term: Term::Group { particles, .. }, .. }, .. } = &ct.content {
7782 assert_eq!(particles[0].max_occurs, MaxOccurs::Unbounded);
7783 }
7784 }
7785 }
7786
7787 #[test]
7788 fn import_with_unresolvable_location_is_a_soft_skip() {
7789 let xml = xsd_str(r#"<xs:import namespace="urn:other" schemaLocation="other.xsd"/>"#);
7794 Schema::compile_str(&xml).expect("schema with unresolvable import should still compile");
7795 }
7796
7797 #[test]
7798 fn import_without_location_is_silently_skipped() {
7799 let xml = xsd_str(r#"<xs:import namespace="urn:other"/>"#);
7802 assert!(Schema::compile_str(&xml).is_ok());
7803 }
7804
7805 #[test]
7806 fn include_via_in_memory_resolver() {
7807 use crate::xsd::InMemoryResolver;
7808 let main = r#"<?xml version="1.0"?>
7809<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
7810 targetNamespace="urn:test" xmlns="urn:test">
7811 <xs:include schemaLocation="types.xsd"/>
7812 <xs:element name="root" type="MyType"/>
7813</xs:schema>"#;
7814 let included = r#"<?xml version="1.0"?>
7815<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
7816 targetNamespace="urn:test" xmlns="urn:test">
7817 <xs:simpleType name="MyType">
7818 <xs:restriction base="xs:string">
7819 <xs:maxLength value="10"/>
7820 </xs:restriction>
7821 </xs:simpleType>
7822</xs:schema>"#;
7823 let resolver = InMemoryResolver::new().with("types.xsd", included.as_bytes().to_vec());
7824 let s = Schema::compile_with(main, resolver).unwrap();
7825 assert!(s.type_def(&QName::new(Some("urn:test"), "MyType")).is_some());
7826 assert!(s.element(&QName::new(Some("urn:test"), "root")).is_some());
7827 }
7828
7829 #[test]
7830 fn include_cycle_is_silently_skipped() {
7831 use crate::xsd::InMemoryResolver;
7832 let a = r#"<?xml version="1.0"?>
7833<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:t" xmlns="urn:t">
7834 <xs:include schemaLocation="b.xsd"/>
7835 <xs:element name="root" type="xs:string"/>
7836</xs:schema>"#;
7837 let b = r#"<?xml version="1.0"?>
7838<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:t" xmlns="urn:t">
7839 <xs:include schemaLocation="a.xsd"/>
7840</xs:schema>"#;
7841 let resolver = InMemoryResolver::new()
7842 .with("a.xsd", a.as_bytes().to_vec())
7843 .with("b.xsd", b.as_bytes().to_vec());
7844 let s = Schema::compile_with(a, resolver).unwrap();
7846 assert!(s.element(&QName::new(Some("urn:t"), "root")).is_some());
7847 }
7848
7849 #[test]
7850 fn include_target_ns_mismatch_rejected() {
7851 use crate::xsd::InMemoryResolver;
7852 let main = r#"<?xml version="1.0"?>
7853<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:a">
7854 <xs:include schemaLocation="other.xsd"/>
7855</xs:schema>"#;
7856 let other = r#"<?xml version="1.0"?>
7857<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:b">
7858 <xs:element name="x" type="xs:string"/>
7859</xs:schema>"#;
7860 let resolver = InMemoryResolver::new().with("other.xsd", other.as_bytes().to_vec());
7861 let err = Schema::compile_with(main, resolver).unwrap_err();
7862 assert!(err.message.contains("targetNamespace"));
7863 }
7864
7865 #[test]
7866 fn rejects_non_schema_root() {
7867 let err = Schema::compile_str("<root/>").unwrap_err();
7868 assert!(err.message.contains("xs:schema"));
7869 }
7870
7871 #[test]
7872 fn enumeration_facet_collected() {
7873 let s = Schema::compile_str(&xsd_str(r#"
7874 <xs:simpleType name="Color">
7875 <xs:restriction base="xs:string">
7876 <xs:enumeration value="red"/>
7877 <xs:enumeration value="green"/>
7878 <xs:enumeration value="blue"/>
7879 </xs:restriction>
7880 </xs:simpleType>
7881 "#)).unwrap();
7882 let qn = QName::new(Some("urn:test"), "Color");
7883 if let TypeRef::Simple(st) = s.type_def(&qn).unwrap() {
7884 let enum_facet = st.facets.facets.iter().find_map(|f| match f {
7885 Facet::Enumeration(opts) => Some(opts),
7886 _ => None,
7887 }).unwrap();
7888 assert_eq!(enum_facet, &vec!["red".to_string(), "green".into(), "blue".into()]);
7889 }
7890 }
7891
7892 #[test]
7893 fn nested_groups_compile() {
7894 let s = Schema::compile_str(&xsd_str(r#"
7895 <xs:complexType name="Form">
7896 <xs:sequence>
7897 <xs:choice>
7898 <xs:element name="a" type="xs:int"/>
7899 <xs:element name="b" type="xs:int"/>
7900 </xs:choice>
7901 <xs:element name="c" type="xs:string"/>
7902 </xs:sequence>
7903 </xs:complexType>
7904 "#));
7905 assert!(s.is_ok());
7906 }
7907}