You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于生效日期与Sequence的XSLT转换实现需求

XML转CSV的XSLT解决方案来了!

你说的需求我完全理解——就是把XML里带Sequence属性的Effective_Change节点,按Effective_Moment的日期部分分组:同日期的合并成一行CSV,不同日期的单独输出对吧?我帮你写了一个XSLT 2.0的实现,刚好能解决这个问题。

需求回顾

  • 若多个Effective_Change节点的Effective_Moment日期部分相同,仅生成一行CSV输出;
  • 日期部分不同的话,每个日期分别生成一行。

你的原始XML(我补全了截断的闭合标签,保证文件合法)

<?xml version="1.0" encoding="UTF-8"?>
<peci:Workers_Effective_Stack xmlns:peci="urn:com.w/peci">
<peci:Worker>
<peci:Summary>
<peci:Integration_Event>14d964101fdb0156e164341b45548d01</peci:Integration_Event>
<peci:Integration_Sent_On>2018-05-10T08:41:39.375-07:00</peci:Integration_Sent_On>
<peci:Payroll_Company_Name>West Brooke - Biweekly: B</peci:Payroll_Company_Name>
<peci:Pay_Group_Country>US</peci:Pay_Group_Country>
<peci:Pay_Group_Code>j</peci:Pay_Group_Code>
<peci:Pay_Period_Start>2018-04-30-07:00</peci:Pay_Period_Start>
<peci:Pay_Period_End>2018-05-13-07:00</peci:Pay_Period_End>
<peci:Updated_From>2018-05-07T19:50:30.963-07:00</peci:Updated_From>
<peci:Updated_To>2018-05-10T08:41:39.375-07:00</peci:Updated_To>
<peci:Effective_From>2018-04-30-07:00</peci:Effective_From>
<peci:Effective_To>2018-05-13-07:00</peci:Effective_To>
<peci:Change_Detection>Include only changes entered since the last successful run.</peci:Change_Detection>
<peci:First_Primary_Run_of_Pay_Period>0</peci:First_Primary_Run_of_Pay_Period>
<peci:Ad_Hoc_Run>0</peci:Ad_Hoc_Run>
<peci:Full_Snapshot>0</peci:Full_Snapshot>
<peci:Worker_Count>2</peci:Worker_Count>
<peci:Version>1</peci:Version>
</peci:Summary>
<peci:Worker>
<peci:Worker_Summary>
<peci:WID>rd</peci:WID>
<peci:Employee_ID>33333</peci:Employee_ID>
<peci:Name>Test 1</peci:Name>
</peci:Worker_Summary>
<peci:Effective_Change peci:Sequence="0">
<peci:Derived_Event_Code>DTA</peci:Derived_Event_Code>
<peci:Effective_Moment>2018-05-10T08:29:21.235-07:00</peci:Effective_Moment>
<peci:Entry_Moment>2018-05-10T08:29:21.235-07:00</peci:Entry_Moment>
<peci:Worker_Status>
<peci:Status>Active</peci:Status>
<peci:Active>1</peci:Active>
<peci:Active_Status_Date>2018-01-08-08:00</peci:Active_Status_Date>
<peci:Terminated>0</peci:Terminated>
<peci:Hire_Date>2018-01-08-08:00</peci:Hire_Date>
<peci:Original_Hire_Date>2018-01-08-08:00</peci:Original_Hire_Date>
<peci:Is_Rehire>0</peci:Is_Rehire>
<peci:Continuous_Service_Date>2018-01-08-08:00</peci:Continuous_Service_Date>
<peci:First_Day_of_Work>2018-01-08-08:00</peci:First_Day_of_Work>
<peci:Seniority_Date>2018-01-08-08:00</peci:Seniority_Date>
</peci:Worker_Status>
</peci:Effective_Change>
<peci:Effective_Change peci:Sequence="1">
<peci:Derived_Event_Code>DTA</peci:Derived_Event_Code>
<peci:Effective_Moment>2018-05-10T08:31:27.880-07:00</peci:Effective_Moment>
<peci:Entry_Moment>2018-05-10T08:31:27.880-07:00</peci:Entry_Moment>
<peci:Worker_Status>
<peci:Status>Active</peci:Status>
<peci:Active>1</peci:Active>
<peci:Active_Status_Date>2018-01-08-08:00</peci:Active_Status_Date>
<peci:Terminated>0</peci:Terminated>
<peci:Hire_Date>2018-01-08-08:00</peci:Hire_Date>
<peci:Original_Hire_Date>2018-01-08-08:00</peci:Original_Hire_Date>
<peci:Is_Rehire>0</peci:Is_Rehire>
<peci:Continuous_Service_Date>2018-01-08-08:00</peci:Continuous_Service_Date>
<peci:First_Day_of_Work>2018-01-08-08:00</peci:First_Day_of_Work>
<peci:Seniority_Date>2018-01-08-08:00</peci:Seniority_Date>
</peci:Worker_Status>
</peci:Effective_Change>
<peci:Effective_Change peci:Sequence="2">
<peci:Derived_Event_Code>DTA</peci:Derived_Event_Code>
<peci:Effective_Moment>2018-05-12T08:29:21.235-07:00</peci:Effective_Moment>
<peci:Entry_Moment>2018-05-12T08:29:21.235-07:00</peci:Entry_Moment>
<peci:Worker_Status>
<peci:Status>Active</peci:Status>
<peci:Active>1</peci:Active>
<peci:Active_Status_Date>2018-01-08-08:00</peci:Active_Status_Date>
<peci:Terminated>0</peci:Terminated>
<peci:Hire_Date>2018-01-08-08:00</peci:Hire_Date>
<peci:Original_Hire_Date>2018-01-08-08:00</peci:Original_Hire_Date>
<peci:Is_Rehire>0</peci:Is_Rehire>
<peci:Continuous_Service_Date>2018-01-08-08:00</peci:Continuous_Service_Date>
<peci:First_Day_of_Work>2018-01-08-08:00</peci:First_Day_of_Work>
<peci:Seniority_Date>2018-01-08-08:00</peci:Seniority_Date>
</peci:Worker_Status>
</peci:Effective_Change>
</peci:Worker>
</peci:Worker>
</peci:Workers_Effective_Stack>

