Commit Graph

5 Commits

Author SHA1 Message Date
380160cc2b refactor(validation): decompose XSD instance validation into composable rules
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.
2026-07-12 14:12:17 +02:00
95fde5b177
fix(xpath): format a large integer-valued number with no decimal point (#268)
XPath 1.0 4.2: an integer-valued number converts to a string with no decimal
point. The formatter only took the integer branch for a magnitude below 1e15,
so a value like 1234567890123456 (exact in a double, which holds integers
exactly to 2^53) printed as 1234567890123456.0. Raise the bound to 2^63, the
range where the Int64 conversion is safe; larger magnitudes still expand
through the exponent path.

Closes Apache Xalan conformance case string132.
2026-06-24 04:31:19 +02:00
b8dbf8e97a perf(xpath): compute document-order keys once per sort
Node-set ordering previously recomputed both nodes' root paths on every
precedes comparison (treePath is O(depth x siblings), so sorts were
O(n log n x depth)). Add decorate-sort-undecorate helpers,
sortedByDocumentOrder() and firstInDocumentOrder(), that compute each node's
order key once, and switch the evaluator's order-and-dedup, the EXSLT set
functions, string-value coercion, and NodeFunctions' target lookup to them.
set:leading/trailing also decorate once, reusing the keys for the pivot
filter and the final sort. precedes stays for pairwise use, sharing the
key comparator (Node.ordered). Behavior unchanged, all suites green.

Closes #113
2026-06-10 03:39:19 +02:00
f15786c0a5 feat(parity): C14N 2.0 text trimming, catalog delegation, XPath number formatting
Close the remaining documented parity edges:

- Canonical XML 2.0 TrimTextNodes: an option that strips leading and trailing
  whitespace from each text node (dropping all-whitespace nodes), exposed as
  Options.canonical2.
- XML Catalog delegation and chaining: delegatePublic, delegateSystem,
  delegateURI, and nextCatalog entries are parsed, and resolveSystem/
  resolvePublic/resolveURI gain a loadingCatalog overload that follows the
  longest matching delegate prefix and then each nextCatalog, with a
  visited-set guard against cycles.
- XPath number formatting: the canonical string form now expands any exponent
  in the shortest double rendering to a plain decimal, since XPath 1.0 forbids
  scientific notation.

Closes #70
2026-06-08 09:37:16 +02:00
d83e5a88ce feat(xpath): expression engine and the four-type model
Compile and evaluate full XPath 1.0 expressions, not just location paths.
Add the four-type Value (node-set, boolean, number, string) with the spec's
coercion rules and canonical number formatting, a recursive-descent parser
for the operator grammar (or/and, equality, relational, additive,
multiplicative, unary minus, union) whose grammatical position disambiguates
* and the operator keywords, function calls, variable references, and filter
expressions. Predicates are now arbitrary expressions (a numeric predicate
is a position test). Comparison follows the node-set quantification rules.
Query gains value/number/string/boolean accessors and a $variable binding
map; the core functions last, position, count, not, true, false, boolean,
number, and string ship with it.

Closes #42
2026-06-08 05:33:13 +02:00