XSLT技术问题:无法计算同一员工多条薪资记录的总和
如何用XSLT计算员工的TotalPay(所有薪资GrossPay之和)
我来帮你搞定这个问题——你需要的是让每个员工的每一条薪资记录都带上自己所有薪资的总和TotalPay对吧?先理清楚你的数据源和期望结果,再给你对应的XSLT解决方案。
你的XML数据(已修正标签错误)
首先注意原XML里的<Type>标签闭合写成了</Paytype>,我已经帮你修正了,不然XML会无效:
<Payroll_Data> <EmpId>1000</EmpId> <FirstName>Mark</FirstName> <LastName>Henry</LastName> <Salary> <Type>B</Type> <GrossPay>1000.50</GrossPay> </Salary> <Salary> <Type>X</Type> <GrossPay>847.50</GrossPay> </Salary> </Payroll_Data> <Payroll_Data> <EmpId>1001</EmpId> <FirstName>John</FirstName> <LastName>Diggle</LastName> <Salary> <Type>B</Type> <GrossPay>800.98</GrossPay> </Salary> <Salary> <Type>X</Type> <GrossPay>630.50</GrossPay> </Salary> <Salary> <Type>Y</Type> <GrossPay>600.50</GrossPay> </Salary> </Payroll_Data>
期望的输出结果
我把你要的结果整理成更清晰的表格形式(注意原结果里的847.48应该是笔误,正确总和是1848.00):
| EmpId | FirstName | LastName | Type | GrossPay | TotalPay |
|---|---|---|---|---|---|
| 1000 | Mark | Henry | B | 1000.50 | 1848.00 (1000.50+847.50) |
| 1000 | Mark | Henry | X | 847.50 | 1848.00 |
| 1001 | John | Diggle | B | 800.98 | 2031.98 (800.98+630.50+600.50) |
| 1001 | John | Diggle | X | 630.50 | 2031.98 |
| 1001 | John | Diggle | Y | 600.50 | 2031.98 |
对应的XSLT解决方案
核心思路是先给每个员工计算好总薪资,再遍历他的每一条薪资记录复用这个总和,代码如下:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text" indent="yes"/> <!-- 先输出表头 --> <xsl:template match="/"> <xsl:text>EmpId FirstName LastName Type GrossPay TotalPay </xsl:text> <xsl:apply-templates select="*/Payroll_Data"/> </xsl:template> <!-- 处理每个员工节点 --> <xsl:template match="Payroll_Data"> <!-- 计算当前员工所有薪资的总和,存到变量里方便复用 --> <xsl:variable name="totalPay" select="sum(Salary/GrossPay)"/> <!-- 遍历当前员工的每一条薪资记录 --> <xsl:for-each select="Salary"> <!-- 输出员工的基础信息 --> <xsl:value-of select="../EmpId"/> <xsl:text> </xsl:text> <xsl:value-of select="../FirstName"/> <xsl:text> </xsl:text> <xsl:value-of select="../LastName"/> <xsl:text> </xsl:text> <!-- 输出当前薪资的类型和金额 --> <xsl:value-of select="Type"/> <xsl:text> </xsl:text> <xsl:value-of select="GrossPay"/> <xsl:text> </xsl:text> <!-- 输出总薪资,第一条记录显示计算公式 --> <xsl:value-of select="$totalPay"/> <xsl:if test="position()=1"> <xsl:text> (</xsl:text> <xsl:for-each select="../Salary/GrossPay"> <xsl:value-of select="."/> <xsl:if test="position()!=last()">+</xsl:if> </xsl:for-each> <xsl:text>)</xsl:text> </xsl:if> <!-- 换行 --> <xsl:text> </xsl:text> </xsl:for-each> </xsl:template> </xsl:stylesheet>
代码关键点说明:
- 总和计算:用
sum(Salary/GrossPay)直接获取当前员工所有薪资的GrossPay之和,不用重复计算,效率更高。 - 复用总和:把计算好的总和存到
totalPay变量里,每个薪资条目直接调用这个变量就行。 - 公式说明:通过
position()=1判断是不是当前员工的第一条薪资记录,是的话就追加计算的公式,和你期望的格式完全匹配。
内容的提问来源于stack exchange,提问作者ar1991
相关产品推荐
相关产品推荐

