Commit Graph

221 Commits

Author SHA1 Message Date
610b7d0ca0 feat(xslt): implement xsl:namespace-alias, completing #81
A literal result element and its attributes in a stylesheet namespace
bound by stylesheet-prefix are rewritten on output to the namespace and
prefix bound by result-prefix (#default supported), so a stylesheet can
emit literal xsl: elements. Prefixes resolve through the in-scope xmlns
declarations; aliases fold across include/import. Splits AVT parsing into
XSLTAVT.swift and trims the transformer to stay within length budgets.
2026-06-09 02:10:16 +02:00
26ebeed155 docs: refresh test count to 624 2026-06-09 01:59:40 +02:00
19baa0cd75 Merge: XSLT xsl:decimal-format (#81) 2026-06-09 01:59:40 +02:00
2d2572e265 feat(xslt): implement xsl:decimal-format for format-number
format-number now honors named and default decimal formats: the decimal
separator, grouping separator, percent, minus sign, zero-digit (for
non-Latin digit sets), NaN, and infinity symbols come from the chosen
xsl:decimal-format, in both the picture and the output. FormatNumber is
parameterized over the symbol set and the formats thread through the
function table; folded across include/import.
2026-06-09 01:59:37 +02:00
2f79be18e1 docs: refresh test count to 619 2026-06-09 01:52:22 +02:00
618bf170c8 Merge: XSLT xsl:fallback (#81) 2026-06-09 01:52:22 +02:00
61ab8ce8f9 feat(xslt): implement xsl:fallback for forwards-compatible processing
An unrecognized XSLT element instantiates its xsl:fallback children in its
place, or is dropped when it has none; a fallback under a supported
instruction is ignored. The fallback content is handled in the instantiate
loop alongside variables, so the evaluate dispatch stays within budget.
2026-06-09 01:52:21 +02:00
0dae8e5670 docs: refresh test count to 615 2026-06-09 01:49:34 +02:00
b9e2cd9fa5 Merge: XSLT xsl:apply-imports (#81) 2026-06-09 01:49:34 +02:00
4f11bafa28 feat(xslt): implement xsl:apply-imports
Re-applies templates to the current node in the current mode, considering
only templates of lower import precedence than the one being instantiated,
falling back to the built-in rule when none match. Threads the current
mode and import precedence through the evaluation context, and moves the
transformer runtime types into XSLTRuntime.swift (namespaced, via private
aliases) to stay within the file-length and namespacing gates.
2026-06-09 01:49:33 +02:00
21ed15b1ec refactor(xslt): keep ResultItem/XSLTContext file-private for namespacing
Only the static deduplicated helper moves to XSLTElements.swift (it needs
no private types); attributeSetAttributes stays in the transformer so the
evaluation context and result-item types remain file-private, satisfying
the one-file-scope-type namespacing gate.
2026-06-09 01:41:48 +02:00
75ed549c33 docs: refresh test count to 613 2026-06-09 01:39:46 +02:00
fe30781f79 Merge: XSLT xsl:attribute-set (#81) 2026-06-09 01:39:46 +02:00
22cd88f8ba feat(xslt): implement xsl:attribute-set and use-attribute-sets
Named attribute sets apply to a literal result element or xsl:element via
use-attribute-sets; sets may include other sets recursively with a cycle
guard, set attributes are lowest precedence so the element's own
attributes override them, and same-named attributes collapse to the last.
Folded across xsl:include/xsl:import. Splits the element-building helpers
into XSLTElements.swift to stay within the file-length budget.
2026-06-09 01:39:45 +02:00
0a78822845 docs: refresh test count to 609 2026-06-09 01:29:38 +02:00
b28f865495 Merge: XSLT xsl:message (#81) 2026-06-09 01:29:37 +02:00
367b5b9425 feat(xslt): implement xsl:message with terminate
xsl:message instantiates its body as diagnostic text and produces no
result-tree output; terminate=yes records the text and aborts the
transform with an XSLTError.terminated, halting further instantiation.
Splits the transform entry points into XSLTTransform.swift and moves the
message case to keep within the complexity and file-length budgets.
2026-06-09 01:29:37 +02:00
ff1cdfd244 docs: refresh test count to 606 2026-06-09 01:23:01 +02:00
83fdeb9bfa Merge: XSLT strip-space/preserve-space (#81) 2026-06-09 01:23:00 +02:00
10d9525e3e feat(xslt): implement xsl:strip-space and xsl:preserve-space
Whitespace-only text nodes are removed from the source tree for elements
named by strip-space before transformation, with preserve-space and a
more specific name test winning over *, and xml:space=preserve on a
source element or ancestor overriding the stripping. The name sets fold
across xsl:include/xsl:import. Refactors the stylesheet compile loop
through a Parts accumulator to absorb the new top-level elements within
the complexity budget.
2026-06-09 01:22:59 +02:00
0a78aa76a1 docs: refresh test count to 602 2026-06-09 01:11:54 +02:00
2551fd16fd Merge: RELAX NG attribute-error detail 2026-06-09 01:11:54 +02:00
d80718c530 feat(relaxng): distinguish undeclared attribute from invalid value
A RELAX NG attribute failure now reports an undeclared attribute
("attribute @b is not allowed on <n>") separately from a declared
attribute carrying a bad value ("attribute @count on <n>: 'abc' is not a
valid integer"), quoting the value and naming its datatype by reusing the
text detail. The declared value pattern is found by matching the
attribute name through the residual.
2026-06-09 01:11:54 +02:00
2dc066b573 docs: refresh test count to 601 2026-06-09 01:09:30 +02:00
2cc434abfd Merge: RELAX NG datatype-mismatch detail 2026-06-09 01:09:30 +02:00
3be6832c23 feat(relaxng): quote the offending value and name the datatype in text errors
A RELAX NG text/datatype mismatch now reports the rich datatype reason
(quoting the value and naming the type, e.g. 'abc' is not a valid
integer) and a value mismatch quotes both the actual text and the
required literal, instead of a generic "text content is not valid". The
detail is peeled from the content pattern at the failure point through
choice, group, list, and ref.
2026-06-09 01:09:29 +02:00
3021615b66 docs: refresh test count to 600 2026-06-09 00:59:26 +02:00
cc4a40314c Merge: DTD located content-model errors 2026-06-09 00:59:26 +02:00
fb31033ce8 feat(dtd): located content-model errors with recovery hints
An element whose children break its content model now names each stray
child outside the model's alphabet individually, and reports a pure
order/count violation once with the allowed elements as a hint, instead
of a single opaque "do not match its content model". Adds an alphabet
extractor to the content-model matcher. This brings DTD to the same
located standard as the XSD, RELAX NG, and Schematron validators, so all
four schema languages give editor-grade diagnostics.
2026-06-09 00:59:25 +02:00
3e3ca0f971 docs: refresh test count to 596 2026-06-09 00:55:43 +02:00
489ff498fa Merge: XSD located content-model errors 2026-06-09 00:55:18 +02:00
ea5387db90 feat(xsd): located, recovering content-model errors
A content-model violation is now placed at the offending child with a
recovery hint naming what was expected, instead of one opaque "content
does not match the content model" per element. The sequence/choice
automaton is walked child by child via its follow-set to flag the first
child the model rejects, or the incomplete content at the end; an xs:all
group recovers past each stray child and reports every missing required
member. Well-placed children are still validated for their own content,
so an editor sees every problem at once. Brings XSD to the same located,
recovering standard as the RELAX NG, DTD, and Schematron validators.
2026-06-09 00:55:17 +02:00
bbd293521a docs: refresh test count to 592 2026-06-09 00:41:31 +02:00
e8af2563dd Merge: RELAX NG located, recovering errors (#79) 2026-06-09 00:40:56 +02:00
ae271d65f6 feat(relaxng): located, recovering validation errors for editor use
Adds RelaxNG.errors(in:) reporting every way a document fails the schema
as individual located errors with coding paths, recovering past each
failure so all of a faulty document's problems surface at once instead of
only the first. Errors carry recovery hints naming the element types
accepted at the failure point, and distinguish unexpected elements,
invalid or missing attributes, invalid text/datatype content, and missing
required content. RelaxNG.validation() exposes the schema as a
Validation<Node, Void>, composing with the same framework as the XSD,
DTD, and Schematron rules. The boolean derivative engine remains the
authority on validity; the diagnostic walk only places and explains the
failures, recovering each step so it never cascades. Splits the engine
and the diagnostics into separate files.
2026-06-09 00:40:56 +02:00
5eeb29d10a docs: move closed catalog #86 to done in roadmap, refresh test count 2026-06-08 18:06:13 +02:00
346eb66f45 Merge: catalog group-level prefer (#86) 2026-06-08 18:05:04 +02:00
2414dbc3bc feat(catalog): honor group-level prefer override
A prefer attribute on a <group> (or nested <catalog>) overrides the
catalog-wide preference for the <public> entries within it, inherited
through nested groups. The resolver records each public entry's effective
preference and consults it when falling back from an unmatched system
identifier, so two entries in one catalog can prefer differently. A system
match still always wins.
2026-06-08 18:05:03 +02:00
cc44800a4a Merge: Schematron abstract patterns (#80) 2026-06-08 17:58:33 +02:00
d7a40b9a7a feat(schematron): instantiate abstract patterns with is-a/param
A <pattern abstract="true"> is a template whose rule queries carry $name
references; a <pattern is-a="…"> with <param> children instantiates it,
substituting each parameter into the template's context, test, <let>
value, and <value-of select=> before the XPath is compiled. The
substitution is a single left-to-right pass, so a substituted value is
never rescanned and a short name never captures a longer one; $name
references that are not parameters stay as written. The template itself
contributes no rules.
2026-06-08 17:58:33 +02:00
873aed7025 Merge: changelog-touched gate (verification.md) 2026-06-08 17:49:22 +02:00
e06a29ae1c chore(ci): add the changelog-touched gate verification.md requires
verification.md listed scripts/check-changelog-touched.sh in the local
gate, but the script did not exist (exit 127). Adds it: when a change set
modifies Sources/*.swift it must also update CHANGELOG.md, comparing the
branch against its base plus the working tree, no-op on a clean base, with
a CHANGELOG_SKIP escape hatch for refactor-only changes. Wires it into
check-all.sh alongside the other shell gates.
2026-06-08 17:49:21 +02:00
0171697c37 Merge: changelog and readme for #79 2026-06-08 17:45:42 +02:00
e0e498c4bb docs: record #79 RELAX NG work in changelog and refresh test count
Adds the Unreleased changelog entry for the datatypeLibrary resolution,
value-space <value> comparison, nsName subtraction, and compact-syntax
annotations/div/concatenation work, and updates the README suite count to
573 tests in 84 suites.
2026-06-08 17:45:42 +02:00
eff530bde7 Merge: RNC string concatenation (#79) 2026-06-08 17:38:59 +02:00
9845e1cd9d feat(relaxng): fold RNC ~ string concatenation
A string literal split with ~ ("a" ~ "b") is the single literal "ab",
the way long values and namespace URIs are wrapped across lines. The fold
applies wherever a string literal is read: value literals and the URIs of
namespace/datatypes/include/external declarations.
2026-06-08 17:38:58 +02:00
79f424321c feat(relaxng): compare typed <value> in the datatype value space
A <value> pattern now carries its datatype, so matching compares the
instance and the literal in that type's value space rather than purely
lexically. Numeric and date/time types compare by value (1 equals 01,
1.5 equals 1.50); booleans treat 1/true and 0/false as equal; string and
token compare by their whitespace-normalized lexical form, as before.
Untyped values default to the built-in token type, and a bare string
literal in the compact syntax is token-typed. Durations and binary types
fall under the lexical rule.
2026-06-08 17:36:16 +02:00
c1e181db50 Merge: datatypeLibrary resolution and nsName subtraction (#79) 2026-06-08 17:21:54 +02:00
147d776d21 feat(relaxng): resolve datatypeLibrary and nsName subtraction
Adds a datatypeLibrary-aware datatype resolver to the XML-syntax parser:
the in-scope library is inherited from the nearest ancestor, the default
(empty) library defines only string and token, and the W3C XML Schema
library defines the full built-in set. A type the in-scope library does
not define is an unknown datatype, so the <data>/<value> pattern matches
nothing rather than silently validating.

Adds an nsNameExcept name-class case so nsName with an <except> child
(XML syntax) and prefix:* - name subtraction (compact syntax) narrow a
namespace wildcard. The compact lexer splits prefix:* into a trailing-
colon word plus a star symbol, which the parser now recognizes.

Existing RELAX NG facet tests declared XSD types without the library and
relied on lenient resolution; they now declare the XSD datatypeLibrary,
matching what a conformant processor requires.
2026-06-08 17:21:49 +02:00
704e5e2161 Merge: RNC annotations and div grouping (#79) 2026-06-08 17:12:39 +02:00