XSLT V1含generate_id与key的For Each循环未遍历第三组问题
这种分组到第三组就“罢工”的情况我之前踩过坑,大概率是key逻辑、循环上下文或者模板条件出了问题,给你几个具体的排查方向:
先确认key的匹配逻辑是否精准
检查你定义的key的use属性,第三组的3个节点是不是返回了相同的键值?比如如果key是按@type分组,第三组的节点刚好@type全一样,那key分组后只会得到一个唯一组,自然循环只执行一次。另外要注意键值的大小写、空格或者特殊字符,比如有的节点@type是"Option",有的是"option",XSLT默认是大小写敏感的,这也会导致分组异常。检查for-each的上下文是否被意外修改
如果你在options模板里用了<xsl:apply-templates>、<xsl:for-each>或者其他切换节点上下文的指令,可能会打断外层的循环迭代。比如模板里不小心跳转到了其他节点,导致后续的循环没继续执行。可以在for-each里加个调试输出,确认循环到底跑了几次:<xsl:for-each select="$sec-rows"> <xsl:message>正在处理第<xsl:value-of select="position()"/>个节点:<xsl:value-of select="name()"/></xsl:message> <xsl:call-template name="options"/> </xsl:for-each>如果控制台输出了3条日志,那说明循环确实跑了3次,问题出在
options模板里;如果只输出1条,那就是$sec-rows的节点在循环时被过滤了。排查options模板的过滤条件
看看options模板里有没有<xsl:if>、<xsl:choose>这类条件判断,是不是第三组的节点不满足条件,导致没有输出内容,看起来像没运行。比如模板里判断<xsl:if test="@required='true'">,但第三组的节点@required都是"false",自然就没输出了。检查key的节点范围(针对XSLT 1.0)
XSLT 1.0里的key默认是匹配整个文档的节点,如果你的$sec-rows是文档的一个子集,那key可能会把文档里其他地方的同键值节点也包含进来,导致分组逻辑混乱。这种情况下可以改用“Muenchian分组”的标准写法,确保只对目标节点集分组:<xsl:key name="sec-key" match="your-target-node" use="group-key"/> <!-- 先获取唯一分组键 --> <xsl:for-each select="$sec-rows[generate-id() = generate-id(key('sec-key', group-key)[1])]"> <!-- 遍历当前分组下的所有节点 --> <xsl:for-each select="key('sec-key', group-key)"> <xsl:call-template name="options"/> </xsl:for-each> </xsl:for-each>如果是XSLT 2.0及以上,建议直接用
<xsl:for-each-group>,语法更清晰,也不容易出错:<xsl:for-each-group select="$sec-rows" group-by="group-key"> <xsl:for-each select="current-group()"> <xsl:call-template name="options"/> </xsl:for-each> </xsl:for-each-group>
内容的提问来源于stack exchange,提问作者iainc

