PureXML/Tests/XSLTApplyImportsTests.swift
Mihaela Mihaljevic 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

52 lines
2.2 KiB
Swift

@testable import PureXML
import Testing
@Suite("XSLT xsl:apply-imports")
struct XSLTApplyImportsTests {
private let xsl = "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\""
private func transform(_ stylesheet: String, _ source: String, loader: @escaping (String) -> String?) throws -> String {
try PureXML.XSLT.transform(stylesheet: stylesheet, source: source, documentLoader: loader)
}
@Test("apply-imports invokes the lower-precedence imported template")
func test_applyImports() throws {
let base = """
<xsl:stylesheet version="1.0" \(xsl)>
<xsl:template match="item">[base:<xsl:value-of select="."/>]</xsl:template>
</xsl:stylesheet>
"""
let main = """
<xsl:stylesheet version="1.0" \(xsl)>
<xsl:import href="base.xsl"/>
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/"><out><xsl:apply-templates select="r/item"/></out></xsl:template>
<xsl:template match="item">main(<xsl:apply-imports/>)</xsl:template>
</xsl:stylesheet>
"""
let output = try transform(main, "<r><item>x</item></r>") { $0 == "base.xsl" ? base : nil }
#expect(output == "<out>main([base:x])</out>")
}
@Test("apply-imports with no lower-precedence match falls back to the built-in rule")
func test_applyImportsBuiltIn() throws {
let base = """
<xsl:stylesheet version="1.0" \(xsl)>
<xsl:template match="other">never</xsl:template>
</xsl:stylesheet>
"""
let main = """
<xsl:stylesheet version="1.0" \(xsl)>
<xsl:import href="base.xsl"/>
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:template match="/"><out><xsl:apply-templates select="r/item"/></out></xsl:template>
<xsl:template match="item">main[<xsl:apply-imports/>]</xsl:template>
</xsl:stylesheet>
"""
// No imported template matches "item", so apply-imports uses the built-in
// rule, which outputs the element's text value.
let output = try transform(main, "<r><item>y</item></r>") { $0 == "base.xsl" ? base : nil }
#expect(output == "<out>main[y]</out>")
}
}