如何用XSLT 1.0生成学生未完成辅导编号的逗号分隔列表?
问题:在XSLT 1.0中生成未完成辅导编号的逗号分隔列表
现有一段XSLT代码,通过<xsl:for-each>遍历学生已完成的辅导记录,生成包含辅导编号和日期的表格:
<xsl:for-each select="$HistDB//AssignmentHistory/*/StudentItems/Item/Name[@Counsel and .=$strName]"> <!-- 按辅导编号升序排序 --> <xsl:sort select="@Counsel" data-type="number"/> <!-- 再按日期升序排序 --> <xsl:sort select="local-name(../../..)"/> <tr> <!-- 辅导编号 --> <td class="counsel"> <xsl:value-of select="@Counsel"/> </td> <!-- 日期(DD/MM/YYYY格式) --> <td class="counsel"> <xsl:variable name="strWeek" select="local-name(../../..)"/> <xsl:value-of select="substring($strWeek, 8, 2)"/> <xsl:text>/</xsl:text> <xsl:value-of select="substring($strWeek, 5, 2)"/> <xsl:text>/</xsl:text> <xsl:value-of select="substring($strWeek, 2, 4)"/> </td> </tr> </xsl:for-each>
这段代码会输出一个表格,展示学生已完成的辅导编号和对应的日期。
现在需求是:辅导编号范围为1-20,需要在表格之后展示学生未完成的辅导编号的逗号分隔列表,格式示例:
未分配:1, 3, 4, 6, 9, 11, 13, 14, 15, 16, 17, 18, 19, 20
同时希望确认该需求能否通过XSLT 1.0实现,并简化代码完成需求。
我尝试了以下方案,但结果错误地列出了全部20个编号,需要协助解决:
<xsl:variable name="missing-items"> <xsl:call-template name="list-missing-items"> <xsl:with-param name="items" select="$HistDB//AssignmentHistory/*/StudentItems/Item/Name[@Counsel and .=$strName]"/> </xsl:call-template> </xsl:variable> <missing-items> <xsl:value-of select="translate(normalize-space($missing-items), ' ', ',')" /> </missing-items>
解决方案(XSLT 1.0)
之前的问题在于调用的list-missing-items模板没有正确对比已完成编号,导致生成了全量的1-20编号。以下是完整的实现方案:
核心思路
- 先收集所有已完成的辅导编号,形成可对比的节点集
- 遍历1-20的所有编号,筛选出不在已完成列表中的编号
- 将筛选出的编号拼接成逗号分隔的字符串
完整代码实现
<!-- 第一步:收集所有已完成的辅导编号 --> <xsl:variable name="completed-counsels" select="$HistDB//AssignmentHistory/*/StudentItems/Item/Name[@Counsel and .=$strName]/@Counsel" /> <!-- 第二步:定义递归模板生成未完成编号列表 --> <xsl:template name="generate-missing-counsels"> <xsl:param name="current" select="1" /> <xsl:param name="max" select="20" /> <xsl:param name="result" select="" /> <xsl:choose> <xsl:when test="$current > $max"> <!-- 移除结果开头多余的", "(如果存在) --> <xsl:value-of select="substring($result, 3)" /> </xsl:when> <xsl:otherwise> <!-- 检查当前编号是否未完成 --> <xsl:variable name="is-missing" select="not($completed-counsels = $current)" /> <xsl:variable name="new-result"> <xsl:value-of select="$result" /> <xsl:if test="$is-missing"> <xsl:if test="$result != ''">, </xsl:if> <xsl:value-of select="$current" /> </xsl:if> </xsl:variable> <!-- 递归处理下一个编号 --> <xsl:call-template name="generate-missing-counsels"> <xsl:with-param name="current" select="$current + 1" /> <xsl:with-param name="max" select="$max" /> <xsl:with-param name="result" select="$new-result" /> </xsl:call-template> </xsl:otherwise> </xsl:choose> </xsl:template> <!-- 第三步:在表格后调用模板输出结果 --> <p>未分配:<xsl:call-template name="generate-missing-counsels" /></p>
代码说明
completed-counsels变量:通过XPath直接收集所有已完成辅导的@Counsel属性值,形成节点集,方便后续对比判断。- 递归模板
generate-missing-counsels:- 从编号1开始遍历到20
- 每次检查当前编号是否存在于已完成列表,不存在则加入结果字符串
- 递归结束后,自动移除结果开头多余的
,
- 输出部分:直接调用模板,将结果嵌入到需求指定的文本格式中。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