实现代码(XSLT 2.0)

这个方案用了XSLT的分组功能,专门适配你的需求:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:peci="urn:com.w/peci">
    <xsl:output method="text" encoding="UTF-8"/>

    <!-- 先输出CSV表头 -->
    <xsl:template match="/">
        <xsl:text>Employee_ID,Name,Effective_Date,Derived_Event_Code,Status,Active,Hire_Date&#10;</xsl:text>
        <xsl:apply-templates select="//peci:Worker[peci:Worker_Summary]"/>
    </xsl:template>

    <!-- 处理每个员工节点 -->
    <xsl:template match="peci:Worker[peci:Worker_Summary]">
        <!-- 先缓存员工基础信息,避免重复查找 -->
        <xsl:variable name="basic-info" select="peci:Worker_Summary"/>
        
        <!-- 核心逻辑:按Effective_Moment的日期部分分组 -->
        <xsl:for-each-group select="peci:Effective_Change" group-by="substring-before(peci:Effective_Moment, 'T')">
            <!-- 同日期的节点取第一个的字段值(从你的示例看,同日期内容完全一致,这样处理没问题) -->
            <xsl:variable name="first-change" select="current-group()[1]"/>
            
            <!-- 拼接CSV行,逗号分隔字段,换行符用&#10; -->
            <xsl:value-of select="$basic-info/peci:Employee_ID"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="$basic-info/peci:Name"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="current-grouping-key()"/> <!-- 分组的日期值 -->
            <xsl:text>,</xsl:text>
            <xsl:value-of select="$first-change/peci:Derived_Event_Code"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="$first-change/peci:Worker_Status/peci:Status"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="$first-change/peci:Worker_Status/peci:Active"/>
            <xsl:text>,</xsl:text>
            <xsl:value-of select="$first-change/peci:Worker_Status/peci:Hire_Date"/>
            <xsl:text>&#10;</xsl:text>
        </xsl:for-each-group>
    </xsl:template>

    <!-- 忽略冗余的文本节点,避免输出无效内容 -->
    <xsl:template match="text()"/>
</xsl:stylesheet>

关键逻辑说明

  1. 分组核心:用xsl:for-each-group把同一日期的Effective_Change归为一组,分组依据是Effective_Moment中T之前的纯日期部分。
  2. 字段复用:同组节点内容一致,直接取第一个节点的字段值即可,无需重复处理。
  3. CSV格式优化:如果你的字段可能包含逗号或双引号,记得给字段套双引号,内部双引号要转成两个(比如把"改成""),这个可以按需扩展。

输出效果

运行这个XSLT后,会得到符合要求的CSV:

Employee_ID,Name,Effective_Date,Derived_Event_Code,Status,Active,Hire_Date
33333,Test 1,2018-05-10,DTA,Active,1,2018-01-08-08:00
33333,Test 1,2018-05-12,DTA,Active,1,2018-01-08-08:00

完美实现你的规则:2018-05-10的两个Effective_Change合并成一行,2018-05-12单独一行。


内容的提问来源于stack exchange,提问作者Viral Shah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:26:03