Whitespace-only text nodes are removed from the source tree for elements named by strip-space before transformation, with preserve-space and a more specific name test winning over *, and xml:space=preserve on a source element or ancestor overriding the stripping. The name sets fold across xsl:include/xsl:import. Refactors the stylesheet compile loop through a Parts accumulator to absorb the new top-level elements within the complexity budget.
68 lines
2.7 KiB
Swift
68 lines
2.7 KiB
Swift
@testable import PureXML
|
|
import Testing
|
|
|
|
@Suite("XSLT strip-space / preserve-space")
|
|
struct XSLTWhitespaceTests {
|
|
private let xsl = "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\""
|
|
|
|
private func transform(_ stylesheet: String, _ source: String) throws -> String {
|
|
try PureXML.XSLT.transform(stylesheet: stylesheet, source: source)
|
|
}
|
|
|
|
@Test("strip-space removes whitespace-only text nodes; a copy reflects it")
|
|
func test_stripSpace() throws {
|
|
let style = """
|
|
<xsl:stylesheet version="1.0" \(xsl)>
|
|
<xsl:strip-space elements="a"/>
|
|
<xsl:output method="xml" omit-xml-declaration="yes"/>
|
|
<xsl:template match="/"><xsl:copy-of select="a"/></xsl:template>
|
|
</xsl:stylesheet>
|
|
"""
|
|
let source = "<a>\n <b/>\n <b/>\n</a>"
|
|
// The indentation whitespace between <b/> elements is stripped.
|
|
#expect(try transform(style, source) == "<a><b/><b/></a>")
|
|
}
|
|
|
|
@Test("Without strip-space the whitespace is preserved")
|
|
func test_noStrip() throws {
|
|
let style = """
|
|
<xsl:stylesheet version="1.0" \(xsl)>
|
|
<xsl:output method="xml" omit-xml-declaration="yes"/>
|
|
<xsl:template match="/"><xsl:copy-of select="a"/></xsl:template>
|
|
</xsl:stylesheet>
|
|
"""
|
|
let source = "<a>\n <b/>\n</a>"
|
|
#expect(try transform(style, source).contains("\n "))
|
|
}
|
|
|
|
@Test("preserve-space overrides strip-space for a named element")
|
|
func test_preserveOverrides() throws {
|
|
let style = """
|
|
<xsl:stylesheet version="1.0" \(xsl)>
|
|
<xsl:strip-space elements="*"/>
|
|
<xsl:preserve-space elements="keep"/>
|
|
<xsl:output method="xml" omit-xml-declaration="yes"/>
|
|
<xsl:template match="/"><xsl:copy-of select="*"/></xsl:template>
|
|
</xsl:stylesheet>
|
|
"""
|
|
// strip-space="*" strips <drop>'s whitespace, but <keep> preserves its own.
|
|
let stripped = try transform(style, "<drop>\n <x/>\n</drop>")
|
|
#expect(stripped == "<drop><x/></drop>")
|
|
let kept = try transform(style, "<keep>\n <x/>\n</keep>")
|
|
#expect(kept.contains("\n "))
|
|
}
|
|
|
|
@Test("xml:space=preserve on a source element keeps its whitespace despite strip-space")
|
|
func test_xmlSpacePreserve() throws {
|
|
let style = """
|
|
<xsl:stylesheet version="1.0" \(xsl)>
|
|
<xsl:strip-space elements="a"/>
|
|
<xsl:output method="xml" omit-xml-declaration="yes"/>
|
|
<xsl:template match="/"><xsl:copy-of select="a"/></xsl:template>
|
|
</xsl:stylesheet>
|
|
"""
|
|
let source = "<a xml:space=\"preserve\">\n <b/>\n</a>"
|
|
#expect(try transform(style, source).contains("\n "))
|
|
}
|
|
}
|