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

XSLT 2.0基于日期有效性校验分组XML节点实现问题

XSLT日期切片转换问题排查

源XML结构

现有如下结构的源XML:

<CompoundEmployee>
    <id>176</id>
    <person>
        <action>NO CHANGE</action>
        <created_by>CONV_ADMIN</created_by>
        <logon_user_id>10005005</logon_user_id>
        <logon_user_is_active>true</logon_user_is_active>
        <person_id>176</person_id>
        <person_id_external>10005005</person_id_external>
        <personal_information>
            <end_date>9999-12-31</end_date>
            <first_name>yutaka</first_name>
            <first_name_previous>Robbin</first_name_previous>
            <first_name_alt1>Robbin</first_name_alt1>
            <start_date>2021-06-03</start_date>
        </personal_information>
        <personal_information>
            <end_date>2021-06-02</end_date>
            <first_name>wataru</first_name>
            <first_name_previous>Robbin</first_name_previous>
            <first_name_alt1>Robbin</first_name_alt1>
            <start_date>2017-12-06</start_date>
        </personal_information>
        <employment_information>
            <employment_id>136</employment_id>
            <start_date>2017-12-06</start_date>
            <user_id>10005005</user_id>
            <job_information>
                <action>NO CHANGE</action>
                <end_date>9999-12-31</end_date>
                <entry_into_group>2017-12-06</entry_into_group>
                <event>5</event>
                <event_reason>DATACONV</event_reason>
                <excl_executive_sector>false</excl_executive_sector>
                <fte>1.0</fte>
                <hazard>false</hazard>
                <job_code>1000039</job_code>
                <location>10000069</location>
                <manager_employment_id>265</manager_employment_id>
                <manager_id>10005069</manager_id>
                <manager_person_id>305</manager_person_id>
                <manager_person_id_external>10005069</manager_person_id_external>
                <start_date>2019-03-02</start_date>
            </job_information>
        </employment_information>
    </person>
    <StartDates>
    <StartDate>2021-06-03</StartDate>
    <StartDate>2017-12-06</StartDate>
    <StartDate>2017-12-06</StartDate>
    <StartDate>2019-03-02</StartDate>
    </StartDates>
</CompoundEmployee>

节点有效范围说明

节点类型节点标识生效日期失效日期
CompoundEmployee(简称CE)根节点全局有效全局有效
PersonalInformationCE/PI012021-06-039999-12-31
PersonalInformationCE/PI022017-12-062021-06-02
EmploymentInformationCE/EI012017-12-069999-12-31
Job InformationCE/EI01/JI012019-03-029999-12-31

转换规则

需要按日期范围生成3条记录,规则如下:

生效日期失效日期包含有效节点
2017-12-062019-03-01CE、EI01、PI02
2019-03-022021-06-02CE、EI01、PI02、JI01
2021-06-039999-12-31CE、EI01、PI01、JI01

规则补充说明

  • 收集所有带生效/失效日期的节点(PersonalInfo、JobInfo等),从最早生效日期开始,判断节点在对应时间段是否有效,有效则纳入当期输出
  • 新增下一条记录时,上一条记录的失效日期需调整为下一条记录生效日期减1
  • 根节点CompoundEmployee及其直属字段默认每条记录都包含,有效节点的内部字段保持原样

预期输出示例

<?xml version="1.0" encoding="UTF-8"?>
<Employees>
<CompoundEmployee>
    <StartDate>6-Dec-17</StartDate>
    <EndDate>1-Mar-19</EndDate>
    <employment_information>
        <employment_id>136</employment_id>
        <start_date>2017-12-06</start_date>
        <user_id>10005005</user_id>
    </employment_information>
    <personal_information>
        <end_date>2021-06-02</end_date>
        <first_name>wataru</first_name>
        <first_name_previous>Robbin</first_name_previous>
        <first_name_alt1>Robbin</first_name_alt1>
        <start_date>2017-12-06</start_date>
    </personal_information>
