PureXML/Sources/XSLT
Mihaela Mihaljevic 4552d24067
fix(xslt): make key(), id(), and EXSLT set functions linear over wide fan-outs (#300)
key(), id(), and EXSLT set:leading/set:trailing sorted their result with
sorted(by: Node.precedes). precedes recomputes both nodes' document-order keys
on every comparison, and each key walks the node to the root taking its index
among each parent's children, a linear scan of a wide parent. Over a wide flat
fan-out the sort was therefore quadratic. key() also deduplicated its matches
with matched.contains(where: ===), a linear membership scan, O(m^2) in the
match count. The EXSLT relative() used the cache-less documentOrder, rescanning
the parent per node.

Sort through sortedByDocumentOrder() (each key computed once behind a shared
sibling-index cache), deduplicate key()'s matches through a Set, and give
relative() a shared cache. The selected nodes, their document order, and the
deduplication are unchanged.

A key()-driven transform over a 20k-element document drops from ~1.15s to
~0.43s (~2.7x). The full suite, the Apache Xalan XSLT gold-output corpus, the
W3C XPath/XSLT/EXSLT tests, and the WASM build stay green; XSLTKeyIdOrderTests
pins key() dedup-and-order and id() document order.
2026-06-25 18:45:08 +02:00
..
XSLTAVT.swift
XSLTCollation.swift feat(xpath,xslt,wasm): evaluation budget, tailored collation, WASI runtime proof 2026-06-11 06:26:13 +02:00
XSLTDocumentCache.swift fix(xslt): resolve string-form document() against the stylesheet element's base URI (closes mdocs12/13) (#257) 2026-06-24 02:03:32 +02:00
XSLTElements.swift fix(xslt): xsl:namespace-alias keeps the literal prefix, remapping only the URI (closes namespace19/23/24/35/113) (#273) 2026-06-24 15:43:02 +02:00
XSLTFunctions.swift fix(xslt): make key(), id(), and EXSLT set functions linear over wide fan-outs (#300) 2026-06-25 18:45:08 +02:00
XSLTGlobals.swift fix(xslt): resolve string-form document() against the stylesheet element's base URI (closes mdocs12/13) (#257) 2026-06-24 02:03:32 +02:00
XSLTLookups.swift fix(xslt): make key(), id(), and EXSLT set functions linear over wide fan-outs (#300) 2026-06-25 18:45:08 +02:00
XSLTMatchCache.swift XSLT/XPath conformance: close 68 Apache Xalan cases (#254) 2026-06-24 00:13:14 +02:00
XSLTModel.swift fix(xslt): xsl:namespace-alias keeps the literal prefix, remapping only the URI (closes namespace19/23/24/35/113) (#273) 2026-06-24 15:43:02 +02:00
XSLTNamespaceFixup.swift
XSLTNumbering.swift fix(xslt): count the from boundary node in xsl:number level=single when it matches count (#270) 2026-06-24 10:47:49 +02:00
XSLTParser.swift fix(xslt): honor xml:space=preserve when stripping stylesheet whitespace (#271) 2026-06-24 10:57:47 +02:00
XSLTParserDeclarations.swift fix(xslt): xsl:namespace-alias keeps the literal prefix, remapping only the URI (closes namespace19/23/24/35/113) (#273) 2026-06-24 15:43:02 +02:00
XSLTParserEntry.swift fix(xslt): resolve string-form document() against the stylesheet element's base URI (closes mdocs12/13) (#257) 2026-06-24 02:03:32 +02:00
XSLTParserStructural.swift fix(xslt): evaluate the xsl:number format attribute as an AVT (#269) 2026-06-24 10:40:11 +02:00
XSLTRawText.swift
XSLTRuntime.swift fix(xslt): resolve string-form document() against the stylesheet element's base URI (closes mdocs12/13) (#257) 2026-06-24 02:03:32 +02:00
XSLTSorting.swift fix(xslt): resolve string-form document() against the stylesheet element's base URI (closes mdocs12/13) (#257) 2026-06-24 02:03:32 +02:00
XSLTTransform.swift fix(xslt): serialize a namespaced element as XML under the html output method (16.2) (#260) 2026-06-24 02:48:50 +02:00
XSLTTransformer.swift fix(xslt): ignore disable-output-escaping for attribute, comment, and PI values (#264) 2026-06-24 03:41:56 +02:00
XSLTUnitCollector.swift fix(xslt): composition cycles terminate; id() gains a per-document index 2026-06-10 18:07:02 +02:00
XSLTWhitespace.swift fix(xslt): match strip-space/preserve-space element tests by namespace (#265) 2026-06-24 03:52:45 +02:00