Add the RELAX NG pattern algebra (Pattern, NameClass), a parser for the XML syntax into a grammar of start plus named defines, and James Clark's derivative validation algorithm. The pattern is derived through each start-tag, attribute, text, and end-tag event with simplifying constructors; the document is valid when the residual pattern is nullable. Supports element, attribute, text, empty, notAllowed, group, choice, interleave, optional, zeroOrMore, oneOrMore, mixed, list, ref/define, data, value, and the name classes; handles interleave and recursive grammars, reusing the XSD datatype library for data and value. Closes #11 Closes #12
43 lines
1.6 KiB
Swift
43 lines
1.6 KiB
Swift
public extension PureXML.Schema {
|
|
/// A RELAX NG name class: which element or attribute names a pattern matches.
|
|
indirect enum NameClass: Sendable {
|
|
case anyName
|
|
case anyNameExcept(NameClass)
|
|
case name(namespace: String, localName: String)
|
|
case nsName(String)
|
|
case choice(NameClass, NameClass)
|
|
|
|
/// Whether `name` is in this class.
|
|
func contains(_ name: PureXML.Model.QualifiedName) -> Bool {
|
|
let namespace = name.namespaceURI ?? ""
|
|
switch self {
|
|
case .anyName: return true
|
|
case let .anyNameExcept(except): return !except.contains(name)
|
|
case let .name(wantedNamespace, wantedLocal): return namespace == wantedNamespace && name.localName == wantedLocal
|
|
case let .nsName(wantedNamespace): return namespace == wantedNamespace
|
|
case let .choice(left, right): return left.contains(name) || right.contains(name)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// A RELAX NG pattern (the simplified algebra used by the derivative
|
|
/// algorithm). `optional`, `zeroOrMore`, and `mixed` are expressed through
|
|
/// these constructors; `after` is internal to derivation.
|
|
indirect enum Pattern: Sendable {
|
|
case empty
|
|
case notAllowed
|
|
case text
|
|
case choice(Pattern, Pattern)
|
|
case interleave(Pattern, Pattern)
|
|
case group(Pattern, Pattern)
|
|
case oneOrMore(Pattern)
|
|
case element(NameClass, Pattern)
|
|
case attribute(NameClass, Pattern)
|
|
case data(BuiltinType)
|
|
case value(String)
|
|
case list(Pattern)
|
|
case ref(String)
|
|
case after(Pattern, Pattern)
|
|
}
|
|
}
|