如何在XSLT中将同一员工的所有记录合并为一行
解决方案:XSLT合并同一员工多笔支付记录为单行固定长度输出
要实现同一员工多笔支付记录合并为一行,核心是用Muenchian分组(XSLT 1.0中最常用的分组方法),按员工唯一标识Employee_Person_ID分组,再在每组内汇总不同类型的支付金额,最后输出固定长度的单行记录。
实现步骤
- 定义分组键:创建基于
Employee_Person_ID的键,同时过滤出符合业务条件的记录(在职状态、雇佣类型、指定扣除项等)。 - 遍历唯一员工分组:只处理每个员工的第一个匹配记录,代表整个分组。
- 提取员工基础信息:从分组内第一条记录获取姓名、ID等固定信息,同一员工这些信息应一致。
- 汇总各类型支付金额:在分组内累加对应扣除项的金额,再按固定格式输出。
- 保持固定长度格式:保留原代码中的字符串补全、数字格式化逻辑。
修改后的完整XSLT代码
<!-- 定义分组键:按Employee_Person_ID分组,同时过滤符合条件的记录 --> <xsl:key name="employeeGroup" match="/Export/Record[ (Employment_Indicator='Regular' or Employment_Indicator='Executive' or Employment_Indicator='Internship') and EmploymentStatusID = 'ACTIVE' and (DeductionName = 'HSA - Self' or DeductionName = 'HSA - Family' or DeductionName = 'Dependent Care - Single' or DeductionName = 'Dependent Care - Family' or DeductionName = 'Health Flex' or DeductionName = 'Health Flex Limited Purpose') and prd_effstart != '' and pp_suffix = '00' ]" use="Employee_Person_ID"/> <!-- 遍历每个唯一的员工分组 --> <xsl:for-each select="/Export/Record[ (Employment_Indicator='Regular' or Employment_Indicator='Executive' or Employment_Indicator='Internship') and EmploymentStatusID = 'ACTIVE' and (DeductionName = 'HSA - Self' or DeductionName = 'HSA - Family' or DeductionName = 'Dependent Care - Single' or DeductionName = 'Dependent Care - Family' or DeductionName = 'Health Flex' or DeductionName = 'Health Flex Limited Purpose') and prd_effstart != '' and pp_suffix = '00' and generate-id() = generate-id(key('employeeGroup', Employee_Person_ID)[1]) ]"> <xsl:sort select="Last_Name"/> <!-- 提取员工基础信息 --> <xsl:value-of select="Record_Type"/> <xsl:choose> <xsl:when test="Employee_Person_ID = ''"> <xsl:value-of select="$zeros"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="Employee_Person_ID"/> </xsl:otherwise> </xsl:choose> <xsl:value-of select="concat(translate(Last_Name, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), substring($spaces, 1, 30 - string-length(Last_Name)))"/> <xsl:value-of select="concat(translate(First_Name, 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), substring($spaces, 1, 20 - string-length(First_Name)))"/> <!-- 汇总Health Flex类金额 --> <xsl:variable name="totalFSA" select="sum(key('employeeGroup', Employee_Person_ID)[DeductionName='Health Flex']/FSA)"/> <xsl:variable name="totalFSALP" select="sum(key('employeeGroup', Employee_Person_ID)[DeductionName='Health Flex Limited Purpose']/FSALP)"/> <xsl:choose> <xsl:when test="$totalFSA > 0"> <xsl:value-of select="format-number($totalFSA * 100, '000000000000000')"/> </xsl:when> <xsl:when test="$totalFSALP > 0"> <xsl:value-of select="format-number($totalFSALP * 100, '000000000000000')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="substring($zeros, 1, 15)"/> <!-- 无金额时补零 --> </xsl:otherwise> </xsl:choose> <!-- 汇总Dependent Care类金额 --> <xsl:variable name="totalDCS" select="sum(key('employeeGroup', Employee_Person_ID)[DeductionName='Dependent Care - Single']/DCS)"/> <xsl:variable name="totalDCFM" select="sum(key('employeeGroup', Employee_Person_ID)[DeductionName='Dependent Care - Family']/DCFM)"/> <xsl:choose> <xsl:when test="$totalDCS > 0"> <xsl:value-of select="format-number($totalDCS * 100, '000000000000000')"/> </xsl:when> <xsl:when test="$totalDCFM > 0"> <xsl:value-of select="format-number($totalDCFM * 100, '000000000000000')"/> </xsl:when> <xsl:otherwise> <xsl:value-of select="substring($zeros, 1, 15)"/> <!-- 无金额时补零 --> </xsl:otherwise> </xsl:choose> <xsl:text>
</xsl:text> </xsl:for-each>
关键说明
- 分组键的过滤逻辑:把原代码中所有
<xsl:if>条件整合到match属性里,确保只对符合业务要求的记录分组。 - 金额汇总:用
sum()函数对分组内对应扣除项的金额求和,避免重复输出多行。 - 固定长度补全:无对应金额时输出15位零,和有金额时的格式一致,保证文件的固定长度要求。
- 分组唯一性判断:
generate-id() = generate-id(key('employeeGroup', Employee_Person_ID)[1])确保每个员工只处理一次。
内容的提问来源于stack exchange,提问作者Aaron Morales
相关产品推荐
相关产品推荐

