XSLT 1.0中基于键的考勤数据值比较问题求助
XSLT 1.0 出勤人数差异检查问题修正方案
问题背景
需用XSLT 1.0处理WebService返回的XML,检查高中班级近5天出勤人数是否存在差异,原代码出现编译错误,无法得到预期输出。
输入XML
<response> <school1> <class> <attendance><class>a</class><day>monday</day><count>20</count></attendance> <attendance><class>a</class><day>tuesday</day><count>20</count></attendance> <attendance><class>a</class><day>wednesday</day><count>20</count></attendance> <attendance><class>a</class><day>thursday</day><count>20</count></attendance> <attendance><class>a</class><day>friday</day><count>20</count></attendance> <attendance><class>b</class><day>monday</day><count>20</count></attendance> <attendance><class>b</class><day>tuesday</day><count>20</count></attendance> <attendance><class>b</class><day>wednesday</day><count>12</count></attendance> <attendance><class>b</class><day>thursday</day><count>20</count></attendance> <attendance><class>b</class><day>friday</day><count>20</count></attendance> <attendance><class>c</class><day>monday</day><count>22</count></attendance> <attendance><class>c</class><day>tuesday</day><count>23</count></attendance> <attendance><class>c</class><day>wednesday</day><count>12</count></attendance> <attendance><class>c</class><day>thursday</day><count>20</count></attendance> <attendance><class>c</class><day>friday</day><count>22</count></attendance> </class> </school1> </response>
原错误XSLT代码
<xsl:stylesheet version="1.0"> <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> <xsl:key name="test" match="attendance[class='a']" use="count"/> <xsl:key name="test2" match="attendance[class='a'][last()]" use="count"/> <xsl:key name="test3" match="attendance[class='b']" use="count"/> <xsl:key name="test4" match="attendance[class='b'][last()]" use="count"/> <xsl:key name="test5" match="attendance[class='c']" use="count"/> <xsl:key name="test6" match="attendance[class='c'][last()]" use="count"/> <xsl:template match="/"> <xsl:for-each select="/response/school1/class/attendance"> <xsl:choose> <xsl:when test="$test!=$test2"> <xsl:value-of select="Check class roll" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="Perfect Attendance" /> </xsl:otherwise> <xsl:when test ="$test3!=$test4"> <xsl:value-of select="Check class roll" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="Perfect Attendance" /> </xsl:otherwise> <xsl:when test ="$test5!=$test6"> <xsl:value-of select="Check class roll" /> </xsl:when> <xsl:otherwise> <xsl:value-of select="Perfect Attendance" /> </xsl:otherwise> </xsl:choose> </xsl:for-each> </xsl:template> </xsl:stylesheet>
原代码错误分析
- 键的使用错误:
xsl:key定义后需通过key()函数调用,不能直接用$key名引用;且match="attendance[class='a'][last()]"中的last()是全局所有attendance节点的最后一个,不是班级分组内的最后一个,逻辑完全错误。 xsl:choose语法错误:一个xsl:choose只能包含多个xsl:when和一个xsl:otherwise,原代码嵌套多个otherwise违反语法。- 遍历逻辑错误:原
for-each遍历所有attendance节点,需求是按班级分组处理,而非每个出勤记录单独处理。 - 字符串输出错误:
<xsl:value-of select="Check class roll" />未用单引号包裹字符串,会被解析为节点选择,而非输出固定文本。
修正后的XSLT代码
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" encoding="UTF-8"/> <!-- 按班级名称分组 --> <xsl:key name="class-group" match="attendance" use="class"/> <xsl:template match="/"> <!-- 遍历每个班级的唯一分组 --> <xsl:for-each select="/response/school1/class/attendance[generate-id() = generate-id(key('class-group', class)[1])]"> <xsl:variable name="current-class" select="class"/> <!-- 获取当前班级所有出勤人数 --> <xsl:variable name="all-counts" select="key('class-group', $current-class)/count"/> <xsl:choose> <!-- 检查所有count是否与第一个count相同 --> <xsl:when test="$all-counts != $all-counts[1]"> <xsl:text>Check class roll</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text>Perfect Attendance</xsl:text> </xsl:otherwise> </xsl:choose> <!-- 添加换行符分隔每个班级结果 --> <xsl:text> </xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet>
代码说明
- 分组逻辑:用
key('class-group', class)按班级名称对attendance节点分组,通过generate-id()筛选出每个班级的唯一节点作为分组入口。 - 差异检查:对每个班级的所有
count节点,判断是否存在与第一个count值不同的节点,若存在则输出提示,否则输出正常。 - 输出格式:设置
output method="text",直接输出预期的文本结果,每个班级结果后添加换行符。
预期输出
Perfect Attendance Check class roll Check class roll
内容的提问来源于stack exchange,提问作者user1393064
相关产品推荐
相关产品推荐

