XSLT 2.0按empID与Date分组求和结果异常求助
XSLT分组求和错误修正
源XML数据
<?xml version="1.0" encoding="UTF-8"?> <Workers> <Worker> <empID>12354</empID> <Cost> <Date>2023-10-06-07:00</Date> <Type>Expense</Type> <Amount>108</Amount> </Cost> <Cost> <Date>2023-10-06-07:00</Date> <Type>Bonus</Type> <Amount>200</Amount> </Cost> <Cost> <Date>2023-10-06-07:00</Date> <Type>Expense</Type> <Amount>550</Amount> </Cost> <Cost> <Date>2023-10-10-07:00</Date> <Type>Expense</Type> <Amount>100</Amount> </Cost> <Cost> <Date>2023-10-10-07:00</Date> <Type>Bonus</Type> <Amount>200</Amount> </Cost> <Cost> <Date>2023-10-10-07:00</Date> <Type>Expense</Type> <Amount>120</Amount> </Cost> <Cost> <Date>2023-10-11-07:00</Date> <Type>Expense</Type> <Amount>120</Amount> </Cost> </Worker> <Worker> <empID>4567</empID> <Cost> <Date>2023-10-06-07:00</Date> <Type>Expense</Type> <Amount>90</Amount> </Cost> <Cost> <Date>2023-10-06-07:00</Date> <Type>Bonus</Type> <Amount>10</Amount> </Cost> <Cost> <Date>2023-10-06-07:00</Date> <Type>Expense</Type> <Amount>120</Amount> </Cost> <Cost> <Date>2023-10-10-07:00</Date> <Type>Expense</Type> <Amount>1297</Amount> </Cost> <Cost> <Date>2023-10-10-07:00</Date> <Type>Bonus</Type> <Amount>312</Amount> </Cost> </Worker> </Workers>
预期需求与输出
- 按
<empID>和<Date>分组记录; - 每个唯一
<Date>对应生成一个<Worker>节点:empID为12354的员工有3个唯一Date,需生成3个<Worker>;empID为4567的员工有2个唯一Date,需生成2个<Worker>; - 对每个唯一
<Date>,分别求和Type为Expense和Bonus的金额。
预期输出XML:
<?xml version="1.0" encoding="UTF-8"?> <Workers> <Worker> <UniqueID>12354</UniqueID> <Date>2023-10-06-07:00</Date> <ExpenseAmount>658.00</ExpenseAmount> <BonusAmount>200.00</BonusAmount> </Worker> <Worker> <UniqueID>12354</UniqueID> <Date>2023-10-10-07:00</Date> <ExpenseAmount>220.00</ExpenseAmount> <BonusAmount>200.00</BonusAmount> </Worker> <Worker> <UniqueID>12354</UniqueID> <Date>2023-10-11-07:00</Date> <ExpenseAmount>120.00</ExpenseAmount> <BonusAmount>0.00</BonusAmount> </Worker> <Worker> <UniqueID>4567</UniqueID> <Date>2023-10-06-07:00</Date> <ExpenseAmount>210.00</ExpenseAmount> <BonusAmount>10.00</BonusAmount> </Worker> <Worker> <UniqueID>4567</UniqueID> <Date>2023-10-10-07:00</Date> <ExpenseAmount>1297.00</ExpenseAmount> <BonusAmount>312.00</BonusAmount> </Worker> </Workers>
注:原预期输出中第三个Worker的金额标注存在笔误,此处已修正为正确值
当前编写的XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="Workers"> <Workers> <xsl:for-each-group select="Worker" group-by="empID"> <xsl:for-each-group select="current-group()" group-by="Cost/Date"> <Worker> <UniqueID> <xsl:value-of select="empID"/> </UniqueID> <Date> <xsl:value-of select="current-grouping-key()"/> </Date> <ExpenseAmount> <xsl:value-of select="format-number(sum(current-group()/Cost[Type = 'Expense']/Amount), '#.00')"/> </ExpenseAmount> <BonusAmount> <xsl:value-of select="format-number(sum(current-group()/Cost[Type = 'Bonus']/Amount), '#.00')"/> </BonusAmount> </Worker> </xsl:for-each-group> </xsl:for-each-group> </Workers> </xsl:template> </xsl:stylesheet>
当前输出结果
<?xml version="1.0" encoding="UTF-8"?> <Workers> <Worker> <UniqueID>12354</UniqueID> <Date>2023-10-06-07:00</Date> <ExpenseAmount>998.00</ExpenseAmount> <BonusAmount>400.00</BonusAmount> </Worker> <Worker> <UniqueID>12354</UniqueID> <Date>2023-10-10-07:00</Date> <ExpenseAmount>998.00</ExpenseAmount> <BonusAmount>400.00</BonusAmount> </Worker> <Worker> <UniqueID>12354</UniqueID> <Date>2023-10-11-07:00</Date> <ExpenseAmount>998.00</ExpenseAmount> <BonusAmount>400.00</BonusAmount> </Worker> <Worker> <UniqueID>4567</UniqueID> <Date>2023-10-06-07:00</Date> <ExpenseAmount>1507.00</ExpenseAmount> <BonusAmount>322.00</BonusAmount> </Worker> <Worker> <UniqueID>4567</UniqueID> <Date>2023-10-10-07:00</Date> <ExpenseAmount>1507.00</ExpenseAmount> <BonusAmount>322.00</BonusAmount> </Worker> </Workers>
问题原因与修正方案
错误原因
原代码第二层分组对象是current-group()(即整个<Worker>节点),而非该员工下的<Cost>节点。这导致分组后current-group()仍包含该员工所有日期的<Cost>记录,求和时会累加该员工所有日期的金额,而非当前分组日期的金额。
修正后的XSLT代码
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="2.0"> <xsl:output method="xml" indent="yes"/> <xsl:template match="Workers"> <Workers> <!-- 按empID分组 --> <xsl:for-each-group select="Worker" group-by="empID"> <!-- 对当前员工的所有Cost节点按Date分组 --> <xsl:for-each-group select="current-group()/Cost" group-by="Date"> <Worker> <UniqueID> <xsl:value-of select="../empID"/> </UniqueID> <Date> <xsl:value-of select="current-grouping-key()"/> </Date> <ExpenseAmount> <xsl:value-of select="format-number(sum(current-group()[Type='Expense']/Amount), '#.00')"/> </ExpenseAmount> <BonusAmount> <xsl:value-of select="format-number(sum(current-group()[Type='Bonus']/Amount), '#.00')"/> </BonusAmount> </Worker> </xsl:for-each-group> </xsl:for-each-group> </Workers> </xsl:template> </xsl:stylesheet>
修正说明
- 第二层分组对象改为
current-group()/Cost,即当前员工下的所有<Cost>节点,按<Date>分组; - 求和时直接对
current-group()(当前日期的所有<Cost>)中对应Type的<Amount>求和; <UniqueID>通过../empID获取当前Cost所属员工的ID,确保关联正确。
内容的提问来源于stack exchange,提问作者MAT0718
相关产品推荐
相关产品推荐

