XSLT: template selection resolves each match pattern once per transform via a per-run MatchCache (the pattern's node set is computed once over the source tree; selection becomes an identity lookup), replacing per-(node, template) recompilation and full-tree re-walks. XSD identity validation: a per-run query cache compiles each selector/field XPath once instead of at every visited element. Schematron was verified to already store compiled queries. Behavior unchanged (all suites green); a multi-template shape test over 300 nodes guards the optimized path. MatchCache lives in its own file to keep the transformer under the length cap. Closes #112
31 lines
1.4 KiB
Swift
31 lines
1.4 KiB
Swift
@testable import PureXML
|
|
import Testing
|
|
|
|
@Suite("XSLT match-pattern caching")
|
|
struct XSLTMatchCacheTests {
|
|
/// Guards the shape #112 optimized: many nodes against several templates,
|
|
/// where each match pattern must be compiled and evaluated once per
|
|
/// transform (not once per node) and selection must stay correct.
|
|
@Test("A multi-template transform over hundreds of nodes selects correctly")
|
|
func test_multiTemplateShape() throws {
|
|
let rows = (1 ... 300).map { index in
|
|
index.isMultiple(of: 2) ? "<even>\(index)</even>" : "<odd>\(index)</odd>"
|
|
}.joined()
|
|
let source = "<r>\(rows)</r>"
|
|
let stylesheet = """
|
|
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
|
<xsl:output method="text"/>
|
|
<xsl:template match="/"><xsl:apply-templates select="/r/*"/></xsl:template>
|
|
<xsl:template match="even">E</xsl:template>
|
|
<xsl:template match="odd | never">O</xsl:template>
|
|
</xsl:stylesheet>
|
|
"""
|
|
let output = try PureXML.XSLT.transform(stylesheet: stylesheet, source: source)
|
|
#expect(output.count == 300)
|
|
#expect(output.count(where: { $0 == "E" }) == 150)
|
|
#expect(output.count(where: { $0 == "O" }) == 150)
|
|
// Alternation is preserved (selection by pattern, not by order accident).
|
|
#expect(output.hasPrefix("OEOE"))
|
|
}
|
|
}
|