extension PureXML.Schema.ComplexValidator { /// A global element declaration is always in the schema's target /// namespace, so an instance element matches one only by full qualified /// name. The namespaced key already covers a no-namespace global (its key /// is `element:{}local`); matching an unqualified instance against a /// namespaced global by bare local name would conflate namespaces, e.g. /// accepting unqualified text where a namespaced `xs:short` is declared. func globalElementDeclaration(for name: PureXML.Model.QualifiedName) -> PureXML.Schema.ElementType? { types[PureXML.Schema.XSDParser.elementDeclarationKey(name)] } /// Validates a wildcard-matched child by its `processContents`: skip does /// nothing, lax validates against a global declaration when one exists, and /// strict requires one. func validateWildcardChild( _ child: PureXML.Model.Element, processContents: PureXML.Schema.ProcessContents, at path: XSDPath, namespaceBindings: [String: String], into errors: inout [XSDFinding], ) { switch processContents { case .skip: return case .lax: if let declaration = globalElementDeclaration(for: child.name) { validateChild(child, against: declaration, at: path, namespaceBindings: namespaceBindings, into: &errors) } case .strict: if let declaration = globalElementDeclaration(for: child.name) { validateChild(child, against: declaration, at: path, namespaceBindings: namespaceBindings, into: &errors) } else if let type = xsiDeclaredType(for: child, namespaceBindings: namespaceBindings) { validateChild(child, against: type, at: path, namespaceBindings: namespaceBindings, into: &errors) } else { errors.append(XSDFinding(.wildcardElementUndeclared, reason: "no declaration for wildcard-matched element '\(child.name.localName)'", at: path)) } } } /// The type named by a wildcard-matched element's `xsi:type`, when present. func xsiDeclaredType(for child: PureXML.Model.Element, namespaceBindings: [String: String]) -> PureXML.Schema.ElementType? { guard Self.xsiTypeAttributeValue(child) != nil else { return nil } guard let reference = Self.xsiTypeReference(child, namespaceBindings: namespaceBindings), let type = Self.resolveNamedType(reference, in: types) else { return nil } return type } }