XSLT命名模板中节点排序无输出问题及替代实现咨询
XSLT 1.0 命名模板中
<for-each>排序后输出消失的问题及解决方法 关于输出消失的问题
这种行为不正常,大概率是<xsl:sort>的select表达式逻辑有误导致的。在XSLT 1.0中,<xsl:sort>本身不会过滤节点,哪怕排序键为空,节点依然会被保留在循环中。出现输出消失的常见原因:
select="text()"仅匹配节点的直接子文本节点,如果你的参数节点的文本嵌套在子元素里,或者没有直接文本节点,这个表达式会返回空序列,部分处理器或插件可能对空排序键的处理存在异常,导致输出中断。- 检查参数传递是否正确:确保调用模板时传入的参数确实是预期的节点集,而非单个空节点。
快速排查方法:把<xsl:sort>的select替换为string(.)(取整个节点的字符串值,而非仅直接子文本),测试是否能正常输出。示例代码:
<xsl:for-each select="$nodes"> <xsl:sort select="string(.)"/> <xsl:value-of select="local-name()"/> </xsl:for-each>
命名模板中实现节点排序的其他方法
方法1:用<xsl:apply-templates>结合排序
这是XSLT推荐的模板驱动写法,比<for-each>更灵活,尤其适合复杂处理逻辑:
<xsl:template name="sort-and-process"> <xsl:param name="target-nodes"/> <!-- 对传入的节点应用模板并排序 --> <xsl:apply-templates select="$target-nodes"> <xsl:sort select="string(.)"/> <!-- 按节点字符串值排序,可按需修改排序规则 --> </xsl:apply-templates> </xsl:template> <!-- 匹配需要处理的节点,输出本地名称 --> <xsl:template match="*"> <xsl:value-of select="local-name()"/> </xsl:template>
方法2:使用EXSLT扩展函数(需处理器支持)
如果你的XSLT处理器支持EXSLT(IntelliJ的XQuery and XSLT插件通常支持),可以用set:sort函数直接对节点集排序:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:set="http://exslt.org/sets" extension-element-prefixes="set" version="1.0"> <xsl:template name="sort-nodes"> <xsl:param name="nodes"/> <xsl:for-each select="set:sort($nodes, 'string(.)')"> <xsl:value-of select="local-name()"/> </xsl:for-each> </xsl:template> </xsl:stylesheet>
注意:这种方法依赖扩展,移植性不如标准写法,优先推荐第一种方法。
内容的提问来源于stack exchange,提问作者Roland Illig
相关产品推荐
相关产品推荐

