Validate XSD identity constraints over the instance document in a pass that walks the tree alongside type validation: - xs:unique requires the selected nodes' field tuples to be distinct, excluding any node that is missing a field. - xs:key additionally requires every field to be present. - xs:keyref requires each tuple to equal a tuple of the named key or unique visible in an enclosing scope, resolved through a stack of scope frames so a keyref and the key it refers to may sit on the same element. The selector and field XPaths run on the existing XPath engine, relative to the declaring element and each selected node. Constraints are gathered for every element declaration at any depth, keyed by element name. Closes #67
32 lines
1.3 KiB
Swift
32 lines
1.3 KiB
Swift
public extension PureXML.Schema {
|
|
/// The kind of an ``IdentityConstraint``, and for a keyref the name of the
|
|
/// key it refers to.
|
|
enum IdentityConstraintKind: Sendable, Equatable {
|
|
/// Tuples must be distinct where present; a node missing a field is
|
|
/// excluded rather than rejected.
|
|
case unique
|
|
/// Tuples must be distinct and every field must be present.
|
|
case key
|
|
/// Every tuple must equal a tuple of the named key or unique in scope.
|
|
case keyref(refer: String)
|
|
}
|
|
|
|
/// An XSD identity constraint declared on an element: `xs:unique`, `xs:key`,
|
|
/// or `xs:keyref`. The `selector` XPath chooses the nodes the constraint
|
|
/// ranges over (relative to the declaring element), and each `field` XPath
|
|
/// extracts one component of the value tuple from a selected node.
|
|
struct IdentityConstraint: Sendable {
|
|
public var name: String
|
|
public var kind: IdentityConstraintKind
|
|
public var selector: String
|
|
public var fields: [String]
|
|
|
|
public init(name: String, kind: IdentityConstraintKind, selector: String, fields: [String]) {
|
|
self.name = name
|
|
self.kind = kind
|
|
self.selector = selector
|
|
self.fields = fields
|
|
}
|
|
}
|
|
}
|