PureXML/Sources/Validation/SchematronModel.swift
Mihaela Mihaljevic 68122ad887 feat(schematron): dynamic message content and phase support
Two ISO Schematron gaps, the most validator-relevant first:

- Dynamic messages: an assert/report message is now a template, so
  <value-of select=> renders the string value of its XPath at the context
  node and <name> renders the node's name. A finding can report actual
  values ("Age 120 must be under 100") instead of static text.
- Phases: <phase id><active pattern=> scopes which patterns run.
  validate(_:phase:) honors a requested phase or the schema's
  defaultPhase; nil or #ALL runs every pattern.

let variables, abstract rules/extends, diagnostics, and key()/document()
remain (the last depends on XSLT-style function injection).

Part of #80
2026-06-08 15:45:27 +02:00

43 lines
1.6 KiB
Swift

extension PureXML.Validation {
/// One piece of an assertion message: literal text, a `<value-of select=>`
/// whose XPath is evaluated against the context node, or a `<name>` rendering
/// the context node's name. Lets a finding report actual values.
enum SchematronMessagePart {
case text(String)
case valueOf(PureXML.XPath.Query)
case name
}
/// One `<assert>` or `<report>`: a compiled XPath test and its message
/// template. An assert flags when its test is false; a report flags when its
/// test is true.
struct SchematronAssertion {
let isReport: Bool
let test: PureXML.XPath.Query
let message: [SchematronMessagePart]
}
/// One `<rule>`: a compiled context that selects the nodes the rule fires on,
/// and its assertions.
struct SchematronRule {
let context: PureXML.XPath.Query
let assertions: [SchematronAssertion]
}
/// One `<pattern>`: an optional id (referenced by `<active>` in a phase) and a
/// list of rules. A node is processed by the first rule in the pattern whose
/// context selects it (the ISO Schematron firing rule).
struct SchematronPattern {
let id: String?
let rules: [SchematronRule]
}
/// A compiled Schematron schema: its patterns and its phases (each phase id
/// mapped to the pattern ids it activates), plus the declared default phase.
struct SchematronSchema {
let patterns: [SchematronPattern]
let phases: [String: [String]]
let defaultPhase: String?
}
}