如何在单个XSLT样式表中执行多步顺序转换
解决XSLT合并后排序未使用修改后节点值的问题
问题出在合并后的样式表中,排序操作直接读取了原始XML的f2节点值,而非第一步修改后的结果。以下是两种可行的解决思路:
方案一:先生成修改后的节点集,再排序
先通过变量保存所有c节点修改后的结果,再对这个变量中的节点执行排序操作。这种方式适合XSLT 1.0及以上版本(XSLT 1.0需要用节点集函数将结果树片段转为可操作的节点集):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt"> <!-- 默认身份转换模板,复制未匹配的节点 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理<root/s/a/b>节点:先修改子节点,再排序 --> <xsl:template match="root/s/a/b"> <xsl:copy> <!-- 第一步:生成所有修改f2后的<c>节点,存入变量 --> <xsl:variable name="modified-c-nodes"> <xsl:apply-templates select="c"/> </xsl:variable> <!-- 第二步:对修改后的节点按f1、修改后的f2排序 --> <xsl:for-each select="msxsl:node-set($modified-c-nodes)/c"> <xsl:sort select="f1"/> <xsl:sort select="f2"/> <xsl:copy-of select="."/> </xsl:for-each> </xsl:copy> </xsl:template> <!-- 修改f2节点:末尾带'x'的添加前缀'0' --> <xsl:template match="c/f2[substring(., string-length(.)) = 'x']"> <f2>0<xsl:value-of select="."/></f2> </xsl:template> </xsl:stylesheet>
如果使用XSLT 2.0或更高版本,无需msxsl:node-set,直接用$modified-c-nodes/c即可访问变量中的节点。
方案二:排序时直接计算修改后的f2值
无需提前生成修改后的节点集,在排序逻辑中直接计算f2的修改后值,确保排序依据的是最终要输出的内容:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- 默认身份转换模板 --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- 处理<root/s/a/b>节点:先排序(用修改后的f2值),再应用修改模板 --> <xsl:template match="root/s/a/b"> <xsl:copy> <xsl:for-each select="c"> <xsl:sort select="f1"/> <!-- 排序时直接计算带前缀的f2值 --> <xsl:sort select="if (substring(f2, string-length(f2)) = 'x') then concat('0', f2) else f2"/> <!-- 对排序后的节点应用修改模板,输出最终结果 --> <xsl:apply-templates select="."/> </xsl:for-each> </xsl:copy> </xsl:template> <!-- 修改f2节点的模板 --> <xsl:template match="c/f2[substring(., string-length(.)) = 'x']"> <f2>0<xsl:value-of select="."/></f2> </xsl:template> </xsl:stylesheet>
关键说明
之前合并失败的原因是排序操作优先基于原始节点值执行,之后才应用修改模板。上述两种方案都确保了排序依据的是修改后的f2值:方案一是先完成修改再排序,方案二是在排序时直接使用修改后的计算逻辑。
内容的提问来源于stack exchange,提问作者juankinspain
相关产品推荐
相关产品推荐