</CompoundEmployee>
<CompoundEmployee>
    <StartDate>2-Mar-19</StartDate>
    <EndDate>2-Jun-21</EndDate>
    <employment_information>
        <employment_id>136</employment_id>
        <start_date>2017-12-06</start_date>
        <user_id>10005005</user_id>
    </employment_information>
    <personal_information>
        <end_date>2021-06-02</end_date>
        <first_name>wataru</first_name>
        <first_name_previous>Robbin</first_name_previous>
        <first_name_alt1>Robbin</first_name_alt1>
        <start_date>2017-12-06</start_date>
    </personal_information>
    <job_information>
        <action>NO CHANGE</action>
        <end_date>9999-12-31</end_date>
        <entry_into_group>2017-12-06</entry_into_group>
        <event>5</event>
        <event_reason>DATACONV</event_reason>
        <excl_executive_sector>false</excl_executive_sector>
        <fte>1.0</fte>
        <hazard>false</hazard>
        <job_code>1000039</job_code>
        <location>10000069</location>
        <manager_employment_id>265</manager_employment_id>
        <manager_id>10005069</manager_id>
        <manager_person_id>305</manager_person_id>
        <manager_person_id_external>10005069</manager_person_id_external>
        <start_date>2019-03-02</start_date>
    </job_information>
</CompoundEmployee>
<CompoundEmployee>
    <StartDate>3-Jun-21</StartDate>
    <EndDate>31-Dec-99</EndDate>
    <employment_information>
        <employment_id>136</employment_id>
        <start_date>2017-12-06</start_date>
        <user_id>10005005</user_id>
    </employment_information>
    <personal_information>
        <end_date>9999-12-31</end_date>
        <first_name>yutaka</first_name>
        <first_name_previous>Robbin</first_name_previous>
        <first_name_alt1>Robbin</first_name_alt1>
        <start_date>2021-06-03</start_date>
    </personal_information>
    <job_information>
        <action>NO CHANGE</action>
        <end_date>9999-12-31</end_date>
        <entry_into_group>2017-12-06</entry_into_group>
        <event>5</event>
        <event_reason>DATACONV</event_reason>
        <excl_executive_sector>false</excl_executive_sector>
        <fte>1.0</fte>
        <hazard>false</hazard>
        <job_code>1000039</job_code>
        <location>10000069</location>
        <manager_employment_id>265</manager_employment_id>
        <manager_id>10005069</manager_id>
        <manager_person_id>305</manager_person_id>
        <manager_person_id_external>10005069</manager_person_id_external>
        <start_date>2019-03-02</start_date>
    </job_information>
</CompoundEmployee>
</Employees>

注:PersonalInfo、EmploymentInfo、JobInfo三类节点出现次数为0到无上限。

现有实现及问题

实现思路

  1. 按节点的生效/失效日期有效性对节点分组
  2. 将上一条记录的end_date调整为下一条记录start_date减1

现有XSLT代码

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />
    
    <xsl:template match="@*|node()">
     <xsl:for-each select="/CompoundEmployee/StartDates/StartDate">
        <Record>
        <xsl:variable name="cDate" select="/CompoundEmployee/StartDates/xs:date(/StartDate)" />
         <xsl:variable name="PIStart" select="/CompoundEmployee/person/personal_information/xs:date(start_date)" />
         <xsl:variable name="PIEnd" select="/CompoundEmployee/person/personal_information/xs:date(end_date)" />
        <xsl:copy-of select="/CompoundEmployee/person/personal_information[$PIStart &lt;= $cDate and $cDate &lt;= PIEnd]"/>
        
        </Record>
    </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

错误输出

<?xml version="1.0" encoding="UTF-8"?>
<Record/>
<Record/>
<Record/>
<Record/>

问题说明

当前代码日期比较逻辑存在问题,未正确筛选出有效节点,需要排查修正。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 17:09:01