PureXML/Tests/XSLTPatternPriorityTests.swift
Mihaela Mihaljevic 70fdcab840
fix(xslt): give an axis-prefixed match pattern its node-test default priority (#266)
XSLT 1.0 5.5: the default priority of a single-step match pattern is set by its
node test, regardless of an explicit child:: or attribute:: axis. defaultPriority
matched the whole pattern string, so attribute::node() fell through to 0 (a name
test) instead of -0.5 (a node() node test), wrongly outranking @*. Strip a
leading child::/attribute:: axis before classifying the node test.

Closes Apache Xalan conformance cases conflictres29 and conflictres30.
2026-06-24 04:08:00 +02:00

30 lines
1.3 KiB
Swift

import Testing
@testable import PureXML
/// XSLT 1.0 5.5 default-priority rules for template match patterns.
@Suite("XSLT pattern priority")
struct XSLTPatternPriorityTests {
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("an axis-prefixed node test ties with @*, not outranks it (5.5)")
func test_axisPatternPriority() throws {
// attribute::node() is a node() node test, default priority -0.5 like @*,
// not a name test (0). On the resulting tie the last template in document
// order wins, so @* (declared last) applies, not attribute::node() which
// was wrongly given priority 0 (Apache Xalan conflictres29, conflictres30).
let style = """
<xsl:stylesheet version="1.0" \(xsl)>
<xsl:output omit-xml-declaration="yes"/>
<xsl:template match="/"><out><xsl:apply-templates select="doc/e/@a"/></out></xsl:template>
<xsl:template match="attribute::node()">node</xsl:template>
<xsl:template match="@*">star</xsl:template>
</xsl:stylesheet>
"""
#expect(try transform(style, "<doc><e a=\"1\"/></doc>") == "<out>star</out>")
}
}