PureXML 0.4.6
XPath string-function and xsl:number quadratic fixes. Backward compatible, results identical.
Fixed
translate()is linear (the from-to map is built once), andcontains()/substring-before()/substring-after()use a linear-time Knuth-Morris-Pratt search instead of matching the needle at every haystack position — closing an O(n×m) denial-of-service vector on repetitive untrusted strings (#308).xsl:number level="any"was cubic over a wide fan-out (each preceding sibling rescanned the child list); now quadratic by walking the child slice directly (#309).xsl:numberlevelssingle/multiplewere quadratic numbering a wide list; now linear via a per-(parent, count pattern) rank cache. An 8000-item defaultxsl:number: ~3.5s -> ~0.04s (~90x) (#310).
Found by scale-testing the string functions and numbering at 2x/4x/8x — workload shapes the default corpus does not exercise.
Verification
Full suite (1753 tests), the W3C XML conformance, RELAX NG, Apache Xalan XSLT gold-output, and C14N corpora, plus the WASM build, all green across macOS, Linux, and Windows. swiftformat and swiftlint --strict clean.
Full changelog: https://github.com/mihaelamj/PureXML/blob/main/CHANGELOG.md