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.
50 lines
2.2 KiB
Swift
50 lines
2.2 KiB
Swift
public extension PureXML.Validation.DTDSchema {
|
|
/// Returns `node` with DTD attribute defaults applied: every element gains any
|
|
/// attribute its `<!ATTLIST>` declares with a default or `#FIXED` value and
|
|
/// that the element omits. `#REQUIRED` and `#IMPLIED` add nothing. The injected
|
|
/// values are the normalized defaults from the declaration, so an editor reads
|
|
/// the same effective attributes a validating processor would see.
|
|
func applyingDefaults(to node: PureXML.Model.Node) -> PureXML.Model.Node {
|
|
// Rebuilt bottom-up (iterative) so a deeply-nested document does not
|
|
// overflow the stack; each element gains its DTD-declared defaults once its
|
|
// children are rebuilt.
|
|
node.rebuildingBottomUp { original, rebuiltChildren in
|
|
switch original {
|
|
case let .element(element):
|
|
var result = element
|
|
result.children = rebuiltChildren
|
|
return .element(withDefaults(result))
|
|
case .document:
|
|
return .document(rebuiltChildren)
|
|
default:
|
|
return original
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Adds the attributes `element`'s `<!ATTLIST>` declares with a default or
|
|
/// `#FIXED` value and that the element omits. `result.children` is assumed
|
|
/// already set by the caller.
|
|
private func withDefaults(_ element: PureXML.Model.Element) -> PureXML.Model.Element {
|
|
var result = element
|
|
guard let declarations = attributes[element.name.description] else { return result }
|
|
for declaration in declarations {
|
|
guard let value = Self.defaultValue(declaration) else { continue }
|
|
let present = result.attributes.contains {
|
|
$0.name.description == declaration.name || $0.name.localName == declaration.name
|
|
}
|
|
if !present {
|
|
result.attributes.append(PureXML.Model.Attribute(declaration.name, value))
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
private static func defaultValue(_ declaration: PureXML.Validation.AttributeDeclaration) -> String? {
|
|
switch declaration.defaultDecl {
|
|
case let .value(value), let .fixed(value): value
|
|
case .required, .implied: nil
|
|
}
|
|
}
|
|
}
|