1use std::collections::{HashMap, HashSet};
8use std::marker::PhantomData;
9
10use crate::arenas::{ComplexTypeDefData, ResolvedAttributeUse};
11use crate::compiler::{compile_content_model_matcher, SubstitutionGroupMap};
12use crate::ids::{
13 AttributeGroupKey, AttributeKey, ComplexTypeKey, ElementKey, IdentityConstraintKey, NameId,
14 NotationKey, SimpleTypeKey, TypeKey,
15};
16use crate::namespace::context::NamespaceContextSnapshot;
17use crate::namespace::qname::{parse_qname_with_snapshot, QNameError};
18use crate::namespace::table::well_known;
19use crate::parser::frames::{AttributeUseKind, AttributeUseResult, IdentityKind, ProcessContents};
20use crate::parser::location::SourceLocation;
21use crate::schema::model::DerivationSet;
22use crate::schema::resolver::format_resolved_qname;
23use crate::schema::SchemaSet;
24use crate::types::value::XmlValue;
25use crate::types::XmlTypeCode;
26#[cfg(feature = "xsd11")]
27use bumpalo::Bump;
28
29use super::content::ContentValidatorState;
30use super::context::{ElementValidationState, ValidatorState};
31use super::errors::{self, ValidationError};
32use super::identity::{CompiledIdentityConstraint, ConstraintStruct, KeyTable};
33#[cfg(feature = "xsd11")]
34use super::info::{AssertionOutcome, InheritedAttribute};
35use super::info::{
36 ContentProcessing, ContentType, DefaultAttribute, ExpectedAttribute, ExpectedElement,
37 NoNamespaceSchemaLocationHint, SchemaInfo, SchemaLocationHint, SchemaValidity, TypeSource,
38 ValidationAttempted, ValidationFlags,
39};
40use crate::types::complex::ProcessContents as TypesProcessContents;
41
42#[cfg(feature = "xsd11")]
43use super::assertions::{
44 evaluate_complex_type_assertions, has_inherited_assertions, AssertionBufferFrame,
45};
46#[cfg(feature = "xsd11")]
47use super::validator::AssertionSource;
48use super::validator::{ValidationSink, ValidationWarning};
49
50#[cfg(feature = "xsd11")]
51use crate::document::builder::BufferDocumentBuilder;
52#[cfg(feature = "xsd11")]
53use crate::document::BufferDocumentOptions;
54
55struct GroupAttribute {
61 name: NameId,
62 namespace: Option<NameId>,
63 use_kind: AttributeUseKind,
64 type_key: Option<TypeKey>,
65 attr_key: Option<AttributeKey>,
66 fixed_value: Option<String>,
67 default_value: Option<String>,
68 #[cfg(feature = "xsd11")]
69 inheritable: bool,
70}
71
72enum AttributeLookup {
78 Found(Option<AttributeKey>, Option<TypeKey>, Option<String>, bool),
81 Prohibited,
83 NotFound,
85}
86
87enum XsiTypeOutcome {
93 Applied(TypeKey),
95 Unresolved,
97 InvalidDerivation,
99}
100
101pub struct ValidationRuntime<'a, S: ValidationSink> {
111 pub(crate) schema_set: &'a SchemaSet,
113 pub(crate) subst_groups: &'a Option<SubstitutionGroupMap>,
115 pub(crate) flags: ValidationFlags,
117 pub sink: S,
119 validation_stack: Vec<ElementValidationState>,
121 current_state: ValidatorState,
123 current_location: Option<SourceLocation>,
125 element_path: String,
127 compiled_constraints: HashMap<IdentityConstraintKey, Option<CompiledIdentityConstraint>>,
129 active_constraints: Vec<ConstraintStruct>,
131 id_values: HashMap<String, u64>,
134 next_element_serial: u64,
136 pending_idrefs: Vec<(String, Option<SourceLocation>, String)>,
138 unparsed_entities: Option<HashSet<String>>,
141 ic_scope_tables: Vec<Option<HashMap<IdentityConstraintKey, KeyTable>>>,
143 deferred_keyrefs: Vec<(KeyTable, Option<IdentityConstraintKey>)>,
146 #[cfg(feature = "xsd11")]
148 pub(crate) assertion_source: AssertionSource,
149 #[cfg(feature = "xsd11")]
154 fragment_builder: Option<BufferDocumentBuilder<'a>>,
155 #[cfg(feature = "xsd11")]
157 fragment_arena: Option<Box<Bump>>,
158 #[cfg(feature = "xsd11")]
160 assertion_buffer_stack: Vec<AssertionBufferFrame>,
161 #[cfg(feature = "xsd11")]
163 pending_assertion_frames: Vec<AssertionBufferFrame>,
164 #[cfg(feature = "xsd11")]
166 deferred_attribute_results: Vec<SchemaInfo>,
167 final_ic_tables: Option<HashMap<IdentityConstraintKey, KeyTable>>,
169 schema_location_hints: Vec<SchemaLocationHint>,
171 no_namespace_schema_location_hints: Vec<NoNamespaceSchemaLocationHint>,
173 first_namespace_use: HashMap<Option<NameId>, u64>,
181 instance_base_uri: String,
183 cached_xsd10_id_key: Option<SimpleTypeKey>,
188 _not_thread_safe: PhantomData<*const ()>,
190}
191
192impl<'a, S: ValidationSink> ValidationRuntime<'a, S> {
193 pub(crate) fn new(
195 schema_set: &'a SchemaSet,
196 subst_groups: &'a Option<SubstitutionGroupMap>,
197 flags: ValidationFlags,
198 sink: S,
199 #[cfg(feature = "xsd11")] assertion_source: AssertionSource,
200 ) -> Self {
201 let cached_xsd10_id_key = if schema_set.is_xsd10() {
202 schema_set.builtin_types().get_by_type_code(XmlTypeCode::Id)
203 } else {
204 None
205 };
206 ValidationRuntime {
207 schema_set,
208 subst_groups,
209 flags,
210 sink,
211 validation_stack: Vec::new(),
212 current_state: ValidatorState::None,
213 current_location: None,
214 element_path: String::new(),
215 compiled_constraints: HashMap::new(),
216 active_constraints: Vec::new(),
217 id_values: HashMap::new(),
218 next_element_serial: 0,
219 pending_idrefs: Vec::new(),
220 unparsed_entities: None,
221 ic_scope_tables: Vec::new(),
222 deferred_keyrefs: Vec::new(),
223 final_ic_tables: None,
224 schema_location_hints: Vec::new(),
225 no_namespace_schema_location_hints: Vec::new(),
226 first_namespace_use: HashMap::new(),
227 instance_base_uri: String::new(),
228 #[cfg(feature = "xsd11")]
229 assertion_source,
230 #[cfg(feature = "xsd11")]
231 fragment_builder: None,
232 #[cfg(feature = "xsd11")]
233 fragment_arena: None,
234 #[cfg(feature = "xsd11")]
235 assertion_buffer_stack: Vec::new(),
236 #[cfg(feature = "xsd11")]
237 pending_assertion_frames: Vec::new(),
238 #[cfg(feature = "xsd11")]
239 deferred_attribute_results: Vec::new(),
240 cached_xsd10_id_key,
241 _not_thread_safe: PhantomData,
242 }
243 }
244
245 pub fn set_location(&mut self, location: SourceLocation) {
247 self.current_location = Some(location);
248 }
249
250 pub fn clear_location(&mut self) {
252 self.current_location = None;
253 }
254
255 pub fn identity_constraint_tables(&self) -> Option<&HashMap<IdentityConstraintKey, KeyTable>> {
260 self.final_ic_tables.as_ref()
261 }
262
263 pub fn set_unparsed_entities(&mut self, entities: HashSet<String>) {
269 self.unparsed_entities = Some(entities);
270 }
271
272 pub fn set_instance_base_uri(&mut self, base_uri: impl Into<String>) {
278 self.instance_base_uri = base_uri.into();
279 }
280
281 pub fn schema_location_hints(&self) -> &[SchemaLocationHint] {
289 &self.schema_location_hints
290 }
291
292 pub fn no_namespace_schema_location_hints(&self) -> &[NoNamespaceSchemaLocationHint] {
294 &self.no_namespace_schema_location_hints
295 }
296
297 #[cfg(feature = "xsd11")]
299 #[cfg(test)]
300 fn fragment_arena(&self) -> Option<&Bump> {
301 self.fragment_arena.as_deref()
302 }
303
304 #[cfg(feature = "xsd11")]
311 #[cfg(test)]
312 fn fragment_arena_mut(&mut self) -> &mut Bump {
313 debug_assert!(
314 self.fragment_builder.is_none(),
315 "fragment_arena_mut() called while fragment_builder is active — \
316 would invalidate the builder's borrow"
317 );
318 self.fragment_arena
319 .get_or_insert_with(|| Box::new(Bump::new()))
320 }
321
322 #[cfg(feature = "xsd11")]
328 #[inline]
329 fn is_buffering_assertions(&self) -> bool {
330 !self.assertion_buffer_stack.is_empty()
331 }
332
333 #[cfg(feature = "xsd11")]
336 fn begin_assertion_buffering(&mut self) -> bool {
337 let arena_box = self
338 .fragment_arena
339 .get_or_insert_with(|| Box::new(Bump::new()));
340 let arena_ref: &'a Bump = unsafe { &*(&**arena_box as *const Bump) };
344 let names_ref: &'a crate::namespace::table::NameTable = &self.schema_set.name_table;
345 match BufferDocumentBuilder::new(
352 arena_ref,
353 names_ref,
354 Some(self.schema_set),
355 BufferDocumentOptions::fragment(),
356 ) {
357 Ok(builder) => {
358 self.fragment_builder = Some(builder);
359 true
360 }
361 Err(e) => {
362 self.report_error(
363 "cvc-assertion",
364 format!("Failed to create assertion fragment builder: {}", e),
365 );
366 false
367 }
368 }
369 }
370
371 #[cfg(feature = "xsd11")]
376 fn abort_assertion_buffering(&mut self, error_msg: String) {
377 self.report_error("cvc-assertion", error_msg);
378 self.fragment_builder.take();
380 self.assertion_buffer_stack.clear();
381 self.pending_assertion_frames.clear();
382 if let Some(arena) = self.fragment_arena.as_mut() {
383 arena.reset();
384 }
385 }
386
387 #[cfg(feature = "xsd11")]
389 fn abort_assertion_buffer_op(&mut self, context: &str, e: impl std::fmt::Display) {
390 self.abort_assertion_buffering(format!(
391 "Assertion fragment buffer error ({}): {}",
392 context, e
393 ));
394 }
395
396 #[cfg(feature = "xsd11")]
400 fn install_fragment_binding(
401 &mut self,
402 node_ref: u32,
403 binding: crate::document::type_remap::NodeSchemaBinding,
404 context: &str,
405 ) -> bool {
406 let Some(builder) = self.fragment_builder.as_mut() else {
407 return true;
408 };
409 if let Err(e) = builder.set_node_binding(node_ref, binding) {
410 self.abort_assertion_buffer_op(context, e);
411 return false;
412 }
413 true
414 }
415
416 #[cfg(feature = "xsd11")]
421 fn detect_assertions_on_element(
422 &mut self,
423 type_key: Option<TypeKey>,
424 local_name: NameId,
425 namespace: Option<NameId>,
426 ) {
427 if self.assertion_source != AssertionSource::FragmentBuffer {
428 return;
429 }
430 let has_assertions = match type_key {
431 Some(TypeKey::Complex(ct_key))
432 if has_inherited_assertions(ct_key, &self.schema_set.arenas) =>
433 {
434 Some(ct_key)
435 }
436 _ => None,
437 };
438
439 let force_start = self
440 .validation_stack
441 .last()
442 .is_some_and(|ev| ev.has_type_alternatives);
443
444 if !self.is_buffering_assertions() && has_assertions.is_none() && !force_start {
445 return; }
447
448 if !self.is_buffering_assertions() && !self.begin_assertion_buffering() {
450 return; }
452
453 let local = self.schema_set.name_table.resolve(local_name);
459 let ns = namespace
460 .map(|id| self.schema_set.name_table.resolve(id).to_string())
461 .unwrap_or_default();
462 let mut ns_strings: Vec<(String, String)> = Vec::new();
463 if let Some(snapshot) = self
464 .validation_stack
465 .last()
466 .and_then(|ev| ev.ns_context.as_ref())
467 {
468 for &(prefix_id, uri_id) in &snapshot.bindings {
469 let prefix = self.schema_set.name_table.resolve(prefix_id).to_string();
470 let uri = self.schema_set.name_table.resolve(uri_id).to_string();
471 ns_strings.push((prefix, uri));
472 }
473 if let Some(default_ns) = snapshot.default_ns {
474 let uri = self.schema_set.name_table.resolve(default_ns).to_string();
475 ns_strings.push((String::new(), uri));
476 }
477 }
478 let ns_decls: Vec<(&str, &str)> = ns_strings
479 .iter()
480 .map(|(p, u)| (p.as_str(), u.as_str()))
481 .collect();
482 let element_ref = match self.fragment_builder.as_mut() {
483 Some(builder) => match builder.start_element(&local, &ns, "", &ns_decls) {
484 Ok(r) => r,
485 Err(e) => {
486 self.report_error(
487 "cvc-assertion",
488 format!("Assertion fragment buffer error (start_element): {}", e),
489 );
490 return;
491 }
492 },
493 None => return, };
495
496 if has_assertions.is_none() {
503 if let Some(tk) = type_key {
504 let (element_decl, content_type) = self
505 .validation_stack
506 .last()
507 .map(|ev| (ev.element_decl, ev.content_type))
508 .unwrap_or((None, None));
509 let binding = crate::document::type_remap::NodeSchemaBinding {
510 type_key: tk,
511 element_decl,
512 attribute_decl: None,
513 content_type,
514 };
515 if !self.install_fragment_binding(element_ref, binding, "element binding") {
516 return;
517 }
518 }
519 }
520
521 if let Some(ev) = self.validation_stack.last_mut() {
523 ev.assertion_element_ref = Some(element_ref);
524 }
525
526 if let Some(ct_key) = has_assertions {
528 self.assertion_buffer_stack.push(AssertionBufferFrame {
529 element_ref,
530 complex_type_key: ct_key,
531 element_path: String::new(), location: None, });
534 if let Some(ev) = self.validation_stack.last_mut() {
535 ev.owns_assertion_buffer = true;
536 }
537 }
538 }
539
540 #[cfg(feature = "xsd11")]
545 fn redetect_assertions_after_cta(&mut self, new_type: Option<TypeKey>) {
546 if self.assertion_source != AssertionSource::FragmentBuffer {
547 return;
548 }
549
550 let old_element_ref = if let Some(ev) = self.validation_stack.last_mut() {
552 if ev.owns_assertion_buffer {
553 let frame = self.assertion_buffer_stack.pop();
554 ev.owns_assertion_buffer = false;
555 frame.map(|f| f.element_ref)
556 } else {
557 None
558 }
559 } else {
560 return;
561 };
562
563 let new_ct_key = match new_type {
565 Some(TypeKey::Complex(ct_key))
566 if has_inherited_assertions(ct_key, &self.schema_set.arenas) =>
567 {
568 ct_key
569 }
570 _ => {
571 if self.assertion_buffer_stack.is_empty() && self.fragment_builder.is_some() {
578 self.fragment_builder.take();
579 self.pending_assertion_frames.clear();
580 if let Some(arena) = self.fragment_arena.as_mut() {
581 arena.reset();
582 }
583 }
584 return;
585 }
586 };
587
588 let element_ref = old_element_ref.or_else(|| {
590 self.validation_stack
591 .last()
592 .and_then(|ev| ev.assertion_element_ref)
593 });
594
595 let Some(element_ref) = element_ref else {
596 return;
597 };
598
599 let need_replay = old_element_ref.is_none() && !self.is_buffering_assertions();
602
603 self.assertion_buffer_stack.push(AssertionBufferFrame {
604 element_ref,
605 complex_type_key: new_ct_key,
606 element_path: String::new(),
607 location: None,
608 });
609 if let Some(ev) = self.validation_stack.last_mut() {
610 ev.owns_assertion_buffer = true;
611 }
612
613 if need_replay {
614 let collected: Vec<_> = match self.validation_stack.last() {
615 Some(ev) => ev.collected_attributes.clone(),
616 None => return,
617 };
618 for (ns, name, value) in &collected {
619 let local = self.schema_set.name_table.resolve(*name);
620 let ns_str = ns
621 .map(|id| self.schema_set.name_table.resolve(id).to_string())
622 .unwrap_or_default();
623 let result = self
624 .fragment_builder
625 .as_mut()
626 .map(|b| b.attribute(&local, &ns_str, "", value));
627 if let Some(Err(e)) = result {
628 self.abort_assertion_buffer_op("attribute replay", e);
629 return;
630 }
631 }
632 }
633 }
634
635 #[cfg(feature = "xsd11")]
637 fn report_assertion_errors(
638 &mut self,
639 assertion_errors: Vec<ValidationError>,
640 ev_state: &mut ElementValidationState,
641 ) {
642 for err in assertion_errors {
643 self.report_validation_error_to(err, &mut ev_state.error_codes);
644 ev_state.validity = SchemaValidity::Invalid;
645 }
646 }
647
648 #[cfg(feature = "xsd11")]
656 fn report_assertion_errors_deferred(
657 &mut self,
658 assertion_errors: Vec<ValidationError>,
659 element_path: &str,
660 location: &Option<SourceLocation>,
661 ) {
662 for err in assertion_errors {
663 let err = if !element_path.is_empty() {
664 err.with_path(element_path.to_string())
665 } else {
666 err
667 };
668 let err = match location {
669 Some(loc) => err.with_location(loc.clone()),
670 None => err,
671 };
672 self.sink.on_error(err);
673 }
674 }
675
676 pub fn validate_element(
687 &mut self,
688 local_name: &str,
689 namespace_uri: &str,
690 xsi_type: Option<&str>,
691 xsi_nil: Option<&str>,
692 ns_context: &NamespaceContextSnapshot,
693 ) -> SchemaInfo {
694 let name_id = self.schema_set.name_table.add(local_name);
695 let ns_id = if namespace_uri.is_empty() {
696 None
697 } else {
698 Some(self.schema_set.name_table.add(namespace_uri))
699 };
700 self.validate_element_by_id(name_id, ns_id, xsi_type, xsi_nil, ns_context)
701 }
702
703 fn push_skipped_element(
707 &mut self,
708 local_name: NameId,
709 namespace: Option<NameId>,
710 ns_context: &NamespaceContextSnapshot,
711 ) -> SchemaInfo {
712 let mut ev_state = ElementValidationState::new(local_name, namespace);
713 ev_state.ns_context = Some(ns_context.clone());
714 ev_state.process_contents = ContentProcessing::Skip;
715 ev_state.content_state = ContentValidatorState::Simple;
716 ev_state.validity = SchemaValidity::NotKnown;
717 self.push_element(ev_state);
718 self.advance_constraints_start_element_skipped(local_name, namespace);
719 #[cfg(feature = "xsd11")]
720 self.detect_assertions_on_element(None, local_name, namespace);
721 SchemaInfo::empty()
722 }
723
724 #[cfg(feature = "xsd11")]
731 fn dynamic_edc_violation_reason(
732 &self,
733 matched_via_wildcard: bool,
734 local_name: NameId,
735 namespace: Option<NameId>,
736 governing_type: Option<TypeKey>,
737 governing_decl: Option<ElementKey>,
738 ) -> Option<String> {
739 if !matched_via_wildcard || !self.schema_set.is_xsd11() {
740 return None;
741 }
742 let parent_ct = match self.validation_stack.last().and_then(|p| p.schema_type) {
743 Some(TypeKey::Complex(ct_key)) => ct_key,
744 _ => return None,
745 };
746 match crate::schema::edc::check_dynamic_edc(
747 self.schema_set,
748 self.subst_groups.as_ref(),
749 parent_ct,
750 (namespace, local_name),
751 governing_type,
752 governing_decl,
753 ) {
754 crate::schema::edc::EdcOutcome::Mismatch { reason } => Some(reason),
755 _ => None,
756 }
757 }
758
759 pub fn validate_element_by_id(
761 &mut self,
762 local_name: NameId,
763 namespace: Option<NameId>,
764 xsi_type: Option<&str>,
765 xsi_nil: Option<&str>,
766 ns_context: &NamespaceContextSnapshot,
767 ) -> SchemaInfo {
768 if !self.current_state.can_start_element() {
770 self.report_error(
771 "cvc-complex-type",
772 format!(
773 "Element start not allowed in current state {:?}",
774 self.current_state
775 ),
776 );
777 return SchemaInfo::invalid();
778 }
779
780 #[cfg(feature = "xsd11")]
782 if self.validation_stack.is_empty() {
783 let has_flag = self.flags.contains(ValidationFlags::PROCESS_ASSERTIONS);
784 let is_fragment = self.assertion_source == AssertionSource::FragmentBuffer;
785 assert!(
786 has_flag == is_fragment,
787 "PROCESS_ASSERTIONS flag and AssertionSource are inconsistent: \
788 flag={has_flag}, source={:?}. Call set_assertion_source() before validation.",
789 self.assertion_source,
790 );
791 }
792
793 let mut match_info: Option<super::content::ElementMatchInfo> = None;
795 let mut content_model_accepted = false;
796 let mut content_model_error = None;
797 let mut nil_error: Option<String> = None;
798 if let Some(parent) = self.validation_stack.last_mut() {
799 if parent.process_contents == ContentProcessing::Skip {
800 parent.has_element_children = true;
802 return self.push_skipped_element(local_name, namespace, ns_context);
803 } else if parent.is_nil {
804 let parent_name = self
805 .schema_set
806 .name_table
807 .resolve(parent.local_name)
808 .to_string();
809 nil_error = Some(format!(
810 "Element '{}' is nilled (xsi:nil='true') but has child element content",
811 parent_name,
812 ));
813 } else {
814 parent.has_element_children = true;
815 let wildcard_target_ns = match parent.schema_type {
821 Some(TypeKey::Complex(ct_key)) => {
822 self.schema_set.arenas.complex_types[ct_key].target_namespace
823 }
824 _ => parent.namespace,
825 };
826 match parent.content_state.advance_element(
827 local_name,
828 namespace,
829 wildcard_target_ns,
830 self.schema_set.xsd_version,
831 self.subst_groups.as_ref(),
832 ) {
833 Some(info) => {
834 match_info = Some(info);
835 content_model_accepted = true;
836 }
837 None => {
838 let elem_name = self.schema_set.name_table.resolve(local_name);
839 content_model_error = Some(format!(
840 "Element '{}' is not allowed at this position in the content model",
841 elem_name,
842 ));
843 }
844 }
845 }
846 }
847 if let Some(msg) = nil_error {
848 self.report_error("cvc-elt.3.2.1", msg);
849 }
850 if let Some(msg) = content_model_error {
851 self.report_error("cvc-complex-type.2.4", msg);
852 }
853
854 let matched_elem_key = match_info.and_then(|i| i.element_key);
856 let matched_type = match_info.and_then(|i| i.resolved_type);
857
858 #[cfg(feature = "xsd11")]
862 let matched_via_wildcard = match_info
863 .as_ref()
864 .and_then(|i| i.process_contents)
865 .is_some();
866
867 let process_contents = match_info
870 .and_then(|i| i.process_contents)
871 .map(|pc| match pc {
872 TypesProcessContents::Strict => ContentProcessing::Strict,
873 TypesProcessContents::Lax => ContentProcessing::Lax,
874 TypesProcessContents::Skip => ContentProcessing::Skip,
875 })
876 .unwrap_or_else(|| {
877 self.validation_stack
878 .last()
879 .map(|p| p.process_contents)
880 .unwrap_or(ContentProcessing::Strict)
881 });
882
883 let element_key = if matched_type.is_some() || process_contents == ContentProcessing::Skip {
887 matched_elem_key
888 } else {
889 matched_elem_key.or_else(|| self.schema_set.lookup_element(namespace, local_name))
890 };
891
892 if element_key.is_none() {
893 if content_model_accepted {
894 if process_contents == ContentProcessing::Skip {
895 return self.push_skipped_element(local_name, namespace, ns_context);
896 }
897
898 let is_nil = matches!(xsi_nil, Some("true") | Some("1"));
901 let mut ev_state = ElementValidationState::new(local_name, namespace);
902 ev_state.ns_context = Some(ns_context.clone());
903 ev_state.validity = SchemaValidity::Valid;
904 ev_state.process_contents = process_contents;
905 ev_state.is_nil = is_nil;
906
907 let mut wildcard_xsi_type_errors = Vec::new();
908 if let Some(mut type_key) = matched_type {
909 let mut b1_type_source = TypeSource::Declaration;
911 if let Some(xsi_type_str) = xsi_type {
912 match self.resolve_xsi_type(
913 xsi_type_str,
914 Some(type_key),
915 DerivationSet::empty(),
916 ns_context,
917 &mut wildcard_xsi_type_errors,
918 ) {
919 XsiTypeOutcome::Applied(overridden) => {
920 type_key = overridden;
921 b1_type_source = TypeSource::XsiType;
922 }
923 XsiTypeOutcome::Unresolved | XsiTypeOutcome::InvalidDerivation => {
924 ev_state.validity = SchemaValidity::Invalid;
925 }
927 }
928 }
929 let (content_state, content_type) = self.init_content_model(Some(type_key));
931 ev_state.schema_type = Some(type_key);
932 ev_state.type_source = Some(b1_type_source);
933 ev_state.content_state = content_state;
934 ev_state.content_type = Some(content_type);
935 } else {
936 if let Some(xsi_type_str) = xsi_type {
940 match self.resolve_xsi_type(
941 xsi_type_str,
942 None,
943 DerivationSet::empty(),
944 ns_context,
945 &mut wildcard_xsi_type_errors,
946 ) {
947 XsiTypeOutcome::Applied(overridden) => {
948 let (content_state, content_type) =
949 self.init_content_model(Some(overridden));
950 ev_state.schema_type = Some(overridden);
951 ev_state.type_source = Some(TypeSource::XsiType);
952 ev_state.content_state = content_state;
953 ev_state.content_type = Some(content_type);
954 }
955 XsiTypeOutcome::Unresolved | XsiTypeOutcome::InvalidDerivation => {
956 ev_state.validity = SchemaValidity::Invalid;
958 let (content_state, content_type) =
959 self.lax_assessment_content_model();
960 ev_state.content_state = content_state;
961 ev_state.content_type = Some(content_type);
962 }
964 }
965 } else {
966 let (content_state, content_type) = self.lax_assessment_content_model();
968 ev_state.content_state = content_state;
969 ev_state.content_type = Some(content_type);
970 }
972 if process_contents == ContentProcessing::Strict
977 && ev_state.schema_type.is_none()
978 {
979 ev_state.validity = SchemaValidity::Invalid;
980 }
981 }
982
983 ev_state.strictly_assessed = (ev_state.element_decl.is_some()
984 || ev_state.schema_type.is_some())
985 && ev_state.process_contents != ContentProcessing::Skip;
986 #[cfg(feature = "xsd11")]
991 let edc_violation_b = self.dynamic_edc_violation_reason(
992 matched_via_wildcard,
993 local_name,
994 namespace,
995 ev_state.schema_type,
996 None,
997 );
998 #[cfg(feature = "xsd11")]
999 if edc_violation_b.is_some() {
1000 ev_state.validity = SchemaValidity::Invalid;
1001 }
1002 let schema_type = ev_state.schema_type;
1003 let content_type = ev_state.content_type;
1004 let validity = ev_state.validity;
1005 let type_source = ev_state.type_source;
1006 let needs_undeclared_error =
1007 process_contents == ContentProcessing::Strict && schema_type.is_none();
1008 self.push_element(ev_state);
1009 #[cfg(feature = "xsd11")]
1010 if let Some(reason) = edc_violation_b {
1011 let elem_name = self.schema_set.name_table.resolve(local_name).to_string();
1012 self.report_error(
1013 "cvc-complex-type.5",
1014 format!(
1015 "Element '{}' matched a wildcard but its governing type is \
1016 inconsistent with the local element declaration in the \
1017 parent's content model: {}",
1018 elem_name, reason,
1019 ),
1020 );
1021 }
1022 self.emit_deferred_xsi_type_errors(wildcard_xsi_type_errors);
1024 if needs_undeclared_error {
1025 let elem_name = self.schema_set.name_table.resolve(local_name);
1026 self.report_error(
1027 "cvc-elt.1",
1028 format!("Element '{}' is not declared", elem_name),
1029 );
1030 }
1031 self.advance_constraints_start_element(local_name, namespace, None);
1032 #[cfg(feature = "xsd11")]
1033 self.detect_assertions_on_element(schema_type, local_name, namespace);
1034 return SchemaInfo {
1035 element_decl: None,
1036 attribute_decl: None,
1037 schema_type,
1038 member_type: None,
1039 validity,
1040 validation_attempted: ValidationAttempted::None,
1041 is_default: false,
1042 is_nil,
1043 content_type,
1044 typed_value: None,
1045 normalized_value: None,
1046 schema_error_codes: Vec::new(),
1047 notation: None,
1048 deferred_by_cta: false,
1049 type_source,
1050 #[cfg(feature = "xsd11")]
1051 cta_selected: false,
1052 #[cfg(feature = "xsd11")]
1053 assertion_outcome: None,
1054 };
1055 }
1056
1057 if self.validation_stack.is_empty() {
1064 if let Some(xsi_type_str) = xsi_type {
1065 let mut deferred = Vec::new();
1066 match self.resolve_xsi_type(
1067 xsi_type_str,
1068 None,
1069 DerivationSet::empty(),
1070 ns_context,
1071 &mut deferred,
1072 ) {
1073 XsiTypeOutcome::Applied(type_key) => {
1074 let is_nil = matches!(xsi_nil, Some("true") | Some("1"));
1075 let mut ev_state =
1076 ElementValidationState::new(local_name, namespace);
1077 ev_state.ns_context = Some(ns_context.clone());
1078 let (content_state, content_type) =
1079 self.init_content_model(Some(type_key));
1080 ev_state.schema_type = Some(type_key);
1081 ev_state.type_source = Some(TypeSource::XsiType);
1082 ev_state.content_state = content_state;
1083 ev_state.content_type = Some(content_type);
1084 ev_state.is_nil = is_nil;
1085 ev_state.validity = SchemaValidity::Valid;
1086 ev_state.process_contents = ContentProcessing::Strict;
1087 ev_state.strictly_assessed = true;
1088 self.push_element(ev_state);
1089 self.advance_constraints_start_element(
1090 local_name, namespace, None,
1091 );
1092 #[cfg(feature = "xsd11")]
1093 self.detect_assertions_on_element(
1094 Some(type_key),
1095 local_name,
1096 namespace,
1097 );
1098 return SchemaInfo {
1099 element_decl: None,
1100 attribute_decl: None,
1101 schema_type: Some(type_key),
1102 member_type: None,
1103 validity: SchemaValidity::Valid,
1104 validation_attempted: ValidationAttempted::None,
1105 is_default: false,
1106 is_nil,
1107 content_type: Some(content_type),
1108 typed_value: None,
1109 normalized_value: None,
1110 schema_error_codes: Vec::new(),
1111 notation: None,
1112 deferred_by_cta: false,
1113 type_source: Some(TypeSource::XsiType),
1114 #[cfg(feature = "xsd11")]
1115 cta_selected: false,
1116 #[cfg(feature = "xsd11")]
1117 assertion_outcome: None,
1118 };
1119 }
1120 XsiTypeOutcome::Unresolved | XsiTypeOutcome::InvalidDerivation => {
1121 let mut ev_state =
1127 ElementValidationState::new(local_name, namespace);
1128 ev_state.ns_context = Some(ns_context.clone());
1129 ev_state.validity = SchemaValidity::Invalid;
1130 let (content_state, content_type) =
1131 self.lax_assessment_content_model();
1132 ev_state.content_state = content_state;
1133 ev_state.content_type = Some(content_type);
1134 self.push_element(ev_state);
1135 let elem_name =
1136 self.schema_set.name_table.resolve(local_name).to_string();
1137 self.report_error(
1138 "cvc-elt.1",
1139 format!("Element '{}' is not declared", elem_name),
1140 );
1141 self.emit_deferred_xsi_type_errors(deferred);
1142 self.advance_constraints_start_element(
1143 local_name, namespace, None,
1144 );
1145 #[cfg(feature = "xsd11")]
1146 self.detect_assertions_on_element(None, local_name, namespace);
1147 return SchemaInfo::invalid();
1148 }
1149 }
1150 }
1151 }
1152
1153 match process_contents {
1154 ContentProcessing::Skip => {
1155 let mut ev_state = ElementValidationState::new(local_name, namespace);
1157 ev_state.ns_context = Some(ns_context.clone());
1158 ev_state.process_contents = ContentProcessing::Skip;
1159 ev_state.content_state = ContentValidatorState::Simple; ev_state.validity = SchemaValidity::NotKnown;
1161 self.push_element(ev_state);
1162 self.advance_constraints_start_element(local_name, namespace, None);
1163 #[cfg(feature = "xsd11")]
1164 self.detect_assertions_on_element(None, local_name, namespace);
1165 return SchemaInfo::empty();
1166 }
1167 ContentProcessing::Lax => {
1168 let mut ev_state = ElementValidationState::new(local_name, namespace);
1170 ev_state.ns_context = Some(ns_context.clone());
1171 ev_state.process_contents = ContentProcessing::Lax;
1172 let (content_state, content_type) = self.lax_assessment_content_model();
1173 ev_state.content_state = content_state;
1174 ev_state.content_type = Some(content_type);
1175 ev_state.validity = SchemaValidity::NotKnown;
1177 self.push_element(ev_state);
1178 self.advance_constraints_start_element(local_name, namespace, None);
1179 #[cfg(feature = "xsd11")]
1180 self.detect_assertions_on_element(None, local_name, namespace);
1181 return SchemaInfo::empty();
1182 }
1183 ContentProcessing::Strict => {
1184 let mut ev_state = ElementValidationState::new(local_name, namespace);
1185 ev_state.ns_context = Some(ns_context.clone());
1186 ev_state.validity = SchemaValidity::Invalid;
1187 let (content_state, content_type) = self.lax_assessment_content_model();
1189 ev_state.content_state = content_state;
1190 ev_state.content_type = Some(content_type);
1191 self.push_element(ev_state);
1193 let elem_name = self.schema_set.name_table.resolve(local_name);
1195 self.report_error(
1196 "cvc-elt.1",
1197 format!("Element '{}' is not declared", elem_name),
1198 );
1199 self.advance_constraints_start_element(local_name, namespace, None);
1200 #[cfg(feature = "xsd11")]
1201 self.detect_assertions_on_element(None, local_name, namespace);
1202 return SchemaInfo::invalid();
1203 }
1204 }
1205 }
1206
1207 let elem_key = element_key.unwrap();
1208 let elem_data = &self.schema_set.arenas.elements[elem_key];
1209
1210 let is_abstract = elem_data.is_abstract;
1212
1213 let has_deferred_type_error = elem_data.deferred_type_error.is_some();
1218
1219 let mut type_key = elem_data.resolved_type;
1221
1222 let (effective_block, _) = crate::compiler::substitution::effective_element_constraints(
1225 self.schema_set,
1226 elem_data,
1227 );
1228 let effective_block = effective_block.element_block_mask();
1231 let mut xsi_type_deferred_errors = Vec::new();
1232 let mut xsi_type_invalid = false;
1233 let mut type_source = TypeSource::Declaration;
1234 if let Some(xsi_type_str) = xsi_type {
1235 let declared_for_xsi =
1237 type_key.or(Some(TypeKey::Complex(self.schema_set.any_type_key())));
1238 match self.resolve_xsi_type(
1239 xsi_type_str,
1240 declared_for_xsi,
1241 effective_block,
1242 ns_context,
1243 &mut xsi_type_deferred_errors,
1244 ) {
1245 XsiTypeOutcome::Applied(overridden) => {
1246 type_key = Some(overridden);
1247 type_source = TypeSource::XsiType;
1248 }
1249 XsiTypeOutcome::Unresolved | XsiTypeOutcome::InvalidDerivation => {
1250 xsi_type_invalid = true;
1251 }
1252 }
1253 }
1254
1255 let abstract_ct_info: Option<(Option<NameId>, Option<NameId>)> = if !xsi_type_invalid {
1259 if let Some(TypeKey::Complex(k)) = type_key {
1260 self.schema_set
1261 .arenas
1262 .complex_types
1263 .get(k)
1264 .filter(|ct| ct.is_abstract)
1265 .map(|ct| (ct.name, ct.target_namespace))
1266 } else {
1267 None
1268 }
1269 } else {
1270 None
1271 };
1272 let abstract_type_invalid = abstract_ct_info.is_some();
1273
1274 let is_nil = if let Some(nil_str) = xsi_nil {
1276 nil_str == "true" || nil_str == "1"
1277 } else {
1278 false
1279 };
1280 let nillable_violation = xsi_nil.is_some() && !elem_data.nillable;
1286
1287 let (content_state, content_type) = self.init_content_model(type_key);
1289
1290 #[cfg(feature = "xsd11")]
1295 let edc_violation_a = self.dynamic_edc_violation_reason(
1296 matched_via_wildcard,
1297 local_name,
1298 namespace,
1299 type_key,
1300 Some(elem_key),
1301 );
1302
1303 let mut ev_state = ElementValidationState::new(local_name, namespace);
1305 ev_state.ns_context = Some(ns_context.clone());
1306 ev_state.element_decl = Some(elem_key);
1307 ev_state.schema_type = type_key;
1308 ev_state.type_source = Some(type_source);
1309 ev_state.content_state = content_state;
1310 ev_state.content_type = Some(content_type);
1311 ev_state.is_nil = is_nil;
1312 ev_state.validity = if xsi_type_invalid
1313 || abstract_type_invalid
1314 || nillable_violation
1315 || has_deferred_type_error
1316 {
1317 SchemaValidity::Invalid
1318 } else {
1319 SchemaValidity::Valid
1320 };
1321 #[cfg(feature = "xsd11")]
1322 if edc_violation_a.is_some() {
1323 ev_state.validity = SchemaValidity::Invalid;
1324 }
1325 ev_state.process_contents = process_contents;
1326 ev_state.strictly_assessed = (ev_state.element_decl.is_some()
1328 || ev_state.schema_type.is_some())
1329 && process_contents != ContentProcessing::Skip;
1330 #[cfg(feature = "xsd11")]
1331 {
1332 ev_state.has_type_alternatives = !self.schema_set.arenas.elements[elem_key]
1333 .alternatives
1334 .is_empty();
1335 }
1336 self.push_element(ev_state);
1337 #[cfg(feature = "xsd11")]
1338 if let Some(reason) = edc_violation_a.as_ref() {
1339 let elem_name = self.schema_set.name_table.resolve(local_name).to_string();
1340 self.report_error(
1341 "cvc-complex-type.5",
1342 format!(
1343 "Element '{}' matched a wildcard but its governing element declaration \
1344 is inconsistent with the local element declaration in the parent's \
1345 content model: {}",
1346 elem_name, reason,
1347 ),
1348 );
1349 }
1350
1351 self.emit_deferred_xsi_type_errors(xsi_type_deferred_errors);
1353
1354 if is_abstract {
1356 let elem_name = self.schema_set.name_table.resolve(local_name);
1357 self.report_error(
1358 "cvc-elt.2",
1359 format!(
1360 "Element '{}' is abstract and cannot appear in instances",
1361 elem_name
1362 ),
1363 );
1364 }
1365 if let Some((ct_name, ct_ns)) = abstract_ct_info {
1366 let type_name =
1367 crate::schema::derivation::format_type_name(self.schema_set, ct_name, ct_ns);
1368 self.report_error(
1369 "cvc-type.2",
1370 format!(
1371 "Type '{}' is abstract and cannot be used to validate an element",
1372 type_name
1373 ),
1374 );
1375 }
1376 if nillable_violation {
1377 let elem_name = self.schema_set.name_table.resolve(local_name);
1378 self.report_error(
1379 "cvc-elt.3.1",
1380 format!(
1381 "Element '{}' is not nillable but xsi:nil was specified",
1382 elem_name,
1383 ),
1384 );
1385 }
1386 if has_deferred_type_error {
1387 let msg = self.schema_set.arenas.elements[elem_key]
1388 .deferred_type_error
1389 .as_ref()
1390 .map(|d| d.message.as_str())
1391 .unwrap_or("");
1392 self.report_error("src-resolve", msg.to_string());
1393 }
1394
1395 self.advance_constraints_start_element(local_name, namespace, Some(elem_key));
1396
1397 #[cfg(feature = "xsd11")]
1399 self.detect_assertions_on_element(type_key, local_name, namespace);
1400
1401 #[allow(unused_mut)]
1403 let mut validity = if xsi_type_invalid
1404 || abstract_type_invalid
1405 || has_deferred_type_error
1406 {
1407 SchemaValidity::Invalid
1408 } else {
1409 SchemaValidity::Valid
1410 };
1411 #[cfg(feature = "xsd11")]
1412 if edc_violation_a.is_some() {
1413 validity = SchemaValidity::Invalid;
1414 }
1415 SchemaInfo {
1416 element_decl: Some(elem_key),
1417 attribute_decl: None,
1418 schema_type: type_key,
1419 member_type: None,
1420 validity,
1421 validation_attempted: ValidationAttempted::None,
1422 is_default: false,
1423 is_nil,
1424 content_type: Some(content_type),
1425 typed_value: None,
1426 normalized_value: None,
1427 schema_error_codes: Vec::new(),
1428 notation: None,
1429 deferred_by_cta: false,
1430 type_source: Some(type_source),
1431 #[cfg(feature = "xsd11")]
1432 cta_selected: false,
1433 #[cfg(feature = "xsd11")]
1434 assertion_outcome: None,
1435 }
1436 }
1437
1438 pub fn validate_attribute(
1440 &mut self,
1441 local_name: &str,
1442 namespace_uri: &str,
1443 value: &str,
1444 ) -> SchemaInfo {
1445 let name_id = self.schema_set.name_table.add(local_name);
1446 let ns_id = if namespace_uri.is_empty() {
1447 None
1448 } else {
1449 Some(self.schema_set.name_table.add(namespace_uri))
1450 };
1451 self.validate_attribute_by_id(name_id, ns_id, value)
1452 }
1453
1454 pub fn validate_attribute_by_id(
1456 &mut self,
1457 local_name: NameId,
1458 namespace: Option<NameId>,
1459 value: &str,
1460 ) -> SchemaInfo {
1461 if !self.current_state.can_validate_attribute() {
1463 self.report_error(
1464 "cvc-complex-type",
1465 format!(
1466 "Attribute validation not allowed in current state {:?}",
1467 self.current_state
1468 ),
1469 );
1470 return SchemaInfo::invalid();
1471 }
1472
1473 #[cfg(feature = "xsd11")]
1481 let fragment_attr_ref: Option<u32> = if self.is_buffering_assertions() {
1482 let local = self.schema_set.name_table.resolve(local_name);
1483 let ns = namespace
1484 .map(|id| self.schema_set.name_table.resolve(id).to_string())
1485 .unwrap_or_default();
1486 let attempt = self
1487 .fragment_builder
1488 .as_mut()
1489 .map(|b| b.attribute(&local, &ns, "", value));
1490 match attempt {
1491 Some(Ok(r)) => Some(r),
1492 Some(Err(e)) => {
1493 self.abort_assertion_buffer_op("attribute", e);
1494 None
1495 }
1496 None => None,
1497 }
1498 } else {
1499 None
1500 };
1501
1502 let mut xml_base_rebase = None;
1509 if namespace == Some(well_known::XML_NAMESPACE)
1510 && local_name == self.schema_set.name_table.add("base")
1511 {
1512 if let Some(ev) = self.validation_stack.last_mut() {
1513 if !ev.base_uri_set_by_xml_base {
1514 let xml_base = value.trim();
1515 let base_uri = resolve_base_uri(xml_base, &ev.base_uri);
1516 ev.base_uri = base_uri.clone();
1517 ev.base_uri_set_by_xml_base = true;
1518 xml_base_rebase = Some((
1519 base_uri,
1520 ev.schema_location_hint_start,
1521 ev.no_namespace_schema_location_hint_start,
1522 ));
1523 }
1524 }
1525 }
1526 if let Some((base_uri, sl_start, nnsl_start)) = xml_base_rebase {
1527 self.rebase_hint_range(sl_start, nnsl_start, &base_uri);
1528 }
1529
1530 let ev_state = match self.validation_stack.last_mut() {
1531 Some(s) => s,
1532 None => {
1533 self.report_error("cvc-complex-type", "No element context for attribute");
1534 return SchemaInfo::invalid();
1535 }
1536 };
1537
1538 if namespace == Some(well_known::XSI_NAMESPACE) {
1540 self.current_state = ValidatorState::Attribute;
1541 let ec_snapshot = self
1542 .validation_stack
1543 .last()
1544 .map(|ev| ev.error_codes.len())
1545 .unwrap_or(0);
1546 let mut result = self.validate_xsi_attribute(local_name, value);
1547 if let Some(ev) = self.validation_stack.last_mut() {
1548 ev.seen_attributes.insert((namespace, local_name));
1555 if ev.error_codes.len() > ec_snapshot {
1557 result.schema_error_codes = ev.error_codes[ec_snapshot..].to_vec();
1558 ev.error_codes.truncate(ec_snapshot);
1559 }
1560 match result.validation_attempted {
1562 ValidationAttempted::Full => {
1563 ev.any_attr_not_none = true;
1564 }
1565 ValidationAttempted::None => {
1566 ev.any_attr_not_full = true;
1567 }
1568 ValidationAttempted::Partial => {
1569 ev.any_attr_not_full = true;
1570 ev.any_attr_not_none = true;
1571 }
1572 }
1573 }
1574 self.post_process_attribute(local_name, namespace, value, &result);
1579 #[cfg(feature = "xsd11")]
1580 self.bind_fragment_attribute(fragment_attr_ref, &result);
1581 return result;
1582 }
1583
1584 if namespace == Some(well_known::XML_NAMESPACE)
1586 && self.flags.contains(ValidationFlags::ALLOW_XML_ATTRIBUTES)
1587 {
1588 self.current_state = ValidatorState::Attribute;
1589 return SchemaInfo::empty();
1590 }
1591
1592 let attr_pair = (namespace, local_name);
1594 if !ev_state.seen_attributes.insert(attr_pair) {
1595 let attr_name = self.schema_set.name_table.resolve(local_name);
1596 self.report_error(
1597 "cvc-complex-type.3",
1598 format!("Duplicate attribute '{}'", attr_name),
1599 );
1600 if let Some(s) = self.validation_stack.last_mut() {
1601 s.validity = SchemaValidity::Invalid;
1602 }
1603 self.current_state = ValidatorState::Attribute;
1604 let mut result = SchemaInfo::invalid();
1605 result.schema_error_codes = vec!["cvc-complex-type.3"];
1606 return result;
1607 }
1608
1609 #[cfg(feature = "xsd11")]
1613 if ev_state.has_type_alternatives {
1614 ev_state
1615 .collected_attributes
1616 .push((namespace, local_name, value.to_string()));
1617 self.current_state = ValidatorState::Attribute;
1618 return SchemaInfo {
1621 deferred_by_cta: true,
1622 ..SchemaInfo::empty()
1623 };
1624 }
1625
1626 let type_key = ev_state.schema_type;
1630 let process_contents = ev_state.process_contents;
1631
1632 if process_contents == ContentProcessing::Skip {
1637 self.current_state = ValidatorState::Attribute;
1638 let result = SchemaInfo::empty();
1639 self.post_process_attribute(local_name, namespace, value, &result);
1640 return result;
1641 }
1642
1643 let ct_key = match type_key {
1644 Some(TypeKey::Complex(ct)) => ct,
1645 None if process_contents != ContentProcessing::Skip => {
1646 self.schema_set.any_type_key()
1649 }
1650 _ => {
1651 self.current_state = ValidatorState::Attribute;
1659 let attr_name = self.schema_set.name_table.resolve(local_name);
1660 self.report_error(
1661 "cvc-complex-type.3.2.1",
1662 format!(
1663 "Attribute '{}' is not allowed on a simple-typed element",
1664 attr_name
1665 ),
1666 );
1667 let mut result = SchemaInfo::invalid();
1668 result.schema_error_codes = vec!["cvc-complex-type.3.2.1"];
1669 self.post_process_attribute(local_name, namespace, value, &result);
1670 return result;
1671 }
1672 };
1673
1674 self.current_state = ValidatorState::Attribute;
1675 let ec_snapshot = self
1677 .validation_stack
1678 .last()
1679 .map_or(0, |ev| ev.error_codes.len());
1680 let mut result = self.validate_attribute_against_type(ct_key, local_name, namespace, value);
1681 let attr_is_id = self.cached_xsd10_id_key.is_some_and(|id_key| {
1690 matches!(result.schema_type, Some(TypeKey::Simple(sk))
1691 if self.schema_set.derives_from(sk, id_key))
1692 });
1693 if let Some(ev) = self.validation_stack.last_mut() {
1695 if ev.error_codes.len() > ec_snapshot {
1696 result.schema_error_codes = ev.error_codes[ec_snapshot..].to_vec();
1697 ev.error_codes.truncate(ec_snapshot);
1698 }
1699 match result.validation_attempted {
1701 ValidationAttempted::Full => {
1702 ev.any_attr_not_none = true;
1703 }
1704 ValidationAttempted::None => {
1705 ev.any_attr_not_full = true;
1706 }
1707 ValidationAttempted::Partial => {
1708 ev.any_attr_not_full = true;
1709 ev.any_attr_not_none = true;
1710 }
1711 }
1712 }
1713 if attr_is_id {
1714 let already_seen = self
1715 .validation_stack
1716 .last()
1717 .is_some_and(|ev| ev.seen_id_attr);
1718 if already_seen {
1719 let attr_name = self.schema_set.name_table.resolve(local_name).to_string();
1720 self.report_error(
1721 "cvc-complex-type",
1722 format!(
1723 "Element has more than one attribute of type xs:ID (or a type \
1724 derived from xs:ID); '{}' is the second such attribute",
1725 attr_name,
1726 ),
1727 );
1728 result.validity = SchemaValidity::Invalid;
1729 } else if let Some(ev) = self.validation_stack.last_mut() {
1730 ev.seen_id_attr = true;
1731 }
1732 }
1733 #[cfg(feature = "xsd11")]
1734 self.bind_fragment_attribute(fragment_attr_ref, &result);
1735 result
1736 }
1737
1738 #[cfg(feature = "xsd11")]
1743 fn bind_fragment_attribute(&mut self, attr_ref: Option<u32>, info: &SchemaInfo) {
1744 let Some(attr_ref) = attr_ref else { return };
1745 let Some(type_key) = info.schema_type else {
1746 return;
1747 };
1748 let binding = crate::document::type_remap::NodeSchemaBinding {
1749 type_key,
1750 element_decl: None,
1751 attribute_decl: info.attribute_decl,
1752 content_type: None,
1753 };
1754 let _ = self.install_fragment_binding(attr_ref, binding, "attr binding");
1755 }
1756
1757 pub fn validate_end_of_attributes(&mut self) -> SchemaInfo {
1759 if !self.current_state.can_end_attributes() {
1760 self.report_error(
1761 "cvc-complex-type",
1762 format!(
1763 "End-of-attributes not allowed in current state {:?}",
1764 self.current_state
1765 ),
1766 );
1767 return SchemaInfo::invalid();
1768 }
1769
1770 let schema_type = match self.validation_stack.last() {
1771 Some(s) => s.schema_type,
1772 None => {
1773 self.current_state = ValidatorState::EndOfAttributes;
1774 return SchemaInfo::empty();
1775 }
1776 };
1777
1778 #[cfg(feature = "xsd11")]
1780 let has_type_alternatives = self
1781 .validation_stack
1782 .last()
1783 .is_some_and(|s| s.has_type_alternatives);
1784
1785 #[cfg(feature = "xsd11")]
1786 let (schema_type, cta_switched, cta_selected) = if has_type_alternatives {
1787 let mut st = schema_type;
1788 let mut switched = false;
1789 let mut selected = false;
1790 if let Some(ev_state) = self.validation_stack.last() {
1791 if let Some(elem_key) = ev_state.element_decl {
1792 let mut cta_attrs = ev_state.collected_attributes.clone();
1798 let explicit_names: HashSet<(Option<NameId>, NameId)> =
1799 cta_attrs.iter().map(|(ns, name, _)| (*ns, *name)).collect();
1800 for ((ns, name), val) in &ev_state.incoming_inherited {
1801 if !explicit_names.contains(&(*ns, *name)) {
1802 cta_attrs.push((*ns, *name, val.value.clone()));
1803 }
1804 }
1805 let new_type = super::alternatives::evaluate_type_alternatives(
1806 elem_key,
1807 ev_state.local_name,
1808 ev_state.namespace,
1809 &cta_attrs,
1810 ev_state.ns_context.as_ref(),
1811 Some(self.instance_base_uri.as_str()).filter(|s| !s.is_empty()),
1812 self.schema_set,
1813 );
1814 if let Some(new_type_key) = new_type {
1815 selected = true;
1816 if Some(new_type_key) != st {
1817 let (content_state, content_type) =
1818 self.init_content_model(Some(new_type_key));
1819 st = Some(new_type_key);
1820 switched = true;
1821 if let Some(ev) = self.validation_stack.last_mut() {
1822 ev.schema_type = Some(new_type_key);
1823 ev.content_state = content_state;
1824 ev.content_type = Some(content_type);
1825 }
1826 }
1827 }
1828 }
1829 }
1830 if selected {
1834 if let Some(ev) = self.validation_stack.last_mut() {
1835 ev.cta_selected = true;
1836 if ev.type_source != Some(TypeSource::XsiType) {
1837 ev.type_source = Some(TypeSource::TypeAlternative);
1838 }
1839 }
1840 }
1841 (st, switched, selected)
1842 } else {
1843 (schema_type, false, false)
1844 };
1845
1846 #[cfg(not(feature = "xsd11"))]
1847 let cta_switched = false;
1848
1849 #[cfg(feature = "xsd11")]
1852 if has_type_alternatives {
1853 if cta_switched {
1856 self.redetect_assertions_after_cta(schema_type);
1857 }
1858 self.validate_deferred_attributes(schema_type);
1859 }
1860
1861 #[cfg(feature = "xsd11")]
1863 if let Some(TypeKey::Complex(ct_key)) = schema_type {
1864 self.record_inheritable_defaults(ct_key);
1865 }
1866
1867 if let Some(TypeKey::Complex(ct_key)) = schema_type {
1869 let seen_attributes = match self.validation_stack.last() {
1870 Some(s) => s.seen_attributes.clone(),
1871 None => HashSet::new(),
1872 };
1873 let ct_data = &self.schema_set.arenas.complex_types[ct_key];
1874 if self.check_required_attributes(ct_data, &seen_attributes) {
1875 self.mark_current_invalid();
1876 }
1877 }
1878
1879 if let Some(TypeKey::Complex(ct_key)) = schema_type {
1883 let ct_data = &self.schema_set.arenas.complex_types[ct_key];
1884 let empty_seen = HashSet::new();
1885 let seen = self
1886 .validation_stack
1887 .last()
1888 .map(|s| &s.seen_attributes)
1889 .unwrap_or(&empty_seen);
1890 let has_ic = !self.active_constraints.is_empty();
1891 let builtin = self.schema_set.builtin_types();
1892 let id_key = builtin.get_by_type_code(XmlTypeCode::Id);
1893 let idref_key = builtin.get_by_type_code(XmlTypeCode::IdRef);
1894 let idrefs_key = builtin.get_by_type_code(XmlTypeCode::IdRefs);
1895 let entity_key = builtin.get_by_type_code(XmlTypeCode::Entity);
1896 let entities_key = builtin.get_by_type_code(XmlTypeCode::Entities);
1897 let mut ic_defaults: Vec<(NameId, NameId, String)> = Vec::new();
1898 let mut id_defaults: Vec<(String, TypeKey)> = Vec::new();
1899 for (i, attr_use) in ct_data.attributes.iter().enumerate() {
1900 if attr_use.use_kind == AttributeUseKind::Prohibited {
1901 continue;
1902 }
1903 let resolved = ct_data.resolved_attributes.get(i);
1904 let (attr_name, attr_ns) =
1905 self.resolve_attr_use_name_ns(attr_use, resolved, ct_data.target_namespace);
1906 if seen.contains(&(attr_ns, attr_name)) {
1907 continue;
1908 }
1909 let attr_key = resolved.and_then(|r| r.resolved_ref);
1910 let ref_decl = attr_key.and_then(|k| self.schema_set.arenas.attributes.get(k));
1911 let value = attr_use
1912 .attribute
1913 .default_value
1914 .as_deref()
1915 .or(attr_use.attribute.fixed_value.as_deref())
1916 .or_else(|| {
1917 ref_decl
1918 .and_then(|d| d.default_value.as_deref().or(d.fixed_value.as_deref()))
1919 });
1920 let Some(v) = value else { continue };
1921 if has_ic {
1922 ic_defaults.push((attr_name, attr_ns.unwrap_or(NameId(0)), v.to_string()));
1923 }
1924 let attr_type = resolved
1927 .and_then(|r| r.resolved_type)
1928 .or_else(|| ref_decl.and_then(|d| d.resolved_type));
1929 let needs_default_validation = match attr_type {
1930 Some(TypeKey::Simple(sk)) => {
1931 id_key == Some(sk)
1932 || idref_key == Some(sk)
1933 || idrefs_key == Some(sk)
1934 || entity_key == Some(sk)
1935 || entities_key == Some(sk)
1936 }
1937 _ => false,
1938 };
1939 if needs_default_validation {
1940 if let Some(tk) = attr_type {
1941 id_defaults.push((v.to_string(), tk));
1942 }
1943 }
1944 }
1945 let mut multi_node_defaults: Vec<(NameId, usize)> = Vec::new();
1947 for (name, ns, value) in ic_defaults {
1948 for cs in &mut self.active_constraints {
1949 let matches = cs.matching_fields(name, ns);
1950 for field_idx in matches {
1951 let already_matched = cs.set_field_value(field_idx, value.clone(), None);
1952 if already_matched {
1953 multi_node_defaults.push((cs.key_table.constraint_name, field_idx));
1954 }
1955 }
1956 }
1957 }
1958 for (constraint_name, field_idx) in multi_node_defaults {
1959 let cname = self
1960 .schema_set
1961 .name_table
1962 .resolve(constraint_name)
1963 .to_string();
1964 self.report_error(
1965 "cvc-identity-constraint.4.2.1",
1966 format!(
1967 "Identity constraint '{}': field {} matches more than one node",
1968 cname,
1969 field_idx + 1
1970 ),
1971 );
1972 }
1973 let default_owner = self
1976 .validation_stack
1977 .last()
1978 .map(|e| e.element_serial)
1979 .unwrap_or(0);
1980 for (value, type_key) in id_defaults {
1981 if let Ok(result) =
1982 super::simple::validate_simple_type(&value, type_key, self.schema_set)
1983 {
1984 self.collect_id_idref(&result.typed_value, &value, default_owner);
1985 self.check_entity_declared(&result.typed_value);
1986 }
1987 }
1988 }
1989
1990 #[cfg(feature = "xsd11")]
1992 if self.is_buffering_assertions() {
1993 if let Some(builder) = self.fragment_builder.as_mut() {
1994 builder.end_of_attributes();
1995 }
1996 }
1997
1998 self.current_state = ValidatorState::EndOfAttributes;
1999
2000 if cta_switched {
2004 let ev = self.validation_stack.last();
2005 let content_type = ev.and_then(|s| s.content_type);
2006 let validity = ev.map(|s| s.validity).unwrap_or(SchemaValidity::NotKnown);
2007 return SchemaInfo {
2008 schema_type,
2009 content_type,
2010 validity,
2011 type_source: ev.and_then(|s| s.type_source),
2012 #[cfg(feature = "xsd11")]
2013 cta_selected: ev.map(|s| s.cta_selected).unwrap_or(false),
2014 #[cfg(feature = "xsd11")]
2015 assertion_outcome: None,
2016 ..SchemaInfo::empty()
2017 };
2018 }
2019 #[cfg(feature = "xsd11")]
2020 if cta_selected {
2021 let ev = self.validation_stack.last();
2022 let content_type = ev.and_then(|s| s.content_type);
2023 let validity = ev.map(|s| s.validity).unwrap_or(SchemaValidity::NotKnown);
2024 return SchemaInfo {
2025 schema_type,
2026 content_type,
2027 validity,
2028 type_source: ev.and_then(|s| s.type_source),
2029 cta_selected: true,
2030 assertion_outcome: None,
2031 ..SchemaInfo::empty()
2032 };
2033 }
2034 SchemaInfo::empty()
2035 }
2036
2037 pub fn validate_text(&mut self, text: &str) {
2039 if !self.current_state.can_validate_text() {
2040 self.report_error(
2041 "cvc-complex-type",
2042 format!(
2043 "Text content not allowed in current state {:?}",
2044 self.current_state
2045 ),
2046 );
2047 return;
2048 }
2049
2050 let mut pending_errors: Vec<(&'static str, String)> = Vec::new();
2052 let has_non_ws = !text.trim().is_empty();
2053
2054 if let Some(ev_state) = self.validation_stack.last_mut() {
2055 if has_non_ws {
2057 match ev_state.content_type {
2058 Some(ContentType::Empty) => {
2059 let elem_name = self
2060 .schema_set
2061 .name_table
2062 .resolve(ev_state.local_name)
2063 .to_string();
2064 pending_errors.push((
2065 "cvc-complex-type.2.1",
2066 format!(
2067 "Element '{}' has empty content type but text was found",
2068 elem_name,
2069 ),
2070 ));
2071 }
2072 Some(ContentType::ElementOnly) => {
2073 let elem_name = self
2074 .schema_set
2075 .name_table
2076 .resolve(ev_state.local_name)
2077 .to_string();
2078 pending_errors.push((
2079 "cvc-complex-type.2.3",
2080 format!(
2081 "Element '{}' has element-only content but non-whitespace text was found",
2082 elem_name,
2083 ),
2084 ));
2085 }
2086 _ => {}
2087 }
2088 }
2089
2090 if ev_state.is_nil
2096 && (has_non_ws || matches!(ev_state.content_type, Some(ContentType::Mixed)))
2097 && !text.is_empty()
2098 {
2099 let elem_name = self
2100 .schema_set
2101 .name_table
2102 .resolve(ev_state.local_name)
2103 .to_string();
2104 pending_errors.push((
2105 "cvc-elt.3.2.1",
2106 format!(
2107 "Element '{}' is nilled but has non-empty content",
2108 elem_name,
2109 ),
2110 ));
2111 }
2112
2113 ev_state.text_content.push_str(text);
2115 ev_state.has_text = true;
2116 }
2117
2118 for (constraint, message) in pending_errors {
2120 self.report_error(constraint, message);
2121 }
2122
2123 #[cfg(feature = "xsd11")]
2125 if self.is_buffering_assertions() {
2126 if let Some(builder) = self.fragment_builder.as_mut() {
2127 builder.text(text);
2128 }
2129 }
2130
2131 self.current_state = ValidatorState::Text;
2132 }
2133
2134 pub fn validate_whitespace(&mut self, text: &str) {
2138 if !self.current_state.can_validate_text() {
2139 self.report_error(
2140 "cvc-complex-type",
2141 format!(
2142 "Whitespace not allowed in current state {:?}",
2143 self.current_state
2144 ),
2145 );
2146 return;
2147 }
2148
2149 let mut nil_violation: Option<String> = None;
2150 let mut empty_violation: Option<String> = None;
2151 if let Some(ev_state) = self.validation_stack.last_mut() {
2152 if !text.is_empty() && matches!(ev_state.content_type, Some(ContentType::Empty)) {
2157 let elem_name = self
2158 .schema_set
2159 .name_table
2160 .resolve(ev_state.local_name)
2161 .to_string();
2162 empty_violation = Some(format!(
2163 "Element '{}' has empty content type but text was found",
2164 elem_name,
2165 ));
2166 }
2167
2168 if ev_state.is_nil
2173 && !text.is_empty()
2174 && matches!(
2175 ev_state.content_type,
2176 Some(ContentType::TextOnly) | Some(ContentType::Mixed)
2177 )
2178 {
2179 let elem_name = self
2180 .schema_set
2181 .name_table
2182 .resolve(ev_state.local_name)
2183 .to_string();
2184 nil_violation = Some(format!(
2185 "Element '{}' is nilled but has non-empty content",
2186 elem_name,
2187 ));
2188 }
2189
2190 if matches!(
2192 ev_state.content_type,
2193 Some(ContentType::TextOnly) | Some(ContentType::Mixed)
2194 ) {
2195 ev_state.text_content.push_str(text);
2196 ev_state.has_text = true;
2197 }
2198 }
2199
2200 if let Some(msg) = empty_violation {
2201 self.report_error("cvc-complex-type.2.1", msg);
2202 }
2203 if let Some(msg) = nil_violation {
2204 self.report_error("cvc-elt.3.2.1", msg);
2205 }
2206
2207 #[cfg(feature = "xsd11")]
2209 if self.is_buffering_assertions() {
2210 if let Some(builder) = self.fragment_builder.as_mut() {
2211 builder.text(text);
2212 }
2213 }
2214
2215 self.current_state = ValidatorState::Whitespace;
2216 }
2217
2218 pub fn validate_end_element(&mut self) -> SchemaInfo {
2220 if !self.current_state.can_end_element() {
2221 self.report_error(
2222 "cvc-complex-type",
2223 format!(
2224 "End element not allowed in current state {:?}",
2225 self.current_state
2226 ),
2227 );
2228 return SchemaInfo::invalid();
2229 }
2230
2231 let mut ev_state = match self.validation_stack.pop() {
2232 Some(s) => s,
2233 None => {
2234 self.report_error(
2235 "cvc-complex-type",
2236 "End element called but validation stack is empty",
2237 );
2238 return SchemaInfo::invalid();
2239 }
2240 };
2241
2242 if !ev_state.is_nil {
2244 match ev_state.content_type {
2245 Some(ContentType::ElementOnly) | Some(ContentType::Mixed) => {
2246 if !ev_state.content_state.is_complete() {
2247 let elem_name = self.schema_set.name_table.resolve(ev_state.local_name);
2248 let err = errors::error(
2249 "cvc-complex-type.2.4",
2250 format!(
2251 "Element '{}' content model is incomplete: expected more child elements",
2252 elem_name,
2253 ),
2254 self.current_location.clone(),
2255 );
2256 self.report_validation_error_to(err, &mut ev_state.error_codes);
2257 ev_state.validity = SchemaValidity::Invalid;
2258 }
2259 }
2260 _ => {}
2261 }
2262 }
2263
2264 if ev_state.content_type == Some(ContentType::TextOnly) && !ev_state.is_nil {
2266 if let Some(elem_key) = ev_state.element_decl {
2270 let elem_data = &self.schema_set.arenas.elements[elem_key];
2271 if !ev_state.has_text && !ev_state.has_element_children {
2272 if let Some(default_value) = &elem_data.default_value {
2273 ev_state.is_default = true;
2274 ev_state.text_content = default_value.clone();
2275 } else if let Some(fixed_value) = &elem_data.fixed_value {
2276 ev_state.text_content = fixed_value.clone();
2280 }
2281 }
2282 }
2283
2284 if let Some(schema_type) = ev_state.schema_type {
2285 match super::simple::validate_simple_type(
2286 &ev_state.text_content,
2287 schema_type,
2288 self.schema_set,
2289 ) {
2290 Ok(result) => {
2291 ev_state.member_type = result.member_type;
2292 ev_state.typed_value = Some(result.typed_value);
2293 ev_state.normalized_value = result.normalized_value;
2294
2295 let needs_qname_check =
2305 ev_state.typed_value.as_ref().is_some_and(|v| {
2306 matches!(
2307 v.value,
2308 crate::types::value::XmlValueKind::Atomic(_)
2309 ) && (v.type_code == XmlTypeCode::QName
2310 || v.type_code == XmlTypeCode::Notation)
2311 });
2312 if needs_qname_check && ev_state.validity == SchemaValidity::Valid {
2313 if let Some(ctx) = ev_state.ns_context.as_ref() {
2314 let raw = ev_state.text_content.trim();
2315 if let Some(colon_pos) = raw.find(':') {
2316 let prefix = &raw[..colon_pos];
2317 let prefix_id = self.schema_set.name_table.add(prefix);
2318 if ctx.resolve_prefix(prefix_id).is_none() {
2319 let elem_name = self
2320 .schema_set
2321 .name_table
2322 .resolve(ev_state.local_name)
2323 .to_string();
2324 let err = errors::error(
2325 "cvc-datatype-valid.1.2.1",
2326 format!(
2327 "Element '{}' has QName value '{}' with undeclared prefix '{}'",
2328 elem_name, raw, prefix
2329 ),
2330 self.current_location.clone(),
2331 );
2332 self.report_validation_error_to(
2333 err,
2334 &mut ev_state.error_codes,
2335 );
2336 ev_state.validity = SchemaValidity::Invalid;
2337 }
2338 }
2339 }
2340 }
2341 }
2342 Err(err) => {
2343 self.report_validation_error_to(err, &mut ev_state.error_codes);
2344 ev_state.validity = SchemaValidity::Invalid;
2345 }
2346 }
2347 }
2348
2349 if let Some(elem_key) = ev_state.element_decl {
2355 let elem_data = &self.schema_set.arenas.elements[elem_key];
2356 if let Some(fixed) = &elem_data.fixed_value {
2357 let matches = if let Some(ref typed) = ev_state.typed_value {
2358 super::simple::fixed_matches_typed(
2359 &ev_state.text_content,
2360 typed,
2361 fixed,
2362 ev_state.schema_type,
2363 self.schema_set,
2364 )
2365 } else {
2366 super::simple::fixed_values_equal(
2367 &ev_state.text_content,
2368 fixed,
2369 ev_state.schema_type,
2370 self.schema_set,
2371 )
2372 };
2373 if !matches {
2374 let elem_name = self.schema_set.name_table.resolve(ev_state.local_name);
2375 let err = errors::error(
2376 "cvc-elt.5.2.2",
2377 format!(
2378 "Element '{}' has fixed value '{}' but actual value is '{}'",
2379 elem_name, fixed, ev_state.text_content,
2380 ),
2381 self.current_location.clone(),
2382 );
2383 self.report_validation_error_to(err, &mut ev_state.error_codes);
2384 ev_state.validity = SchemaValidity::Invalid;
2385 }
2386 }
2387 }
2388 }
2389
2390 if ev_state.content_type == Some(ContentType::Mixed) && !ev_state.is_nil {
2392 if let Some(elem_key) = ev_state.element_decl {
2393 let elem_data = &self.schema_set.arenas.elements[elem_key];
2394 if let Some(ref fixed) = elem_data.fixed_value {
2395 let elem_name = self.schema_set.name_table.resolve(ev_state.local_name);
2396 if ev_state.has_element_children {
2397 let err = errors::error(
2399 "cvc-elt.5.2.2.1",
2400 format!(
2401 "Element '{}' has fixed value '{}' but contains element children",
2402 elem_name, fixed,
2403 ),
2404 self.current_location.clone(),
2405 );
2406 self.report_validation_error_to(err, &mut ev_state.error_codes);
2407 ev_state.validity = SchemaValidity::Invalid;
2408 } else if ev_state.has_text && ev_state.text_content != *fixed {
2409 let err = errors::error(
2411 "cvc-elt.5.2.2.2",
2412 format!(
2413 "Element '{}' has fixed value '{}' but actual value is '{}'",
2414 elem_name, fixed, ev_state.text_content,
2415 ),
2416 self.current_location.clone(),
2417 );
2418 self.report_validation_error_to(err, &mut ev_state.error_codes);
2419 ev_state.validity = SchemaValidity::Invalid;
2420 }
2421 }
2422 }
2423 }
2424
2425 #[cfg(feature = "xsd11")]
2427 let type_has_assertions = matches!(ev_state.schema_type,
2428 Some(TypeKey::Complex(ct_key)) if has_inherited_assertions(ct_key, &self.schema_set.arenas));
2429 #[cfg(feature = "xsd11")]
2430 let mut assertion_outcome: Option<AssertionOutcome> = None;
2431
2432 #[cfg(feature = "xsd11")]
2433 'assertion_eval: {
2434 debug_assert!(
2435 self.flags.contains(ValidationFlags::PROCESS_ASSERTIONS)
2436 == (self.assertion_source == AssertionSource::FragmentBuffer),
2437 "PROCESS_ASSERTIONS / AssertionSource invariant violated at end-element"
2438 );
2439
2440 if !self.is_buffering_assertions() {
2441 if self.fragment_builder.is_some() {
2445 self.fragment_builder.take();
2446 self.pending_assertion_frames.clear();
2447 if let Some(arena) = self.fragment_arena.as_mut() {
2448 arena.reset();
2449 }
2450 }
2451 if type_has_assertions {
2452 assertion_outcome = Some(AssertionOutcome::NotEvaluated);
2453 }
2454 break 'assertion_eval;
2455 }
2456
2457 if let Some(builder) = self.fragment_builder.as_mut() {
2459 if let Err(e) = builder.end_element() {
2460 self.abort_assertion_buffer_op("end_element", e);
2461 ev_state.validity = SchemaValidity::Invalid;
2462 break 'assertion_eval;
2463 }
2464 }
2465
2466 if ev_state.owns_assertion_buffer {
2467 let frame = match self.assertion_buffer_stack.pop() {
2469 Some(f) => f,
2470 None => {
2471 self.abort_assertion_buffering(
2473 "Internal: assertion buffer stack underflow".into(),
2474 );
2475 ev_state.validity = SchemaValidity::Invalid;
2476 break 'assertion_eval;
2477 }
2478 };
2479
2480 if self.assertion_buffer_stack.is_empty() {
2481 let builder = match self.fragment_builder.take() {
2483 Some(b) => b,
2484 None => {
2485 self.pending_assertion_frames.clear();
2487 if let Some(arena) = self.fragment_arena.as_mut() {
2488 arena.reset();
2489 }
2490 break 'assertion_eval;
2491 }
2492 };
2493 match builder.finalize() {
2494 Ok(doc) => {
2495 let pending = std::mem::take(&mut self.pending_assertion_frames);
2497 for pf in &pending {
2498 let errs = evaluate_complex_type_assertions(
2499 &doc,
2500 pf.element_ref,
2501 pf.complex_type_key,
2502 self.schema_set,
2503 );
2504 self.report_assertion_errors_deferred(
2505 errs,
2506 &pf.element_path,
2507 &pf.location,
2508 );
2509 }
2510 let errs = evaluate_complex_type_assertions(
2512 &doc,
2513 frame.element_ref,
2514 frame.complex_type_key,
2515 self.schema_set,
2516 );
2517 if errs.is_empty() {
2518 assertion_outcome = Some(AssertionOutcome::Passed);
2519 } else {
2520 assertion_outcome = Some(AssertionOutcome::Failed);
2521 }
2522 self.report_assertion_errors(errs, &mut ev_state);
2523 }
2524 Err(e) => {
2525 self.pending_assertion_frames.clear();
2529 let err = errors::error(
2530 "cvc-assertion",
2531 format!("Failed to finalize assertion fragment: {}", e),
2532 self.current_location.clone(),
2533 );
2534 self.report_validation_error_to(err, &mut ev_state.error_codes);
2535 ev_state.validity = SchemaValidity::Invalid;
2536 assertion_outcome = Some(AssertionOutcome::Failed);
2537 }
2538 }
2539 if let Some(arena) = self.fragment_arena.as_mut() {
2541 arena.reset();
2542 }
2543 } else {
2544 let mut deferred = frame;
2546 deferred.element_path = self.element_path.clone();
2547 deferred.location = self.current_location.clone();
2548 self.pending_assertion_frames.push(deferred);
2549 assertion_outcome = Some(AssertionOutcome::NotEvaluated);
2550 }
2551 }
2552 }
2553
2554 #[cfg(feature = "xsd11")]
2556 if assertion_outcome.is_none() && type_has_assertions {
2557 assertion_outcome = Some(AssertionOutcome::NotEvaluated);
2558 }
2559
2560 let is_complex_content = matches!(
2562 ev_state.content_type,
2563 Some(ContentType::ElementOnly) | Some(ContentType::Mixed)
2564 );
2565 let ic_typed_value = Self::resolve_ic_qname_value(
2568 &ev_state.typed_value,
2569 &ev_state.text_content,
2570 ev_state.ns_context.as_ref(),
2571 &self.schema_set.name_table,
2572 );
2573 let ic_ref = ic_typed_value.as_ref().or(ev_state.typed_value.as_ref());
2574 self.process_constraints_end_element(
2575 &ev_state.text_content,
2576 ic_ref,
2577 ev_state.is_nil,
2578 is_complex_content,
2579 &mut ev_state.error_codes,
2580 );
2581
2582 if let Some(Some(scope_map)) = self.ic_scope_tables.pop() {
2584 if let Some(parent_slot) = self.ic_scope_tables.last_mut() {
2585 let parent_map = parent_slot.get_or_insert_with(HashMap::new);
2586 for (ic_key, key_table) in scope_map {
2587 parent_map
2588 .entry(ic_key)
2589 .and_modify(|existing| {
2590 existing.sequences.extend(key_table.sequences.clone())
2591 })
2592 .or_insert(key_table);
2593 }
2594 } else {
2595 self.final_ic_tables = Some(scope_map);
2597 }
2598 }
2599
2600 if !self.deferred_keyrefs.is_empty() {
2602 let pending = std::mem::take(&mut self.deferred_keyrefs);
2603 let name_table = &self.schema_set.name_table;
2604 let scope_empty = self.ic_scope_tables.is_empty();
2605 let mut still_deferred = Vec::new();
2606 let mut deferred_errors = Vec::new();
2607 for (keyref_table, refer_key) in pending {
2608 let target = refer_key.and_then(|rk| {
2609 self.ic_scope_tables
2610 .last()
2611 .and_then(|slot| slot.as_ref())
2612 .and_then(|map| map.get(&rk))
2613 });
2614 match target {
2615 Some(target_table) => {
2616 let errs = keyref_table.check_keyref_against(target_table, name_table);
2617 deferred_errors.extend(errs);
2618 }
2619 None => {
2620 if scope_empty {
2621 let keyref_name = name_table.resolve(keyref_table.constraint_name);
2623 let refer_display = self
2624 .compiled_constraints
2625 .get(&keyref_table.ic_key)
2626 .and_then(|opt| opt.as_ref())
2627 .and_then(|compiled| {
2628 compiled.refer.as_ref().map(|refer| {
2629 let refer_ns =
2630 refer.namespace.or(compiled.target_namespace);
2631 format_resolved_qname(
2632 name_table,
2633 refer_ns,
2634 refer.local_name,
2635 )
2636 })
2637 })
2638 .unwrap_or_else(|| "<unknown>".to_string());
2639 deferred_errors.push(errors::error(
2640 "cvc-identity-constraint.4.3",
2641 format!(
2642 "Keyref '{}' references unknown constraint '{}'",
2643 keyref_name, refer_display
2644 ),
2645 None,
2646 ));
2647 } else {
2648 still_deferred.push((keyref_table, refer_key));
2649 }
2650 }
2651 }
2652 }
2653 self.deferred_keyrefs = still_deferred;
2654 for err in deferred_errors {
2658 self.sink.on_error(err);
2659 }
2660 }
2661
2662 if let Some(ref tv) = ev_state.typed_value {
2667 let parent_serial = self
2668 .validation_stack
2669 .last()
2670 .map(|e| e.element_serial)
2671 .unwrap_or(ev_state.element_serial); self.collect_id_idref(tv, &ev_state.text_content, parent_serial);
2673 self.check_entity_declared(tv);
2674 }
2675
2676 self.pop_element_path();
2678
2679 let validity = ev_state.validity;
2680 self.current_state = ValidatorState::EndElement;
2681
2682 let all_full = !ev_state.any_child_not_full && !ev_state.any_attr_not_full;
2684 let all_none = !ev_state.any_child_not_none && !ev_state.any_attr_not_none;
2685 let validation_attempted = if ev_state.strictly_assessed && all_full {
2686 ValidationAttempted::Full
2687 } else if !ev_state.strictly_assessed && all_none {
2688 ValidationAttempted::None
2689 } else {
2690 ValidationAttempted::Partial
2691 };
2692
2693 if let Some(parent) = self.validation_stack.last_mut() {
2695 match validation_attempted {
2696 ValidationAttempted::Full => {
2697 parent.any_child_not_none = true;
2698 }
2699 ValidationAttempted::None => {
2700 parent.any_child_not_full = true;
2701 }
2702 ValidationAttempted::Partial => {
2703 parent.any_child_not_full = true;
2704 parent.any_child_not_none = true;
2705 }
2706 }
2707 }
2708
2709 SchemaInfo {
2710 element_decl: ev_state.element_decl,
2711 attribute_decl: None,
2712 schema_type: ev_state.schema_type,
2713 member_type: ev_state.member_type,
2714 validity,
2715 validation_attempted,
2716 is_default: ev_state.is_default,
2717 is_nil: ev_state.is_nil,
2718 content_type: ev_state.content_type,
2719 typed_value: ev_state.typed_value,
2720 normalized_value: ev_state.normalized_value,
2721 schema_error_codes: ev_state.error_codes,
2722 notation: ev_state.notation,
2723 deferred_by_cta: false,
2724 type_source: ev_state.type_source,
2725 #[cfg(feature = "xsd11")]
2726 cta_selected: ev_state.cta_selected,
2727 #[cfg(feature = "xsd11")]
2728 assertion_outcome,
2729 }
2730 }
2731
2732 pub fn end_validation(&mut self) -> Result<(), ValidationError> {
2736 if !self.current_state.can_finish() {
2737 return Err(errors::error(
2738 "cvc-complex-type",
2739 format!(
2740 "end_validation called in invalid state {:?}",
2741 self.current_state
2742 ),
2743 self.current_location.clone(),
2744 ));
2745 }
2746
2747 if !self.validation_stack.is_empty() {
2748 return Err(errors::error(
2749 "cvc-complex-type",
2750 format!(
2751 "Validation ended with {} unclosed elements",
2752 self.validation_stack.len()
2753 ),
2754 self.current_location.clone(),
2755 ));
2756 }
2757
2758 for (idref_value, location, element_path) in &self.pending_idrefs {
2760 if !self.id_values.contains_key(idref_value) {
2761 self.sink.on_error(errors::error_with_path(
2762 "cvc-id.1",
2763 format!(
2764 "IDREF '{}' does not match any ID in the document",
2765 idref_value
2766 ),
2767 location.clone(),
2768 element_path,
2769 ));
2770 }
2771 }
2772
2773 #[cfg(feature = "xsd11")]
2774 {
2775 debug_assert!(
2776 self.assertion_buffer_stack.is_empty(),
2777 "assertion_buffer_stack not empty at end_validation"
2778 );
2779 debug_assert!(
2780 self.fragment_builder.is_none(),
2781 "fragment_builder not None at end_validation"
2782 );
2783 debug_assert!(
2784 self.pending_assertion_frames.is_empty(),
2785 "pending_assertion_frames not empty at end_validation"
2786 );
2787 }
2788
2789 self.current_state = ValidatorState::Finish;
2790 Ok(())
2791 }
2792
2793 pub fn get_expected_elements(&self) -> Vec<ExpectedElement> {
2799 let ev_state = match self.validation_stack.last() {
2800 Some(s) => s,
2801 None => return Vec::new(),
2802 };
2803
2804 match &ev_state.content_state {
2805 ContentValidatorState::Nfa {
2806 nfa, active_states, ..
2807 } => active_states
2808 .expected_element_terms(nfa)
2809 .into_iter()
2810 .map(|(name, namespace, element_key)| ExpectedElement {
2811 local_name: name,
2812 namespace,
2813 element_key,
2814 })
2815 .collect(),
2816 ContentValidatorState::AllGroup { model, state, .. } => {
2817 let mut result = Vec::new();
2818 for (i, particle) in model.particles.iter().enumerate() {
2819 if state.can_accept(model, i) {
2820 if let crate::compiler::NfaTerm::Element {
2821 ref name,
2822 ref namespace,
2823 ref element_key,
2824 ..
2825 } = particle.term
2826 {
2827 result.push(ExpectedElement {
2828 local_name: *name,
2829 namespace: *namespace,
2830 element_key: *element_key,
2831 });
2832 }
2833 }
2834 }
2835 result
2836 }
2837 #[cfg(feature = "xsd11")]
2838 ContentValidatorState::AllGroupExtension {
2839 model,
2840 state,
2841 extension_nfa,
2842 phase,
2843 } => {
2844 use super::content::AllGroupExtPhase;
2845
2846 let mut result = Vec::new();
2847 match phase {
2848 AllGroupExtPhase::AllGroup => {
2849 for (i, particle) in model.particles.iter().enumerate() {
2851 if state.can_accept(model, i) {
2852 if let crate::compiler::NfaTerm::Element {
2853 ref name,
2854 ref namespace,
2855 ref element_key,
2856 ..
2857 } = particle.term
2858 {
2859 result.push(ExpectedElement {
2860 local_name: *name,
2861 namespace: *namespace,
2862 element_key: *element_key,
2863 });
2864 }
2865 }
2866 }
2867 if state.is_satisfied(model) {
2869 let initial = crate::compiler::ActiveStates::from_nfa(extension_nfa);
2870 for (name, namespace, element_key) in
2871 initial.expected_element_terms(extension_nfa)
2872 {
2873 result.push(ExpectedElement {
2874 local_name: name,
2875 namespace,
2876 element_key,
2877 });
2878 }
2879 }
2880 }
2881 AllGroupExtPhase::Nfa(active_states) => {
2882 for (name, namespace, element_key) in
2883 active_states.expected_element_terms(extension_nfa)
2884 {
2885 result.push(ExpectedElement {
2886 local_name: name,
2887 namespace,
2888 element_key,
2889 });
2890 }
2891 }
2892 }
2893 result
2894 }
2895 _ => Vec::new(),
2896 }
2897 }
2898
2899 pub fn get_expected_attributes(&self) -> Vec<ExpectedAttribute> {
2901 let ev_state = match self.validation_stack.last() {
2902 Some(s) => s,
2903 None => return Vec::new(),
2904 };
2905
2906 let ct_key = match ev_state.schema_type {
2907 Some(TypeKey::Complex(ct)) => ct,
2908 _ => return Vec::new(),
2909 };
2910
2911 let ct_data = &self.schema_set.arenas.complex_types[ct_key];
2912 let mut result = Vec::new();
2913
2914 for (i, attr_use) in ct_data.attributes.iter().enumerate() {
2915 let use_kind = attr_use.use_kind;
2916 if use_kind == AttributeUseKind::Prohibited {
2917 continue;
2918 }
2919 let resolved = ct_data.resolved_attributes.get(i);
2920 let (attr_name, attr_ns) =
2921 self.resolve_attr_use_name_ns(attr_use, resolved, ct_data.target_namespace);
2922 let attr_key = resolved.and_then(|r| r.resolved_ref);
2923
2924 result.push(ExpectedAttribute {
2925 local_name: attr_name,
2926 namespace: attr_ns,
2927 attribute_key: attr_key,
2928 required: use_kind == AttributeUseKind::Required,
2929 });
2930 }
2931
2932 for ga in self.collect_group_attributes(ct_data) {
2934 if ga.use_kind == AttributeUseKind::Prohibited {
2935 continue;
2936 }
2937 result.push(ExpectedAttribute {
2938 local_name: ga.name,
2939 namespace: ga.namespace,
2940 attribute_key: ga.attr_key,
2941 required: ga.use_kind == AttributeUseKind::Required,
2942 });
2943 }
2944
2945 result
2946 }
2947
2948 pub fn get_default_attributes(&self) -> Vec<DefaultAttribute> {
2950 let ev_state = match self.validation_stack.last() {
2951 Some(s) => s,
2952 None => return Vec::new(),
2953 };
2954
2955 let ct_key = match ev_state.schema_type {
2956 Some(TypeKey::Complex(ct)) => ct,
2957 _ => return Vec::new(),
2958 };
2959
2960 let ct_data = &self.schema_set.arenas.complex_types[ct_key];
2961 let mut result = Vec::new();
2962
2963 for (i, attr_use) in ct_data.attributes.iter().enumerate() {
2964 if attr_use.use_kind == AttributeUseKind::Prohibited {
2965 continue;
2966 }
2967
2968 let resolved = ct_data.resolved_attributes.get(i);
2969 let (attr_name, attr_ns) =
2970 self.resolve_attr_use_name_ns(attr_use, resolved, ct_data.target_namespace);
2971 let attr_key = resolved.and_then(|r| r.resolved_ref);
2972
2973 if ev_state.seen_attributes.contains(&(attr_ns, attr_name)) {
2975 continue;
2976 }
2977
2978 let default = attr_use.attribute.default_value.as_deref().or_else(|| {
2980 attr_key
2981 .and_then(|k| self.schema_set.arenas.attributes.get(k))
2982 .and_then(|d| d.default_value.as_deref())
2983 });
2984 if let Some(value) = default {
2985 if let Some(attr_key) = attr_key {
2986 result.push(DefaultAttribute {
2987 local_name: attr_name,
2988 namespace: attr_ns,
2989 attribute_key: attr_key,
2990 value: value.to_string(),
2991 });
2992 }
2993 }
2994 }
2995
2996 for ga in self.collect_group_attributes(ct_data) {
2998 if ga.use_kind == AttributeUseKind::Prohibited {
2999 continue;
3000 }
3001 if ev_state.seen_attributes.contains(&(ga.namespace, ga.name)) {
3002 continue;
3003 }
3004 if let Some(value) = ga.default_value {
3005 if let Some(attr_key) = ga.attr_key {
3006 result.push(DefaultAttribute {
3007 local_name: ga.name,
3008 namespace: ga.namespace,
3009 attribute_key: attr_key,
3010 value,
3011 });
3012 }
3013 }
3014 }
3015
3016 result
3017 }
3018
3019 #[cfg(feature = "xsd11")]
3029 pub fn get_inherited_attributes(&self) -> Vec<InheritedAttribute> {
3030 let ev_state = match self.validation_stack.last() {
3031 Some(s) => s,
3032 None => return Vec::new(),
3033 };
3034
3035 if ev_state.process_contents == ContentProcessing::Skip {
3037 return Vec::new();
3038 }
3039
3040 let mut result = Vec::new();
3041 for ((ns, name), val) in &ev_state.incoming_inherited {
3042 result.push(InheritedAttribute {
3043 local_name: *name,
3044 namespace: *ns,
3045 attribute_key: val.attribute_key,
3046 value: val.value.clone(),
3047 });
3048 }
3049 result
3050 }
3051
3052 pub fn content_processing(&self) -> ContentProcessing {
3054 self.validation_stack
3055 .last()
3056 .map(|s| s.process_contents)
3057 .unwrap_or(ContentProcessing::Strict)
3058 }
3059
3060 fn push_element(&mut self, mut ev_state: ElementValidationState) {
3066 ev_state.element_serial = self.next_element_serial;
3068 self.next_element_serial += 1;
3069
3070 if self.schema_set.is_xsd10() {
3074 self.first_namespace_use
3075 .entry(ev_state.namespace)
3076 .or_insert(ev_state.element_serial);
3077 }
3078
3079 let local_name = self.schema_set.name_table.resolve(ev_state.local_name);
3080 if !self.element_path.is_empty() || self.validation_stack.is_empty() {
3081 self.element_path.push('/');
3082 }
3083 self.element_path.push_str(&local_name);
3084
3085 ev_state.base_uri = match self.validation_stack.last() {
3088 Some(parent) => parent.base_uri.clone(),
3089 None => self.instance_base_uri.clone(),
3090 };
3091 ev_state.schema_location_hint_start = self.schema_location_hints.len();
3092 ev_state.no_namespace_schema_location_hint_start =
3093 self.no_namespace_schema_location_hints.len();
3094
3095 self.validation_stack.push(ev_state);
3096 self.ic_scope_tables.push(None);
3097
3098 #[cfg(feature = "xsd11")]
3107 {
3108 let len = self.validation_stack.len();
3109 if len >= 2 {
3110 let parent_pc = self.validation_stack[len - 2].process_contents;
3111 let child_pc = self.validation_stack[len - 1].process_contents;
3112 if parent_pc != ContentProcessing::Skip && child_pc != ContentProcessing::Skip {
3113 let from_parent = self.validation_stack[len - 2].outgoing_inherited.clone();
3114 self.validation_stack[len - 1].incoming_inherited = from_parent.clone();
3115 self.validation_stack[len - 1].outgoing_inherited = from_parent;
3116 }
3117 }
3118 }
3119
3120 if self.current_state == ValidatorState::None {
3121 self.current_state = ValidatorState::Start;
3122 }
3123 self.current_state = ValidatorState::Element;
3124 }
3125
3126 fn pop_element_path(&mut self) {
3128 if let Some(pos) = self.element_path.rfind('/') {
3129 self.element_path.truncate(pos);
3130 } else {
3131 self.element_path.clear();
3132 }
3133 }
3134
3135 fn emit_error(&mut self, err: ValidationError) {
3138 if let Some(ev) = self.validation_stack.last_mut() {
3139 ev.error_codes.push(err.constraint);
3140 }
3141 self.sink.on_error(err);
3142 }
3143
3144 fn emit_error_to(&mut self, err: ValidationError, codes: &mut Vec<&'static str>) {
3148 codes.push(err.constraint);
3149 self.sink.on_error(err);
3150 }
3151
3152 fn report_error(&mut self, constraint: &'static str, message: impl Into<String>) {
3154 let err = errors::error(constraint, message, self.current_location.clone());
3155 let err = if self.element_path.is_empty() {
3156 err
3157 } else {
3158 err.with_path(self.element_path.clone())
3159 };
3160 self.emit_error(err);
3161 }
3162
3163 fn enrich(&self, err: ValidationError) -> ValidationError {
3167 let err = match &self.current_location {
3168 Some(loc) => err.with_location(loc.clone()),
3169 None => err,
3170 };
3171 if self.element_path.is_empty() {
3172 err
3173 } else {
3174 err.with_path(self.element_path.clone())
3175 }
3176 }
3177
3178 fn report_validation_error_to(&mut self, err: ValidationError, codes: &mut Vec<&'static str>) {
3182 let err = self.enrich(err);
3183 self.emit_error_to(err, codes);
3184 }
3185
3186 fn report_validation_error(&mut self, err: ValidationError) {
3188 let err = self.enrich(err);
3189 self.emit_error(err);
3190 }
3191
3192 fn mark_current_invalid(&mut self) {
3194 if let Some(s) = self.validation_stack.last_mut() {
3195 s.validity = SchemaValidity::Invalid;
3196 }
3197 }
3198
3199 fn current_element_base_uri(&self) -> String {
3202 self.validation_stack
3203 .last()
3204 .map(|ev| ev.base_uri.clone())
3205 .unwrap_or_else(|| self.instance_base_uri.clone())
3206 }
3207
3208 fn rebase_hint_range(&mut self, sl_start: usize, nnsl_start: usize, base_uri: &str) {
3209 for hint in &mut self.schema_location_hints[sl_start..] {
3210 hint.base_uri = base_uri.to_string();
3211 }
3212 for hint in &mut self.no_namespace_schema_location_hints[nnsl_start..] {
3213 hint.base_uri = base_uri.to_string();
3214 }
3215 }
3216
3217 fn validate_xsi_attribute(&mut self, local_name: NameId, value: &str) -> SchemaInfo {
3228 let builtin = self.schema_set.builtin_types();
3229 if local_name == well_known::XSI_TYPE {
3230 let type_key = TypeKey::Simple(builtin.qname);
3233 let attr_key = builtin.xsi_type_attr;
3234 return self.validate_xsi_simple_value(value, type_key, attr_key);
3235 }
3236 if local_name == well_known::XSI_NIL {
3237 let type_key = TypeKey::Simple(builtin.boolean);
3238 let attr_key = builtin.xsi_nil_attr;
3239 return self.validate_xsi_simple_value(value, type_key, attr_key);
3240 }
3241 if local_name == well_known::XSI_SCHEMA_LOCATION {
3242 return self.validate_xsi_schema_location(value);
3243 }
3244 if local_name == well_known::XSI_NO_NAMESPACE_SCHEMA_LOCATION {
3245 return self.validate_xsi_no_ns_schema_location(value);
3246 }
3247 self.validate_unknown_xsi_attribute(local_name, value)
3249 }
3250
3251 fn validate_unknown_xsi_attribute(&mut self, local_name: NameId, value: &str) -> SchemaInfo {
3253 let ct_key = match self.validation_stack.last() {
3254 Some(ev) => match ev.schema_type {
3255 Some(TypeKey::Complex(ct)) => ct,
3256 _ => return SchemaInfo::empty(),
3257 },
3258 None => return SchemaInfo::empty(),
3259 };
3260 self.validate_attribute_against_type(
3261 ct_key,
3262 local_name,
3263 Some(well_known::XSI_NAMESPACE),
3264 value,
3265 )
3266 }
3267
3268 fn validate_xsi_simple_value(
3270 &mut self,
3271 value: &str,
3272 type_key: TypeKey,
3273 attr_key: AttributeKey,
3274 ) -> SchemaInfo {
3275 match super::simple::validate_simple_type(value, type_key, self.schema_set) {
3276 Ok(result) => SchemaInfo {
3277 element_decl: None,
3278 attribute_decl: Some(attr_key),
3279 schema_type: Some(type_key),
3280 member_type: result.member_type,
3281 validity: SchemaValidity::Valid,
3282 validation_attempted: ValidationAttempted::Full,
3283 is_default: false,
3284 is_nil: false,
3285 content_type: None,
3286 typed_value: Some(result.typed_value),
3287 normalized_value: result.normalized_value,
3288 schema_error_codes: Vec::new(),
3289 notation: None,
3290 deferred_by_cta: false,
3291 type_source: None,
3292 #[cfg(feature = "xsd11")]
3293 cta_selected: false,
3294 #[cfg(feature = "xsd11")]
3295 assertion_outcome: None,
3296 },
3297 Err(err) => {
3298 self.report_validation_error(err);
3299 SchemaInfo {
3300 attribute_decl: Some(attr_key),
3301 schema_type: Some(type_key),
3302 validity: SchemaValidity::Invalid,
3303 validation_attempted: ValidationAttempted::Full,
3304 ..SchemaInfo::empty()
3305 }
3306 }
3307 }
3308 }
3309
3310 fn validate_xsi_schema_location(&mut self, value: &str) -> SchemaInfo {
3313 let builtin = self.schema_set.builtin_types();
3314 let any_uri_key = TypeKey::Simple(builtin.any_uri);
3315 let list_type_key = TypeKey::Simple(builtin.xsi_schema_location_type);
3316 let attr_key = builtin.xsi_schema_location_attr;
3317
3318 let tokens: Vec<&str> = value.split_whitespace().collect();
3319 let mut validity = SchemaValidity::Valid;
3320
3321 if !tokens.len().is_multiple_of(2) {
3323 self.report_error(
3324 "cvc-schema-location",
3325 format!(
3326 "xsi:schemaLocation value must contain an even number of URI tokens, \
3327 but found {} tokens",
3328 tokens.len()
3329 ),
3330 );
3331 validity = SchemaValidity::Invalid;
3332 }
3333
3334 for token in &tokens {
3336 if let Err(err) =
3337 super::simple::validate_simple_type(token, any_uri_key, self.schema_set)
3338 {
3339 self.report_validation_error(err);
3340 validity = SchemaValidity::Invalid;
3341 }
3342 }
3343
3344 let base_uri = self.current_element_base_uri();
3355 let xsd10 = self.schema_set.is_xsd10();
3356 let current_serial = self.validation_stack.last().map(|ev| ev.element_serial);
3357 for pair in tokens.chunks_exact(2) {
3358 let ns_str = pair[0];
3359 let loc_str = pair[1];
3360
3361 if xsd10 {
3362 if let Some(serial) = current_serial {
3363 let ns_id: Option<NameId> = if ns_str.is_empty() {
3364 None
3365 } else {
3366 Some(self.schema_set.name_table.add(ns_str))
3367 };
3368 if let Some(&first_serial) = self.first_namespace_use.get(&ns_id) {
3369 if first_serial != serial
3370 && !self
3371 .schema_location_hints
3372 .iter()
3373 .any(|h| h.namespace == ns_str && h.location == loc_str)
3374 {
3375 self.report_error(
3376 "sch-late-component",
3377 format!(
3378 "xsi:schemaLocation announces a new schema document \
3379 '{loc_str}' for namespace '{ns_str}', but an item \
3380 from that namespace has already been encountered \
3381 earlier in the instance document (XSD 1.0 §4.3.2 \
3382 Rule 4 'late-arriving components')"
3383 ),
3384 );
3385 validity = SchemaValidity::Invalid;
3386 }
3387 }
3388 }
3389 }
3390
3391 self.schema_location_hints.push(SchemaLocationHint {
3392 namespace: ns_str.to_string(),
3393 location: loc_str.to_string(),
3394 base_uri: base_uri.clone(),
3395 });
3396 }
3397
3398 SchemaInfo {
3399 element_decl: None,
3400 attribute_decl: Some(attr_key),
3401 schema_type: Some(list_type_key),
3402 member_type: None,
3403 validity,
3404 validation_attempted: ValidationAttempted::Full,
3405 is_default: false,
3406 is_nil: false,
3407 content_type: None,
3408 typed_value: None,
3409 normalized_value: if tokens.is_empty() {
3410 None
3411 } else {
3412 Some(tokens.join(" "))
3413 },
3414 schema_error_codes: Vec::new(),
3415 notation: None,
3416 deferred_by_cta: false,
3417 type_source: None,
3418 #[cfg(feature = "xsd11")]
3419 cta_selected: false,
3420 #[cfg(feature = "xsd11")]
3421 assertion_outcome: None,
3422 }
3423 }
3424
3425 fn validate_xsi_no_ns_schema_location(&mut self, value: &str) -> SchemaInfo {
3427 let builtin = self.schema_set.builtin_types();
3428 let any_uri_key = TypeKey::Simple(builtin.any_uri);
3429 let attr_key = builtin.xsi_no_namespace_schema_location_attr;
3430 let mut result = self.validate_xsi_simple_value(value, any_uri_key, attr_key);
3431
3432 let trimmed = value.trim();
3433 if !trimmed.is_empty() {
3434 if self.schema_set.is_xsd10() {
3440 let current_serial = self.validation_stack.last().map(|ev| ev.element_serial);
3441 if let Some(serial) = current_serial {
3442 if let Some(&first_serial) = self.first_namespace_use.get(&None) {
3443 if first_serial != serial
3444 && !self
3445 .no_namespace_schema_location_hints
3446 .iter()
3447 .any(|h| h.location == trimmed)
3448 {
3449 self.report_error(
3450 "sch-late-component",
3451 format!(
3452 "xsi:noNamespaceSchemaLocation announces a new schema \
3453 document '{trimmed}' for the absent namespace, but \
3454 an item from the absent namespace has already been \
3455 encountered earlier in the instance document (XSD 1.0 \
3456 §4.3.2 Rule 4 'late-arriving components')"
3457 ),
3458 );
3459 result.validity = SchemaValidity::Invalid;
3460 }
3461 }
3462 }
3463 }
3464
3465 self.no_namespace_schema_location_hints
3466 .push(NoNamespaceSchemaLocationHint {
3467 location: trimmed.to_string(),
3468 base_uri: self.current_element_base_uri(),
3469 });
3470 }
3471
3472 result
3473 }
3474
3475 fn resolve_refer_key(
3484 &self,
3485 refer_local_name: NameId,
3486 refer_ns: Option<NameId>,
3487 ) -> Option<IdentityConstraintKey> {
3488 for (key, ic_data) in &self.schema_set.arenas.identity_constraints {
3489 if ic_data.kind == IdentityKind::Keyref {
3490 continue;
3491 }
3492 if ic_data.name != refer_local_name {
3493 continue;
3494 }
3495 let ic_target_ns = ic_data
3496 .source
3497 .as_ref()
3498 .and_then(|s| self.schema_set.documents.get(s.doc_id as usize))
3499 .and_then(|d| d.target_namespace);
3500 if ic_target_ns == refer_ns {
3501 return Some(key);
3502 }
3503 }
3504 None
3505 }
3506
3507 fn ensure_compiled(&mut self, ic_key: IdentityConstraintKey) -> bool {
3510 if let Some(cached) = self.compiled_constraints.get(&ic_key) {
3511 return cached.is_some();
3512 }
3513 let ic_data = &self.schema_set.arenas.identity_constraints[ic_key];
3514 let doc = ic_data
3515 .source
3516 .as_ref()
3517 .and_then(|s| self.schema_set.documents.get(s.doc_id as usize));
3518 let schema_xpath_default_ns = doc.and_then(|d| d.xpath_default_namespace);
3519 let target_namespace = doc.and_then(|d| d.target_namespace);
3520 let ic_name = ic_data.name;
3521 match CompiledIdentityConstraint::compile(
3522 ic_data,
3523 ic_key,
3524 &self.schema_set.name_table,
3525 schema_xpath_default_ns,
3526 target_namespace,
3527 self.schema_set.xsd_version,
3528 ) {
3529 Ok(mut compiled) => {
3530 if compiled.kind == IdentityKind::Keyref {
3532 if let Some(refer) = &compiled.refer {
3533 let refer_ns = refer.namespace.or(compiled.target_namespace);
3534 compiled.refer_key = self.resolve_refer_key(refer.local_name, refer_ns);
3535 if compiled.refer_key.is_none() {
3536 let name = self.schema_set.name_table.resolve(ic_name);
3537 let refer_display = format_resolved_qname(
3538 &self.schema_set.name_table,
3539 refer_ns,
3540 refer.local_name,
3541 );
3542 self.sink.on_warning(ValidationWarning {
3543 code: "cvc-identity-constraint",
3544 message: format!(
3545 "Keyref '{}': could not resolve refer target '{}'",
3546 name, refer_display
3547 ),
3548 location: None,
3549 });
3550 }
3551 }
3552 }
3553 self.compiled_constraints.insert(ic_key, Some(compiled));
3554 true
3555 }
3556 Err(e) => {
3557 let name = self.schema_set.name_table.resolve(ic_name);
3558 self.sink.on_warning(ValidationWarning {
3559 code: "cvc-identity-constraint",
3560 message: format!(
3561 "Identity constraint '{}': XPath compilation failed: {}",
3562 name, e
3563 ),
3564 location: None,
3565 });
3566 self.compiled_constraints.insert(ic_key, None);
3567 false
3568 }
3569 }
3570 }
3571
3572 fn advance_constraints_start_element(
3575 &mut self,
3576 local_name: NameId,
3577 namespace: Option<NameId>,
3578 element_key: Option<ElementKey>,
3579 ) {
3580 self.advance_constraints_start_element_inner(local_name, namespace, element_key, false);
3581 }
3582
3583 fn advance_constraints_start_element_skipped(
3590 &mut self,
3591 local_name: NameId,
3592 namespace: Option<NameId>,
3593 ) {
3594 self.advance_constraints_start_element_inner(local_name, namespace, None, true);
3595 }
3596
3597 fn advance_constraints_start_element_inner(
3598 &mut self,
3599 local_name: NameId,
3600 namespace: Option<NameId>,
3601 element_key: Option<ElementKey>,
3602 skipped: bool,
3603 ) {
3604 let ns = namespace.unwrap_or(NameId(0));
3605
3606 for cs in &mut self.active_constraints {
3608 if skipped {
3609 cs.start_element_skipped(local_name, ns);
3610 } else {
3611 cs.start_element(local_name, ns);
3612 }
3613 }
3614
3615 if !skipped {
3618 if let Some(ek) = element_key {
3619 let ic_keys: Vec<IdentityConstraintKey> = self.schema_set.arenas.elements[ek]
3620 .identity_constraints
3621 .clone();
3622 for ic_key in ic_keys {
3623 if self.ensure_compiled(ic_key) {
3624 let compiled = self.compiled_constraints[&ic_key].as_ref().unwrap();
3625 let mut cs = ConstraintStruct::new(compiled);
3626 cs.activate();
3627 self.active_constraints.push(cs);
3628 }
3629 }
3630 }
3631 }
3632 }
3633
3634 fn process_constraints_end_element(
3638 &mut self,
3639 text_content: &str,
3640 typed_value: Option<&XmlValue>,
3641 is_nil: bool,
3642 is_complex_content: bool,
3643 error_codes: &mut Vec<&'static str>,
3644 ) {
3645 let name_table = &self.schema_set.name_table;
3646 let element_path = self.element_path.clone();
3647 let location = self.current_location.clone();
3648
3649 let mut ic_errors = Vec::new();
3651 for cs in &mut self.active_constraints {
3652 let errs = cs.end_element_with_text(
3653 text_content,
3654 typed_value,
3655 is_nil,
3656 is_complex_content,
3657 name_table,
3658 &element_path,
3659 location.clone(),
3660 );
3661 ic_errors.extend(errs);
3662 }
3663 for err in ic_errors {
3664 self.emit_error_to(err, error_codes);
3665 }
3666
3667 let mut deactivated: Vec<ConstraintStruct> = Vec::new();
3669 let mut i = 0;
3670 while i < self.active_constraints.len() {
3671 if !self.active_constraints[i].is_active() {
3672 deactivated.push(self.active_constraints.swap_remove(i));
3673 } else {
3674 i += 1;
3675 }
3676 }
3677
3678 if !deactivated.is_empty() {
3680 let mut scope_keyrefs: Vec<(KeyTable, Option<IdentityConstraintKey>)> = Vec::new();
3681
3682 for cs in deactivated {
3683 if cs.key_table.kind == IdentityKind::Keyref {
3684 let refer_key = self
3686 .compiled_constraints
3687 .get(&cs.ic_key)
3688 .and_then(|opt| opt.as_ref())
3689 .and_then(|compiled| compiled.refer_key);
3690 scope_keyrefs.push((cs.key_table, refer_key));
3691 } else {
3692 let scope_slot = self.ic_scope_tables.last_mut();
3694 if let Some(slot) = scope_slot {
3695 let scope_map = slot.get_or_insert_with(HashMap::new);
3696 let ic_key = cs.key_table.ic_key;
3697 scope_map
3698 .entry(ic_key)
3699 .and_modify(|existing| {
3700 existing.sequences.extend(cs.key_table.sequences.clone())
3701 })
3702 .or_insert(cs.key_table);
3703 }
3704 }
3705 }
3706
3707 let name_table = &self.schema_set.name_table;
3711 for (keyref_table, refer_key) in scope_keyrefs {
3712 let target = refer_key.and_then(|rk| {
3713 self.ic_scope_tables
3714 .last()
3715 .and_then(|slot| slot.as_ref())
3716 .and_then(|map| map.get(&rk))
3717 });
3718 match target {
3719 Some(target_table) => {
3720 let errs = keyref_table.check_keyref_against(target_table, name_table);
3721 for err in errs {
3722 self.emit_error_to(err, error_codes);
3723 }
3724 }
3725 None => {
3726 self.deferred_keyrefs.push((keyref_table, refer_key));
3728 }
3729 }
3730 }
3731 }
3732 }
3733
3734 fn union_has_id_idref(&self, type_key: TypeKey) -> bool {
3737 let sk = match type_key {
3738 TypeKey::Simple(sk) => sk,
3739 _ => return false,
3740 };
3741 if let Some(code) = self.schema_set.get_type_code(sk) {
3743 if matches!(code, XmlTypeCode::Id | XmlTypeCode::IdRef) {
3744 return true;
3745 }
3746 }
3747 if let Some(st) = self.schema_set.arenas.simple_types.get(sk) {
3749 for &member_key in &st.resolved_member_types {
3750 if self.union_has_id_idref(member_key) {
3751 return true;
3752 }
3753 }
3754 }
3755 false
3756 }
3757
3758 fn check_entity_declared(&mut self, typed_value: &XmlValue) {
3763 use crate::types::value::XmlValueKind;
3764 let entities = match &self.unparsed_entities {
3765 Some(e) => e,
3766 None => return,
3767 };
3768 let mut undeclared: Vec<String> = Vec::new();
3770
3771 if let XmlValueKind::List { item_type, items } = &typed_value.value {
3775 if *item_type == XmlTypeCode::Entity || typed_value.type_code == XmlTypeCode::Entities {
3776 for item in items {
3777 let name = item.to_string();
3778 if !entities.contains(&name) {
3779 undeclared.push(name);
3780 }
3781 }
3782 }
3783 } else if typed_value.type_code == XmlTypeCode::Entity {
3784 let name = typed_value.to_string_value();
3785 if !entities.contains(&name) {
3786 undeclared.push(name);
3787 }
3788 }
3789
3790 for name in undeclared {
3791 self.report_error(
3792 "cvc-datatype-valid.1.2.1",
3793 format!("ENTITY '{}' is not declared as an unparsed entity", name),
3794 );
3795 }
3796 }
3797
3798 fn register_id_value(&mut self, value: String, owner_serial: u64) {
3804 match self.id_values.get(&value) {
3805 Some(&existing_serial) => {
3806 if !(self.schema_set.is_xsd11() && existing_serial == owner_serial) {
3807 self.report_error("cvc-id.2", format!("Duplicate ID value '{}'", value));
3808 }
3809 }
3810 None => {
3811 self.id_values.insert(value, owner_serial);
3812 }
3813 }
3814 }
3815
3816 fn collect_id_idref(&mut self, typed_value: &XmlValue, value_str: &str, owner_serial: u64) {
3830 use crate::types::value::XmlValueKind;
3831
3832 let mut effective = typed_value;
3834 while let XmlValueKind::Union(inner) = &effective.value {
3835 effective = inner.as_ref();
3836 }
3837
3838 if let XmlValueKind::List { item_type, items } = &effective.value {
3841 let union_resolved = effective
3845 .schema_type
3846 .and_then(|sk| self.schema_set.arenas.simple_types.get(sk))
3847 .and_then(|st| st.resolved_item_type)
3848 .filter(|item_tk| self.union_has_id_idref(*item_tk));
3849 if let Some(item_type_key) = union_resolved {
3850 for token in value_str.split_whitespace() {
3851 if let Ok(result) =
3852 super::simple::validate_simple_type(token, item_type_key, self.schema_set)
3853 {
3854 match result.typed_value.type_code {
3855 XmlTypeCode::Id => {
3856 self.register_id_value(token.to_string(), owner_serial);
3857 }
3858 XmlTypeCode::IdRef => {
3859 self.pending_idrefs.push((
3860 token.to_string(),
3861 self.current_location.clone(),
3862 self.element_path.clone(),
3863 ));
3864 }
3865 _ => {} }
3867 }
3868 }
3869 return;
3870 }
3871 match *item_type {
3873 XmlTypeCode::Id => {
3874 for item in items {
3875 self.register_id_value(item.to_string(), owner_serial);
3876 }
3877 return;
3878 }
3879 XmlTypeCode::IdRef => {
3880 for item in items {
3881 self.pending_idrefs.push((
3882 item.to_string(),
3883 self.current_location.clone(),
3884 self.element_path.clone(),
3885 ));
3886 }
3887 return;
3888 }
3889 _ => {}
3890 }
3891 }
3892
3893 match effective.type_code {
3896 XmlTypeCode::Id => {
3897 let normalized = effective.to_string_value();
3898 self.register_id_value(normalized, owner_serial);
3899 }
3900 XmlTypeCode::IdRef | XmlTypeCode::IdRefs => {
3901 if let XmlValueKind::List { items, .. } = &effective.value {
3902 for item in items {
3903 self.pending_idrefs.push((
3904 item.to_string(),
3905 self.current_location.clone(),
3906 self.element_path.clone(),
3907 ));
3908 }
3909 } else if effective.type_code == XmlTypeCode::IdRefs {
3910 for token in value_str.split_whitespace() {
3912 self.pending_idrefs.push((
3913 token.to_string(),
3914 self.current_location.clone(),
3915 self.element_path.clone(),
3916 ));
3917 }
3918 } else {
3919 self.pending_idrefs.push((
3921 effective.to_string_value(),
3922 self.current_location.clone(),
3923 self.element_path.clone(),
3924 ));
3925 }
3926 }
3927 _ => {}
3928 }
3929 }
3930
3931 fn validate_attribute_against_type(
3935 &mut self,
3936 ct_key: ComplexTypeKey,
3937 local_name: NameId,
3938 namespace: Option<NameId>,
3939 value: &str,
3940 ) -> SchemaInfo {
3941 let found = {
3942 let ct_data = &self.schema_set.arenas.complex_types[ct_key];
3943 self.find_attribute_in_type(ct_data, local_name, namespace)
3944 };
3945 let mut wildcard_cache: Option<
3961 Option<crate::schema::derivation::EffectiveAttributeWildcard>,
3962 > = None;
3963 let found = match found {
3964 AttributeLookup::Prohibited => {
3965 let wc = crate::schema::derivation::compute_runtime_attribute_wildcard(
3966 self.schema_set,
3967 ct_key,
3968 );
3969 let rescued = match wc.as_ref() {
3970 Some(w) => crate::schema::derivation::effective_wildcard_allows_attribute(
3971 self.schema_set,
3972 w,
3973 namespace,
3974 local_name,
3975 ),
3976 None => false,
3977 };
3978 wildcard_cache = Some(wc);
3979 if rescued {
3980 AttributeLookup::NotFound
3981 } else {
3982 AttributeLookup::Prohibited
3983 }
3984 }
3985 other => other,
3986 };
3987
3988 match found {
3989 AttributeLookup::Found(attr_key, attr_type, fixed_value, inheritable) => {
3990 let mut member_type = None;
3992 let mut typed_value = None;
3993 let mut normalized_value = None;
3994 let mut attr_validity = SchemaValidity::Valid;
3995 if let Some(type_key) = attr_type {
3996 match super::simple::validate_simple_type(value, type_key, self.schema_set) {
3997 Ok(result) => {
3998 member_type = result.member_type;
3999 typed_value = Some(result.typed_value);
4000 normalized_value = result.normalized_value;
4001 }
4002 Err(err) => {
4003 self.report_validation_error(err);
4004 attr_validity = SchemaValidity::Invalid;
4005 self.mark_current_invalid();
4006 }
4007 }
4008 }
4009
4010 if attr_validity == SchemaValidity::Valid {
4013 match self.resolve_attribute_qname_typed_value(typed_value.as_ref(), value) {
4014 Ok(Some(resolved)) => typed_value = Some(resolved),
4015 Ok(None) => {}
4016 Err(prefix) => {
4017 let attr_name = self.schema_set.name_table.resolve(local_name);
4018 self.report_error(
4019 "cvc-datatype-valid.1.2.1",
4020 format!(
4021 "Attribute '{}' has QName value '{}' with undeclared prefix '{}'",
4022 attr_name, value, prefix
4023 ),
4024 );
4025 self.mark_current_invalid();
4026 attr_validity = SchemaValidity::Invalid;
4027 }
4028 }
4029 }
4030
4031 if let Some(fixed) = fixed_value {
4032 let matches = if let Some(ref tv) = typed_value {
4033 super::simple::fixed_matches_typed(
4034 value,
4035 tv,
4036 &fixed,
4037 attr_type,
4038 self.schema_set,
4039 )
4040 } else {
4041 super::simple::fixed_values_equal(value, &fixed, attr_type, self.schema_set)
4042 };
4043 if !matches {
4044 let attr_name = self.schema_set.name_table.resolve(local_name);
4045 self.report_error(
4046 "cvc-attribute.4",
4047 format!(
4048 "Attribute '{}' has fixed value '{}' but got '{}'",
4049 attr_name, fixed, value
4050 ),
4051 );
4052 self.mark_current_invalid();
4053 }
4054 }
4055
4056 #[cfg(feature = "xsd11")]
4060 if inheritable {
4061 if let Some(ev) = self.validation_stack.last_mut() {
4062 use super::context::InheritedAttributeValue;
4063 ev.outgoing_inherited.insert(
4064 (namespace, local_name),
4065 InheritedAttributeValue {
4066 value: value.to_string(),
4067 attribute_key: attr_key,
4068 },
4069 );
4070 }
4071 }
4072 let _ = inheritable;
4073
4074 let result = SchemaInfo {
4075 element_decl: None,
4076 attribute_decl: attr_key,
4077 schema_type: attr_type,
4078 member_type,
4079 validity: attr_validity,
4080 validation_attempted: ValidationAttempted::Full,
4081 is_default: false,
4082 is_nil: false,
4083 content_type: None,
4084 typed_value,
4085 normalized_value,
4086 schema_error_codes: Vec::new(),
4087 notation: None,
4088 deferred_by_cta: false,
4089 type_source: Some(TypeSource::Declaration),
4090 #[cfg(feature = "xsd11")]
4091 cta_selected: false,
4092 #[cfg(feature = "xsd11")]
4093 assertion_outcome: None,
4094 };
4095 self.post_process_attribute(local_name, namespace, value, &result);
4096 result
4097 }
4098 AttributeLookup::Prohibited => {
4099 let attr_name = self.schema_set.name_table.resolve(local_name);
4100 self.report_error(
4101 "cvc-complex-type.3.2.2",
4102 format!("Attribute '{}' is prohibited", attr_name),
4103 );
4104 self.mark_current_invalid();
4105 SchemaInfo::invalid()
4106 }
4107 AttributeLookup::NotFound => {
4108 let effective_wildcard = wildcard_cache.unwrap_or_else(|| {
4109 crate::schema::derivation::compute_runtime_attribute_wildcard(
4110 self.schema_set,
4111 ct_key,
4112 )
4113 });
4114 if let Some(ref wildcard) = effective_wildcard {
4115 if crate::schema::derivation::effective_wildcard_allows_attribute(
4116 self.schema_set,
4117 wildcard,
4118 namespace,
4119 local_name,
4120 ) {
4121 let result = match wildcard.process_contents {
4122 ProcessContents::Skip => SchemaInfo::empty(),
4123 ProcessContents::Strict => self
4124 .validate_wildcard_attribute_strict(local_name, namespace, value),
4125 ProcessContents::Lax => {
4126 self.validate_wildcard_attribute_lax(local_name, namespace, value)
4127 }
4128 };
4129 #[cfg(feature = "xsd11")]
4134 if let Some(attr_key) = result.attribute_decl {
4135 if let Some(decl) = self.schema_set.arenas.attributes.get(attr_key) {
4136 if decl.inheritable {
4137 if let Some(ev) = self.validation_stack.last_mut() {
4138 use super::context::InheritedAttributeValue;
4139 ev.outgoing_inherited.insert(
4140 (namespace, local_name),
4141 InheritedAttributeValue {
4142 value: value.to_string(),
4143 attribute_key: Some(attr_key),
4144 },
4145 );
4146 }
4147 }
4148 }
4149 }
4150 if wildcard.process_contents == ProcessContents::Skip {
4151 let ns = namespace.unwrap_or(NameId(0));
4157 let mut multi_node_ic: Vec<(NameId, usize)> = Vec::new();
4158 for cs in &mut self.active_constraints {
4159 let matches = cs.matching_fields(local_name, ns);
4160 for field_idx in matches {
4161 if cs.increment_field_match_count(field_idx) {
4162 multi_node_ic
4163 .push((cs.key_table.constraint_name, field_idx));
4164 }
4165 }
4166 }
4167 for (constraint_name, field_idx) in multi_node_ic {
4168 let name = self
4169 .schema_set
4170 .name_table
4171 .resolve(constraint_name)
4172 .to_string();
4173 self.report_error(
4174 "cvc-identity-constraint.4.2.1",
4175 format!(
4176 "Identity constraint '{}': field {} matches more than one node",
4177 name, field_idx + 1
4178 ),
4179 );
4180 }
4181 } else {
4182 self.post_process_attribute(local_name, namespace, value, &result);
4183 }
4184 return result;
4185 }
4186 }
4187
4188 let attr_name = self.schema_set.name_table.resolve(local_name);
4189 self.report_error(
4190 "cvc-complex-type.3.2.2",
4191 format!("Attribute '{}' is not allowed for this element", attr_name),
4192 );
4193 self.mark_current_invalid();
4194 SchemaInfo::invalid()
4195 }
4196 }
4197 }
4198
4199 #[cfg(feature = "xsd11")]
4204 fn validate_deferred_attributes(&mut self, schema_type: Option<TypeKey>) {
4205 self.deferred_attribute_results.clear();
4206
4207 let collected = match self.validation_stack.last_mut() {
4208 Some(ev) => std::mem::take(&mut ev.collected_attributes),
4209 None => return,
4210 };
4211
4212 let ct_key = match schema_type {
4213 Some(TypeKey::Complex(k)) => k,
4214 _ => {
4215 self.deferred_attribute_results
4220 .resize_with(collected.len(), SchemaInfo::empty);
4221 return;
4222 }
4223 };
4224
4225 for (namespace, local_name, value) in &collected {
4226 let ec_snapshot = self
4227 .validation_stack
4228 .last()
4229 .map_or(0, |ev| ev.error_codes.len());
4230 let mut info =
4231 self.validate_attribute_against_type(ct_key, *local_name, *namespace, value);
4232 if let Some(ev) = self.validation_stack.last_mut() {
4233 if ev.error_codes.len() > ec_snapshot {
4234 info.schema_error_codes = ev.error_codes[ec_snapshot..].to_vec();
4235 ev.error_codes.truncate(ec_snapshot);
4236 }
4237 match info.validation_attempted {
4239 ValidationAttempted::Full => {
4240 ev.any_attr_not_none = true;
4241 }
4242 ValidationAttempted::None => {
4243 ev.any_attr_not_full = true;
4244 }
4245 ValidationAttempted::Partial => {
4246 ev.any_attr_not_full = true;
4247 ev.any_attr_not_none = true;
4248 }
4249 }
4250 }
4251 self.deferred_attribute_results.push(info);
4252 }
4253 }
4254
4255 #[cfg(feature = "xsd11")]
4260 pub fn take_deferred_attribute_results(&mut self) -> Vec<SchemaInfo> {
4261 std::mem::take(&mut self.deferred_attribute_results)
4262 }
4263
4264 fn post_process_attribute(
4267 &mut self,
4268 local_name: NameId,
4269 namespace: Option<NameId>,
4270 value: &str,
4271 result: &SchemaInfo,
4272 ) {
4273 let ns = namespace.unwrap_or(NameId(0));
4274
4275 let ns_ctx = self
4277 .validation_stack
4278 .last()
4279 .and_then(|ev| ev.ns_context.as_ref());
4280 let ic_typed_value = Self::resolve_ic_qname_value(
4281 &result.typed_value,
4282 value,
4283 ns_ctx,
4284 &self.schema_set.name_table,
4285 )
4286 .or_else(|| result.typed_value.clone());
4287 let mut multi_node_ic: Vec<(NameId, usize)> = Vec::new();
4288 for cs in &mut self.active_constraints {
4289 let matches = cs.matching_fields(local_name, ns);
4290 for field_idx in matches {
4291 let already_matched =
4292 cs.set_field_value(field_idx, value.to_string(), ic_typed_value.clone());
4293 if already_matched {
4294 multi_node_ic.push((cs.key_table.constraint_name, field_idx));
4295 }
4296 }
4297 }
4298 for (constraint_name, field_idx) in multi_node_ic {
4299 let name = self
4300 .schema_set
4301 .name_table
4302 .resolve(constraint_name)
4303 .to_string();
4304 self.report_error(
4305 "cvc-identity-constraint.4.2.1",
4306 format!(
4307 "Identity constraint '{}': field {} matches more than one node",
4308 name,
4309 field_idx + 1
4310 ),
4311 );
4312 }
4313
4314 if let Some(ref tv) = result.typed_value {
4316 let owner = self
4317 .validation_stack
4318 .last()
4319 .map(|e| e.element_serial)
4320 .unwrap_or(0);
4321 self.collect_id_idref(tv, value, owner);
4322 self.check_entity_declared(tv);
4323
4324 if tv.type_code == XmlTypeCode::Notation {
4326 let notation = self
4328 .validation_stack
4329 .last()
4330 .filter(|ev| ev.notation.is_none())
4331 .and_then(|ev| ev.ns_context.as_ref())
4332 .and_then(|ctx| self.resolve_notation_qname(value, ctx));
4333 if let (Some(nk), Some(ev)) = (notation, self.validation_stack.last_mut()) {
4334 if ev.notation.is_none() {
4335 ev.notation = Some(nk);
4336 }
4337 }
4338 }
4339 }
4340 }
4341
4342 fn resolve_notation_qname(
4346 &self,
4347 value: &str,
4348 ns_context: &NamespaceContextSnapshot,
4349 ) -> Option<NotationKey> {
4350 let qn =
4351 parse_qname_with_snapshot(value, ns_context, &self.schema_set.name_table, true).ok()?;
4352 self.schema_set
4353 .lookup_notation(qn.namespace_uri, qn.local_name)
4354 }
4355
4356 fn resolve_attribute_qname_typed_value(
4368 &self,
4369 typed_value: Option<&XmlValue>,
4370 value: &str,
4371 ) -> Result<Option<XmlValue>, String> {
4372 use crate::types::value::{XmlAtomicValue, XmlValueKind};
4373 let Some(tv) = typed_value else {
4374 return Ok(None);
4375 };
4376 if tv.type_code != XmlTypeCode::QName && tv.type_code != XmlTypeCode::Notation {
4377 return Ok(None);
4378 }
4379 let Some(ctx) = self
4380 .validation_stack
4381 .last()
4382 .and_then(|ev| ev.ns_context.as_ref())
4383 else {
4384 return Ok(None);
4385 };
4386 let qn = match parse_qname_with_snapshot(value, ctx, &self.schema_set.name_table, true) {
4387 Ok(qn) => qn,
4388 Err(QNameError::UndefinedPrefix(prefix)) => return Err(prefix),
4389 Err(_) => return Ok(None),
4390 };
4391 let atom = if tv.type_code == XmlTypeCode::Notation {
4392 XmlAtomicValue::Notation(qn)
4393 } else {
4394 XmlAtomicValue::QName(qn)
4395 };
4396 Ok(Some(XmlValue {
4397 type_code: tv.type_code,
4398 schema_type: tv.schema_type,
4399 value: XmlValueKind::Atomic(atom),
4400 }))
4401 }
4402
4403 fn resolve_ic_qname_value(
4410 typed_value: &Option<XmlValue>,
4411 string_value: &str,
4412 ns_context: Option<&NamespaceContextSnapshot>,
4413 name_table: &crate::namespace::table::NameTable,
4414 ) -> Option<XmlValue> {
4415 use crate::types::value::{XmlAtomicValue, XmlValueKind};
4416 let val = typed_value.as_ref()?;
4417 if val.type_code != XmlTypeCode::QName && val.type_code != XmlTypeCode::Notation {
4418 return None;
4419 }
4420 if matches!(
4424 val.value,
4425 XmlValueKind::Atomic(XmlAtomicValue::QName(_))
4426 | XmlValueKind::Atomic(XmlAtomicValue::Notation(_))
4427 ) {
4428 return None;
4429 }
4430 let ctx = ns_context?;
4431 let qn = parse_qname_with_snapshot(string_value, ctx, name_table, true).ok()?;
4432 let atom = if val.type_code == XmlTypeCode::Notation {
4433 XmlAtomicValue::Notation(qn)
4434 } else {
4435 XmlAtomicValue::QName(qn)
4436 };
4437 Some(XmlValue {
4438 type_code: val.type_code,
4439 schema_type: val.schema_type,
4440 value: XmlValueKind::Atomic(atom),
4441 })
4442 }
4443
4444 fn init_content_model(
4446 &self,
4447 type_key: Option<TypeKey>,
4448 ) -> (ContentValidatorState, ContentType) {
4449 match type_key {
4450 Some(TypeKey::Complex(ct_key)) => {
4451 let ct_data = &self.schema_set.arenas.complex_types[ct_key];
4452 let content_type = self.determine_content_type(ct_data);
4453
4454 let content_state = match content_type {
4455 ContentType::Empty => ContentValidatorState::Empty,
4456 ContentType::TextOnly => ContentValidatorState::Simple,
4457 ContentType::ElementOnly | ContentType::Mixed => {
4458 match compile_content_model_matcher(self.schema_set, ct_data) {
4459 Ok(matcher) => ContentValidatorState::from_matcher(matcher),
4460 Err(_) => {
4461 ContentValidatorState::Empty
4463 }
4464 }
4465 }
4466 };
4467
4468 (content_state, content_type)
4469 }
4470 Some(TypeKey::Simple(_)) => (ContentValidatorState::Simple, ContentType::TextOnly),
4471 None => (ContentValidatorState::Simple, ContentType::TextOnly),
4472 }
4473 }
4474
4475 fn determine_content_type(&self, ct_data: &ComplexTypeDefData) -> ContentType {
4477 use crate::parser::frames::ComplexContentResult;
4478 use crate::parser::frames::DerivationMethod;
4479 match &ct_data.content {
4480 ComplexContentResult::Empty => {
4481 #[cfg(feature = "xsd11")]
4485 if self.schema_set.is_xsd11()
4486 && self.empty_ct_has_applicable_default_open_content(ct_data)
4487 {
4488 return if ct_data.mixed {
4489 ContentType::Mixed
4490 } else {
4491 ContentType::ElementOnly
4492 };
4493 }
4494 if ct_data.mixed {
4495 ContentType::Mixed
4496 } else {
4497 ContentType::Empty
4498 }
4499 }
4500 ComplexContentResult::Simple(_) => ContentType::TextOnly,
4501 ComplexContentResult::Complex(def) => {
4502 let particle_empty = match &def.particle {
4512 None => true,
4513 Some(p) => {
4514 self.schema_set.is_xsd11()
4515 && crate::parser::frames::particle_is_explicit_empty(p)
4516 }
4517 };
4518 let has_open_content = self.type_has_effective_open_content(ct_data, def);
4519 if particle_empty && !ct_data.mixed && !def.mixed && !has_open_content {
4520 if matches!(ct_data.derivation_method, Some(DerivationMethod::Extension)) {
4522 if let Some(TypeKey::Complex(base_ct_key)) = ct_data.resolved_base_type {
4523 let base_data = &self.schema_set.arenas.complex_types[base_ct_key];
4524 return self.determine_content_type(base_data);
4525 }
4526 }
4527 ContentType::Empty
4528 } else if ct_data.mixed || def.mixed {
4529 ContentType::Mixed
4530 } else {
4531 ContentType::ElementOnly
4532 }
4533 }
4534 }
4535 }
4536
4537 #[cfg(feature = "xsd11")]
4548 fn empty_ct_has_applicable_default_open_content(&self, ct_data: &ComplexTypeDefData) -> bool {
4549 let doc = ct_data
4550 .source
4551 .as_ref()
4552 .and_then(|s| self.schema_set.documents.get(s.defaults_doc() as usize));
4553 if let Some(default) = doc.and_then(|d| d.default_open_content.as_ref()) {
4554 if default.mode == crate::schema::model::OpenContentMode::None {
4555 return false;
4556 }
4557 return default.applies_to_empty;
4558 }
4559 false
4560 }
4561
4562 #[allow(unused_variables)]
4563 fn type_has_effective_open_content(
4564 &self,
4565 ct_data: &ComplexTypeDefData,
4566 def: &crate::parser::frames::ComplexContentDefResult,
4567 ) -> bool {
4568 #[cfg(feature = "xsd11")]
4569 {
4570 use crate::parser::frames::OpenContentMode;
4571 if let Some(oc) = def.open_content.as_ref() {
4573 return oc.mode != OpenContentMode::None;
4574 }
4575 let doc = ct_data
4579 .source
4580 .as_ref()
4581 .and_then(|s| self.schema_set.documents.get(s.defaults_doc() as usize));
4582 if let Some(default) = doc.and_then(|d| d.default_open_content.as_ref()) {
4583 if default.mode == crate::schema::model::OpenContentMode::None {
4584 return false;
4585 }
4586 if default.applies_to_empty {
4587 return true;
4588 }
4589 return !ct_data.content.explicit_content_type_is_empty();
4590 }
4591 }
4592 let _ = (ct_data, def);
4593 false
4594 }
4595
4596 fn resolve_xsi_type(
4602 &self,
4603 xsi_type_str: &str,
4604 declared_type: Option<TypeKey>,
4605 block: DerivationSet,
4606 ns_context: &NamespaceContextSnapshot,
4607 deferred_errors: &mut Vec<(&'static str, String)>,
4608 ) -> XsiTypeOutcome {
4609 let qname = match parse_qname_with_snapshot(
4611 xsi_type_str,
4612 ns_context,
4613 &self.schema_set.name_table,
4614 true,
4615 ) {
4616 Ok(qn) => qn,
4617 Err(e) => {
4618 let msg = match e {
4619 QNameError::UndefinedPrefix(p) => {
4620 format!(
4621 "Undeclared prefix '{}' in xsi:type value '{}'",
4622 p, xsi_type_str
4623 )
4624 }
4625 _ => format!("Invalid xsi:type value '{}': {}", xsi_type_str, e),
4626 };
4627 deferred_errors.push(("cvc-elt.4.1", msg));
4628 return XsiTypeOutcome::Unresolved;
4629 }
4630 };
4631
4632 let resolved = self
4634 .schema_set
4635 .lookup_type(qname.namespace_uri, qname.local_name)
4636 .or_else(|| {
4637 self.schema_set
4638 .get_built_in_type_by_qname(qname.namespace_uri, qname.local_name)
4639 });
4640
4641 match resolved {
4642 Some(type_key) => {
4643 if let Some(declared) = declared_type {
4645 if !self.schema_set.is_type_derived_from(
4647 type_key,
4648 declared,
4649 DerivationSet::empty(),
4650 ) {
4651 deferred_errors.push((
4652 "cvc-elt.4.2",
4653 format!(
4654 "xsi:type '{}' does not derive from the declared type",
4655 xsi_type_str
4656 ),
4657 ));
4658 return XsiTypeOutcome::InvalidDerivation;
4659 }
4660 let mut combined_block = block;
4664 if let TypeKey::Complex(declared_ct_key) = declared {
4665 if let Some(declared_ct) =
4666 self.schema_set.arenas.complex_types.get(declared_ct_key)
4667 {
4668 combined_block |= declared_ct.block.element_block_mask();
4669 }
4670 }
4671 if !combined_block.is_empty()
4672 && !self
4673 .schema_set
4674 .is_type_derived_from(type_key, declared, combined_block)
4675 {
4676 deferred_errors.push((
4677 "cvc-elt.4.3",
4678 format!(
4679 "xsi:type '{}' is not validly substitutable for the declared type \
4680 (blocked by 'block' attribute)",
4681 xsi_type_str
4682 ),
4683 ));
4684 return XsiTypeOutcome::InvalidDerivation;
4685 }
4686 }
4687 XsiTypeOutcome::Applied(type_key)
4688 }
4689 None => {
4690 deferred_errors.push((
4691 "cvc-elt.4.1",
4692 format!(
4693 "Type '{}' specified in xsi:type is not declared",
4694 xsi_type_str
4695 ),
4696 ));
4697 XsiTypeOutcome::Unresolved
4698 }
4699 }
4700 }
4701
4702 fn emit_deferred_xsi_type_errors(&mut self, errors: Vec<(&'static str, String)>) {
4704 for (constraint, message) in errors {
4705 self.report_error(constraint, message);
4706 }
4707 }
4708
4709 fn lax_assessment_content_model(&self) -> (ContentValidatorState, ContentType) {
4714 let any_type_key = TypeKey::Complex(self.schema_set.any_type_key());
4715 self.init_content_model(Some(any_type_key))
4716 }
4717
4718 fn validate_wildcard_attribute_strict(
4723 &mut self,
4724 local_name: NameId,
4725 namespace: Option<NameId>,
4726 value: &str,
4727 ) -> SchemaInfo {
4728 match self.schema_set.lookup_attribute(namespace, local_name) {
4729 Some(attr_key) => {
4730 let attr_data = self.schema_set.arenas.attributes.get(attr_key);
4731 let attr_type = attr_data.and_then(|d| d.resolved_type);
4732 let fixed = attr_data.and_then(|d| d.fixed_value.clone());
4733
4734 let mut member_type = None;
4736 let mut typed_value = None;
4737 let mut normalized_value = None;
4738 let mut attr_validity = SchemaValidity::Valid;
4739 if let Some(type_key) = attr_type {
4740 match super::simple::validate_simple_type(value, type_key, self.schema_set) {
4741 Ok(result) => {
4742 member_type = result.member_type;
4743 typed_value = Some(result.typed_value);
4744 normalized_value = result.normalized_value;
4745 }
4746 Err(err) => {
4747 self.report_validation_error(err);
4748 attr_validity = SchemaValidity::Invalid;
4749 if let Some(s) = self.validation_stack.last_mut() {
4750 s.validity = SchemaValidity::Invalid;
4751 }
4752 }
4753 }
4754 }
4755
4756 if let Some(fixed_val) = fixed {
4757 let matches = if let Some(ref tv) = typed_value {
4758 super::simple::fixed_matches_typed(
4759 value,
4760 tv,
4761 &fixed_val,
4762 attr_type,
4763 self.schema_set,
4764 )
4765 } else {
4766 super::simple::fixed_values_equal(
4767 value,
4768 &fixed_val,
4769 attr_type,
4770 self.schema_set,
4771 )
4772 };
4773 if !matches {
4774 let attr_name = self.schema_set.name_table.resolve(local_name);
4775 self.report_error(
4776 "cvc-attribute.4",
4777 format!(
4778 "Attribute '{}' has fixed value '{}' but got '{}'",
4779 attr_name, fixed_val, value
4780 ),
4781 );
4782 if let Some(s) = self.validation_stack.last_mut() {
4783 s.validity = SchemaValidity::Invalid;
4784 }
4785 }
4786 }
4787
4788 SchemaInfo {
4789 element_decl: None,
4790 attribute_decl: Some(attr_key),
4791 schema_type: attr_type,
4792 member_type,
4793 validity: attr_validity,
4794 validation_attempted: ValidationAttempted::Full,
4795 is_default: false,
4796 is_nil: false,
4797 content_type: None,
4798 typed_value,
4799 normalized_value,
4800 schema_error_codes: Vec::new(),
4801 notation: None,
4802 deferred_by_cta: false,
4803 type_source: Some(TypeSource::Declaration),
4804 #[cfg(feature = "xsd11")]
4805 cta_selected: false,
4806 #[cfg(feature = "xsd11")]
4807 assertion_outcome: None,
4808 }
4809 }
4810 None => {
4811 let attr_name = self.schema_set.name_table.resolve(local_name);
4812 self.report_error(
4813 "cvc-assess-attr.1.2",
4814 format!(
4815 "No global attribute declaration for '{}' (wildcard processContents=\"strict\")",
4816 attr_name
4817 ),
4818 );
4819 if let Some(s) = self.validation_stack.last_mut() {
4820 s.validity = SchemaValidity::Invalid;
4821 }
4822 SchemaInfo::invalid()
4823 }
4824 }
4825 }
4826
4827 fn validate_wildcard_attribute_lax(
4831 &mut self,
4832 local_name: NameId,
4833 namespace: Option<NameId>,
4834 value: &str,
4835 ) -> SchemaInfo {
4836 match self.schema_set.lookup_attribute(namespace, local_name) {
4837 Some(attr_key) => {
4838 let attr_data = self.schema_set.arenas.attributes.get(attr_key);
4840 let attr_type = attr_data.and_then(|d| d.resolved_type);
4841 let fixed = attr_data.and_then(|d| d.fixed_value.clone());
4842
4843 let mut member_type = None;
4845 let mut typed_value = None;
4846 let mut normalized_value = None;
4847 let mut attr_validity = SchemaValidity::Valid;
4848 if let Some(type_key) = attr_type {
4849 match super::simple::validate_simple_type(value, type_key, self.schema_set) {
4850 Ok(result) => {
4851 member_type = result.member_type;
4852 typed_value = Some(result.typed_value);
4853 normalized_value = result.normalized_value;
4854 }
4855 Err(err) => {
4856 self.report_validation_error(err);
4857 attr_validity = SchemaValidity::Invalid;
4858 if let Some(s) = self.validation_stack.last_mut() {
4859 s.validity = SchemaValidity::Invalid;
4860 }
4861 }
4862 }
4863 }
4864
4865 if let Some(fixed_val) = fixed {
4866 let matches = if let Some(ref tv) = typed_value {
4867 super::simple::fixed_matches_typed(
4868 value,
4869 tv,
4870 &fixed_val,
4871 attr_type,
4872 self.schema_set,
4873 )
4874 } else {
4875 super::simple::fixed_values_equal(
4876 value,
4877 &fixed_val,
4878 attr_type,
4879 self.schema_set,
4880 )
4881 };
4882 if !matches {
4883 let attr_name = self.schema_set.name_table.resolve(local_name);
4884 self.report_error(
4885 "cvc-attribute.4",
4886 format!(
4887 "Attribute '{}' has fixed value '{}' but got '{}'",
4888 attr_name, fixed_val, value
4889 ),
4890 );
4891 if let Some(s) = self.validation_stack.last_mut() {
4892 s.validity = SchemaValidity::Invalid;
4893 }
4894 }
4895 }
4896
4897 SchemaInfo {
4898 element_decl: None,
4899 attribute_decl: Some(attr_key),
4900 schema_type: attr_type,
4901 member_type,
4902 validity: attr_validity,
4903 validation_attempted: ValidationAttempted::Full,
4904 is_default: false,
4905 is_nil: false,
4906 content_type: None,
4907 typed_value,
4908 normalized_value,
4909 schema_error_codes: Vec::new(),
4910 notation: None,
4911 deferred_by_cta: false,
4912 type_source: Some(TypeSource::Declaration),
4913 #[cfg(feature = "xsd11")]
4914 cta_selected: false,
4915 #[cfg(feature = "xsd11")]
4916 assertion_outcome: None,
4917 }
4918 }
4919 None => {
4920 SchemaInfo::empty()
4922 }
4923 }
4924 }
4925
4926 fn collect_group_attributes(&self, ct_data: &ComplexTypeDefData) -> Vec<GroupAttribute> {
4928 let mut result = Vec::new();
4929 let mut visited = HashSet::new();
4930 for &group_key in &ct_data.resolved_attribute_groups {
4931 self.collect_group_attributes_recursive(group_key, &mut result, &mut visited);
4932 }
4933 result
4934 }
4935
4936 fn collect_group_attributes_recursive(
4937 &self,
4938 group_key: AttributeGroupKey,
4939 result: &mut Vec<GroupAttribute>,
4940 visited: &mut HashSet<AttributeGroupKey>,
4941 ) {
4942 if !visited.insert(group_key) {
4943 return; }
4945 let group_data = match self.schema_set.arenas.get_attribute_group(group_key) {
4946 Some(g) => g,
4947 None => return,
4948 };
4949 for (i, attr_use) in group_data.attributes.iter().enumerate() {
4950 let resolved = group_data.resolved_attributes.get(i);
4951 let attr_key = resolved.and_then(|r| r.resolved_ref);
4952 let attr_type = resolved.and_then(|r| r.resolved_type).or_else(|| {
4960 attr_key
4961 .and_then(|k| self.schema_set.arenas.attributes.get(k))
4962 .and_then(|d| d.resolved_type)
4963 });
4964 let (name, namespace) =
4965 self.resolve_attr_use_name_ns(attr_use, resolved, group_data.target_namespace);
4966 let fixed_value = attr_use.attribute.fixed_value.clone().or_else(|| {
4967 attr_key
4968 .and_then(|k| self.schema_set.arenas.attributes.get(k))
4969 .and_then(|d| d.fixed_value.clone())
4970 });
4971 let default_value = attr_use.attribute.default_value.clone().or_else(|| {
4972 attr_key
4973 .and_then(|k| self.schema_set.arenas.attributes.get(k))
4974 .and_then(|d| d.default_value.clone())
4975 });
4976 result.push(GroupAttribute {
4977 name,
4978 namespace,
4979 use_kind: attr_use.use_kind,
4980 type_key: attr_type,
4981 attr_key,
4982 fixed_value,
4983 default_value,
4984 #[cfg(feature = "xsd11")]
4985 inheritable: attr_use.attribute.inheritable,
4986 });
4987 }
4988 for &nested_key in &group_data.resolved_attribute_groups {
4989 self.collect_group_attributes_recursive(nested_key, result, visited);
4990 }
4991 }
4992
4993 fn resolve_attr_use_name_ns(
5002 &self,
5003 attr_use: &AttributeUseResult,
5004 resolved: Option<&ResolvedAttributeUse>,
5005 fallback_namespace: Option<NameId>,
5006 ) -> (NameId, Option<NameId>) {
5007 if let Some(name) = attr_use.attribute.name {
5008 if attr_use.attribute.ref_name.is_none() {
5009 let ns = self.schema_set.effective_local_attribute_namespace(
5011 attr_use.attribute.target_namespace,
5012 attr_use.attribute.form.as_deref(),
5013 attr_use.attribute.source.as_ref(),
5014 fallback_namespace,
5015 );
5016 return (name, ns);
5017 }
5018 }
5020 if let Some(attr_key) = resolved.and_then(|r| r.resolved_ref) {
5021 if let Some(decl) = self.schema_set.arenas.attributes.get(attr_key) {
5022 if let Some(name) = decl.name {
5023 return (name, decl.target_namespace);
5024 }
5025 }
5026 }
5027 (well_known::EMPTY, None)
5028 }
5029
5030 fn find_attribute_in_type(
5037 &self,
5038 ct_data: &ComplexTypeDefData,
5039 local_name: NameId,
5040 namespace: Option<NameId>,
5041 ) -> AttributeLookup {
5042 for (i, attr_use) in ct_data.attributes.iter().enumerate() {
5043 let resolved = ct_data.resolved_attributes.get(i);
5044 let (attr_name, attr_ns) =
5045 self.resolve_attr_use_name_ns(attr_use, resolved, ct_data.target_namespace);
5046
5047 if attr_name == local_name && attr_ns == namespace {
5048 let attr_key = resolved.and_then(|r| r.resolved_ref);
5049 let attr_type = resolved.and_then(|r| r.resolved_type).or_else(|| {
5050 attr_key
5051 .and_then(|k| self.schema_set.arenas.attributes.get(k))
5052 .and_then(|d| d.resolved_type)
5053 });
5054
5055 let fixed = attr_use.attribute.fixed_value.clone().or_else(|| {
5057 attr_key
5058 .and_then(|k| self.schema_set.arenas.attributes.get(k))
5059 .and_then(|d| d.fixed_value.clone())
5060 });
5061
5062 if attr_use.use_kind == AttributeUseKind::Prohibited {
5063 if fixed.is_some() && self.schema_set.is_xsd10() {
5068 let inheritable = attr_use.attribute.inheritable;
5069 return AttributeLookup::Found(attr_key, attr_type, fixed, inheritable);
5070 }
5071 return AttributeLookup::Prohibited;
5072 }
5073
5074 let inheritable = attr_use.attribute.inheritable;
5075 return AttributeLookup::Found(attr_key, attr_type, fixed, inheritable);
5076 }
5077 }
5078
5079 for ga in self.collect_group_attributes(ct_data) {
5081 if ga.name == local_name && ga.namespace == namespace {
5082 if ga.use_kind == AttributeUseKind::Prohibited {
5083 break;
5088 }
5089 #[cfg(feature = "xsd11")]
5090 let inheritable = ga.inheritable;
5091 #[cfg(not(feature = "xsd11"))]
5092 let inheritable = false;
5093 return AttributeLookup::Found(
5094 ga.attr_key,
5095 ga.type_key,
5096 ga.fixed_value,
5097 inheritable,
5098 );
5099 }
5100 }
5101
5102 if let Some(TypeKey::Complex(base_ct_key)) = ct_data.resolved_base_type {
5104 if base_ct_key != self.schema_set.any_type_key() {
5105 let base_data = &self.schema_set.arenas.complex_types[base_ct_key];
5106 return self.find_attribute_in_type(base_data, local_name, namespace);
5107 }
5108 }
5109
5110 AttributeLookup::NotFound
5111 }
5112
5113 #[cfg(feature = "xsd11")]
5119 fn record_inheritable_defaults(&mut self, ct_key: ComplexTypeKey) {
5120 use super::context::InheritedAttributeValue;
5121
5122 let ct_data = &self.schema_set.arenas.complex_types[ct_key];
5123
5124 let mut candidates: Vec<(Option<NameId>, NameId, String, Option<AttributeKey>)> =
5126 Vec::new();
5127
5128 for (i, attr_use) in ct_data.attributes.iter().enumerate() {
5130 if attr_use.use_kind == AttributeUseKind::Prohibited || !attr_use.attribute.inheritable
5131 {
5132 continue;
5133 }
5134 let resolved = ct_data.resolved_attributes.get(i);
5135 let attr_key = resolved.and_then(|r| r.resolved_ref);
5136 let (name, ns) =
5137 self.resolve_attr_use_name_ns(attr_use, resolved, ct_data.target_namespace);
5138 let value = attr_use
5139 .attribute
5140 .default_value
5141 .as_deref()
5142 .or(attr_use.attribute.fixed_value.as_deref())
5143 .or_else(|| {
5144 attr_key
5145 .and_then(|k| self.schema_set.arenas.attributes.get(k))
5146 .and_then(|d| d.default_value.as_deref().or(d.fixed_value.as_deref()))
5147 });
5148 if let Some(val) = value {
5149 candidates.push((ns, name, val.to_string(), attr_key));
5150 }
5151 }
5152
5153 for ga in self.collect_group_attributes(ct_data) {
5155 if ga.use_kind == AttributeUseKind::Prohibited || !ga.inheritable {
5156 continue;
5157 }
5158 let value = ga.default_value.as_deref().or(ga.fixed_value.as_deref());
5159 if let Some(val) = value {
5160 candidates.push((ga.namespace, ga.name, val.to_string(), ga.attr_key));
5161 }
5162 }
5163
5164 if let Some(ev) = self.validation_stack.last_mut() {
5168 for (ns, name, val, attr_key) in candidates {
5169 if !ev.seen_attributes.contains(&(ns, name)) {
5170 ev.outgoing_inherited.insert(
5171 (ns, name),
5172 InheritedAttributeValue {
5173 value: val,
5174 attribute_key: attr_key,
5175 },
5176 );
5177 }
5178 }
5179 }
5180 }
5181
5182 fn check_required_attributes(
5188 &mut self,
5189 ct_data: &ComplexTypeDefData,
5190 seen: &HashSet<(Option<NameId>, NameId)>,
5191 ) -> bool {
5192 let mut has_missing = false;
5193 let mut checked_names: HashSet<(Option<NameId>, NameId)> = HashSet::new();
5194
5195 for (i, attr_use) in ct_data.attributes.iter().enumerate() {
5196 let resolved = ct_data.resolved_attributes.get(i);
5197 let (attr_name, attr_ns) =
5198 self.resolve_attr_use_name_ns(attr_use, resolved, ct_data.target_namespace);
5199 checked_names.insert((attr_ns, attr_name));
5200
5201 if attr_use.use_kind != AttributeUseKind::Required {
5202 continue;
5203 }
5204 if !seen.contains(&(attr_ns, attr_name)) {
5205 let name_str = self.schema_set.name_table.resolve(attr_name);
5206 self.report_error(
5207 "cvc-complex-type.4",
5208 format!("Required attribute '{}' is missing", name_str),
5209 );
5210 has_missing = true;
5211 }
5212 }
5213
5214 for ga in self.collect_group_attributes(ct_data) {
5216 checked_names.insert((ga.namespace, ga.name));
5217 if ga.use_kind != AttributeUseKind::Required {
5218 continue;
5219 }
5220 if !seen.contains(&(ga.namespace, ga.name)) {
5221 let name_str = self.schema_set.name_table.resolve(ga.name);
5222 self.report_error(
5223 "cvc-complex-type.4",
5224 format!("Required attribute '{}' is missing", name_str),
5225 );
5226 has_missing = true;
5227 }
5228 }
5229
5230 let any_type = self.schema_set.any_type_key();
5232 let mut base_type = ct_data.resolved_base_type;
5233 while let Some(TypeKey::Complex(base_ct_key)) = base_type {
5234 if base_ct_key == any_type {
5235 break;
5236 }
5237 let base_data = &self.schema_set.arenas.complex_types[base_ct_key];
5238
5239 for (i, attr_use) in base_data.attributes.iter().enumerate() {
5240 let resolved = base_data.resolved_attributes.get(i);
5241 let (attr_name, attr_ns) =
5242 self.resolve_attr_use_name_ns(attr_use, resolved, base_data.target_namespace);
5243 if !checked_names.insert((attr_ns, attr_name)) {
5244 continue; }
5246 if attr_use.use_kind != AttributeUseKind::Required {
5247 continue;
5248 }
5249 if !seen.contains(&(attr_ns, attr_name)) {
5250 let name_str = self.schema_set.name_table.resolve(attr_name);
5251 self.report_error(
5252 "cvc-complex-type.4",
5253 format!("Required attribute '{}' is missing", name_str),
5254 );
5255 has_missing = true;
5256 }
5257 }
5258
5259 for ga in self.collect_group_attributes(base_data) {
5260 if !checked_names.insert((ga.namespace, ga.name)) {
5261 continue;
5262 }
5263 if ga.use_kind != AttributeUseKind::Required {
5264 continue;
5265 }
5266 if !seen.contains(&(ga.namespace, ga.name)) {
5267 let name_str = self.schema_set.name_table.resolve(ga.name);
5268 self.report_error(
5269 "cvc-complex-type.4",
5270 format!("Required attribute '{}' is missing", name_str),
5271 );
5272 has_missing = true;
5273 }
5274 }
5275
5276 base_type = base_data.resolved_base_type;
5277 }
5278
5279 has_missing
5280 }
5281}
5282
5283fn resolve_base_uri(xml_base: &str, inherited: &str) -> String {
5289 if xml_base.is_empty() {
5290 return inherited.to_string();
5291 }
5292 if xml_base.contains("://")
5294 || xml_base.starts_with('/')
5295 || (xml_base.len() >= 2 && xml_base.as_bytes().get(1) == Some(&b':'))
5296 {
5297 return xml_base.to_string();
5298 }
5299 if inherited.is_empty() {
5300 return xml_base.to_string();
5301 }
5302 let last_sep = inherited.rfind('/').or_else(|| inherited.rfind('\\'));
5305 let base_dir = match last_sep {
5306 Some(pos) => &inherited[..=pos],
5307 None => "",
5308 };
5309 if base_dir.is_empty() {
5310 xml_base.to_string()
5311 } else {
5312 format!("{}{}", base_dir, xml_base)
5313 }
5314}
5315
5316#[cfg(test)]
5317#[path = "runtime_tests.rs"]
5318mod tests;