XSLT:映射转换(分组)问题

XSLT: Issue with mapping transformation (grouping)

提问人:Carlos Moraes 提问时间:10/5/2023 最后编辑:Carlos Moraes 更新时间:10/6/2023 访问量:34

问:

这里的任何帮助都是值得赞赏的。

我需要转换上面的输入xml:

<?xml version='1.0' encoding='UTF-8'?>
<root>
    <row>
        <userId>40668825871</userId>
        <JobDescription>ANL CONTR QUALIDADE SR</JobDescription>
        <StartDate>01/01/2023</StartDate>
        <EndDate>01/08/2023</EndDate>
        <EventReason>1000</EventReason>
    </row>
    <row>
        <userId>40668825871</userId>
        <JobDescription>ANL CONTR QUALIDADE SR</JobDescription>
        <Atuacao>Interno</Atuacao>
        <StartDate>01/09/2023</StartDate>
        <EndDate>01/31/2023</EndDate>
        <EventReason>1001</EventReason>     
    </row>
    <row>
        <userId>40668825871</userId>
        <JobDescription>ANL CONTR QUALIDADE SR</JobDescription>
        <StartDate>02/01/2023</StartDate>
        <EndDate>02/28/2023</EndDate>
        <EventReason>1003</EventReason>     
    </row>
    <row>
        <userId>40668825871</userId>
        <JobDescription>ANL VALIDACAO SR</JobDescription>
        <StartDate>03/01/2023</StartDate>
        <EndDate>05/05/2023</EndDate>
        <EventReason>9000</EventReason>     
    </row>
    <row>
        <userId>40668825871</userId>
        <JobDescription>ANL VALIDACAO SR</JobDescription>
        <StartDate>05/06/2023</StartDate>
        <EndDate>12/31/2023</EndDate>
        <EventReason>1010</EventReason>     
    </row>
    <row>
        <userId>34916921801</userId>
        <JobDescription>COORD DESENV FARMACOTECNICO</JobDescription>
        <StartDate>08/01/2022</StartDate>
        <EndDate>01/31/2023</EndDate>
        <EventReason>9000</EventReason>     
    </row>
    <row>
        <userId>34916921801</userId>
        <JobDescription>COORD DESENV EMBALAGENS</JobDescription>
        <StartDate>02/01/2023</StartDate>
        <EndDate>02/28/2023</EndDate>
        <EventReason>9002</EventReason>     
    </row>
    <row>
        <userId>34916921801</userId>
        <JobDescription>COORD DESENV EMBALAGENS</JobDescription>
        <StartDate>03/01/2023</StartDate>
        <EndDate>05/05/2023</EndDate>
        <EventReason>1000</EventReason>     
    </row>
    <row>
        <userId>34916921801</userId>
        <JobDescription>COORD DESENV EMBALAGENS</JobDescription>
        <StartDate>05/06/2023</StartDate>
        <EndDate>12/31/2023</EndDate>
        <EventReason>1010</EventReason>     
    </row>
</root>

进入这个:

<?xml version='1.0' encoding='UTF-8'?>
<root>
    <employee>
    <userId>40668825871</userId>
        <job>
            <JobDescription>ANL CONTR QUALIDADE SR</JobDescription>
            <StartDate>01/01/2023</StartDate>
            <EndDate>02/28/2023</EndDate>
        </job>
        <job>
            <JobDescription>ANL VALIDACAO SR</JobDescription>
            <StartDate>03/01/2023</StartDate>
            <EndDate>12/31/2023</EndDate>
        </job>
    </employee> 
    <employee>
    <userId>34916921801</userId>
        <job>
            <JobDescription>COORD DESENV FARMACOTECNICO</JobDescription>
            <StartDate>08/01/2022</StartDate>
            <EndDate>01/31/2023</EndDate>
        </job>
        <job>
            <JobDescription>COORD DESENV EMBALAGENS</JobDescription>
            <StartDate>02/01/2023</StartDate>
            <EndDate>02/28/2023</EndDate>
        </job>
        <job>
            <JobDescription>COORD DESENV EMBALAGENS</JobDescription>
            <StartDate>03/01/2023</StartDate>
            <EndDate>12/31/2023</EndDate>
        </job>
    </employee>     
</root>

输入 XML 它基本上是特定年份的员工工作记录(因此员工可以有一条或多条记录)。

输出 xml 将是记录的分组,规则如下:

1 - 每当员工具有值为 9000 或 9002 的 eventReason 标记时,都必须使用上一条记录的 JobDescription 和 endDate 创建一个新的作业标记。startDate 将是当前员工作业最早的 startDate。

2 - 因此,在生成新的作业标记后,新作业的 startDate 将是事件为 9000 或 9002 的当前记录的 startDate,并且 JobDescription 和 endDate 将填充两种可能性:

2.1 如果存在另一个事件 9000 或 9002,则在记录事件 9000 或 9002 之前,将填充记录的 JobDescription 和 endDate 值;

2.2 如果不存在其他事件 9000 或 9002,则将用员工最后记录的值填充它们。

目前我不知道如何使用 XSLT 执行此操作。

提前致谢。

该方案如上所述。

XSLT XSLT-3.0

评论

0赞 michael.hor257k 10/5/2023
请选择 XSLT 1.0、2.0 或 3.0 之一,而不是全部这三个。
0赞 Carlos Moraes 10/5/2023
嗨,迈克尔,完成了。谢谢。
0赞 michael.hor257k 10/5/2023
不,它还没有完成。我们需要知道您可以使用哪个版本的 XSLT。
0赞 Carlos Moraes 10/5/2023
我可以使用所有这些。1、2 或 3。
0赞 michael.hor257k 10/6/2023
然后将您的问题标记为 XSLT 3.0。

答:

0赞 y.arazim 10/6/2023 #1

我不确定我是否正确阅读了您的解释。您似乎希望按员工对记录进行分组,然后在每个组中创建一个新作业,从具有 EventReason 9000 或 9002 的任何行开始。

假设您至少可以使用 XSLT 2.0,这可以按以下方式完成:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"indent="yes"/>

<xsl:template match="/root">
    <output>
        <!-- group by employee -->
        <xsl:for-each-group select="row" group-by="userId">
            <employee>
                <xsl:copy-of select="userId"/>
                    <!-- break the group at each row with EventReason 9000 or 9002"> -->
                    <xsl:for-each-group select="current-group()" group-starting-with="row[EventReason=('9000', '9002')]">
                        <xsl:variable name="last-row" select="current-group()[last()]" />
                        <job>
                            <xsl:copy-of select="$last-row/JobDescription"/>
                            <xsl:copy-of select="StartDate"/>
                            <xsl:copy-of select="$last-row/EndDate"/>
                        </job>
                </xsl:for-each-group>
            </employee>
        </xsl:for-each-group>
    </output>
</xsl:template>

</xsl:stylesheet>

但是,我得到的结果与您显示的预期结果不同。因此,您的解释或我对它的理解中似乎缺少某些内容。但至少你应该有一个起点。

评论

0赞 Carlos Moraes 10/6/2023
感谢您的回复。让我使用您的 XSLT 执行一些测试,并让您知道是否有效。
0赞 Carlos Moraes 10/6/2023
谢谢Y.Arazim,它工作正常。