The two monolithic XSD content/identity rules only satisfied the OpenAPIKit validation idiom at the wrong granularity: no per-constraint removability, no isolable failing/near-miss tests. Split them into 32 named rules, each finding tagged at its origin and cached per XSDContext so the walk still runs once per document (the #101 decision against duplicating XSD's recursive type resolution still holds). Wired the streaming path's ID/IDREF and identity checks through the same framework instead of calling the validators imperatively, and added the unwrapAndLookup combinator the rule already named as required. Also includes the mandated repo-wide swiftformat/swiftlint pass.
49 lines
2.5 KiB
Swift
49 lines
2.5 KiB
Swift
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
|
|
}
|
|
}
|