通过 xslt 转换 xml 时无法跳过重复项

Unable to skip the duplicates while transform the xml through xslt

当我尝试通过应用 XSLT 解析 XML 文件时,无法在获取不同值时跳过重复值。

这是 XML 文件,其中包含以 XML 格式显示数据的原始值和列

<Poll>
<SQLConnection>
<SQLCommand identifier="TIMEPUNCH">
    <Data>
        <Row sdt="12-03-2017 00:00:00" edt="12-03-2017 00:00:00" e="7" j="630" Expr1004="630" cin="11:07a" cout="1:24p" hrs_ovrday="0" hrs_ovrwk="2.6333" tips="23" sales=256" hrs_holida="0" rh="4.1833" total_pay="113.87"/>
        <Row sdt="12-03-2017 00:00:00" edt="12-03-2017 00:00:00" e="7" j="630" Expr1004="630" cin="6:04a" cout="10:36a" hrs_ovrday="0" hrs_ovrwk="2.6333" tips="0" sales="0" hrs_holida="0" rh="4.1833" total_pay="113.87"/>
        <Row sdt="12-03-2017 00:00:00" edt="12-03-2017 00:00:00" e="71" j="400" Expr1004="400" cin="12:05p" cout="3:18p" hrs_ovrday="0" hrs_ovrwk="0" tips="47.59" sales="357.61" hrs_holida="0" rh="7.5" total_pay="78.75"/>
        <Row sdt="12-03-2017 00:00:00" edt="12-03-2017 00:00:00" e="71" j="500" Expr1004="500" cin="4:07p" cout="8:24p" hrs_ovrday="0" hrs_ovrwk="0" tips="47.59" sales="357.61" hrs_holida="0" rh="7.5" total_pay="78.75"/>
    </Data>
</SQLCommand>
</SQLConnection>
</Poll>

通过在此之上使用此 XSLT,我无法将上述 XML 转换为有意义的数据

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:param name="include-control-elements">true</xsl:param>
    <xsl:key name="RECORDS" match="/Poll/SQLConnection/SQLCommand/Data/Row" use="../../@identifier"/>
    <xsl:key name="TIMEPUNCH" match="/Poll/SQLConnection/SQLCommand[@identifier='TIMEPUNCH']/Data/Row" use="@j"/>
    <xsl:template match="/*">
        <xsl:element name="{name()}">
            <xsl:copy-of select="@*"/>
            <xsl:if test="not($include-control-elements = 'false')">
                <xsl:apply-templates select="HEADER"/>
                <xsl:copy-of select="Location | Environment[*] | Diagnostics"/>
            <xsl:call-template name="LaborGroup"/>
            </xsl:if>
</xsl:element>
</xsl:template>
        <xsl:template name="LaborGroup">
        <xsl:variable name="timepunch" select="key('RECORDS','TIMEPUNCH')"/>
        <xsl:if test="$timepunch">
            <Labor>
                <xsl:if test="$timepunch">
                    <TM0 type="SHIFT">
                        <xsl:apply-templates select="$timepunch" mode="TIMEPUNCH"/>
                    </TM0>
                </xsl:if>
            </Labor>
        </xsl:if>
    </xsl:template>
    <xsl:template match="Row" mode="TIMEPUNCH">
        <TM1>
            <xsl:attribute name="e"><xsl:value-of select="format-number(@e,'0000')"/></xsl:attribute>
            <xsl:apply-templates select="@j|@tips|@sales|@rh" mode="String"/>
            <xsl:variable name="varOvrTimeHr" select="@hrs_ovrday+@hrs_ovrwk+@hrs_holida"/>
            <xsl:variable name="varRegHour" select="concat(substring-before(format-number( (@rh ),'0.00'),'.'),':', format-number((@rh * 60)mod 60,'00'))"/>
            <xsl:variable name="tempVarIn">
                <xsl:if test="count(@e)  &gt; 1">
                    <xsl:value-of select="$e"/>
                </xsl:if>
                <xsl:value-of select="concat(format-number(substring-before(@cin,':'),'00'),':',substring-after(@cin,':'))"/>
            </xsl:variable>
            <xsl:variable name="VarIn">
                <xsl:choose>
                    <xsl:when test="substring(substring-after(current()/@cin,':'),3,1)='a'">
                        <xsl:value-of select="concat(substring-before(@sdt,' '),' ', substring-before($tempVarIn,'a'),':00',' ','AM')"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="concat(substring-before(@sdt,' '),' ',substring-before($tempVarIn,'p'),':00',' ','PM')"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:variable name="tempVarOut">
                <xsl:value-of select="concat(format-number(substring-before(@cout,':'),'00'),':',substring-after(@cout,':'))"/>
            </xsl:variable>
            <xsl:variable name="VarOut">
                <xsl:choose>
                    <xsl:when test="substring(substring-after(current()/@cout,':'),3,1)='a'">
                        <xsl:value-of select="concat(substring-before(@edt,' '),' ',substring-before($tempVarOut,'a'),':00',' ','AM')"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="concat(substring-before(@edt,' '),' ',substring-before($tempVarOut,'p'),':00',' ','PM')"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:variable>
            <xsl:attribute name="pay"><xsl:value-of select="@total_pay"/></xsl:attribute>
            <xsl:attribute name="in"><xsl:value-of select="$VarIn"/></xsl:attribute>
            <xsl:attribute name="out"><xsl:value-of select="$VarOut"/></xsl:attribute>
            <xsl:attribute name="pay"><xsl:value-of select="@total_pay"/></xsl:attribute>
        </TM1>
    </xsl:template>
    <xsl:template match="Row" mode="TM1">
        <xsl:apply-templates select="@e" mode="EMPLOYEE_ID"/>
        <xsl:apply-templates select="@j | @r | @rh | @rp | @otr | @ot | @op | @wkh | @pay" mode="Number"/>
    </xsl:template>
    <xsl:template match="@*" mode="String">
        <xsl:param name="name" select="name(.)"/>
        <xsl:param name="value" select="normalize-space(.)"/>
        <xsl:if test="$value">
            <xsl:attribute name="{$name}"><xsl:value-of select="$value"/></xsl:attribute>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

输出为

<Poll>
    <Labor>
        <TM0 type="SHIFT">
            <TM1 e="0007" j="630" tips="23" sales="256" rh="4.1833" in="12-03-2017 11:07:00 AM" out="12-03-2017 01:24:00 PM" pay="113.87"/>
            <TM1 e="0007" j="630" tips="0" sales="0" rh="4.1833" in="12-03-2017 06:04:00 AM" out="12-03-2017 10:36:00 AM" pay="113.87"/>
            <TM1 e="0071" j="400" tips="47.59" sales="357.61" rh="7.5" in="12-03-2017 12:05:00 PM" out="12-03-2017 03:18:00 PM" pay="78.75"/>
            <TM1 e="0071" j="500" tips="47.59" sales="357.61" rh="7.5" in="12-03-2017 04:07:00 PM" out="12-03-2017 08:24:00 PM" pay="78.75"/>
        </TM0>
    </Labor>
</Poll>

现在我只想通过修改 XSLT 得到这样的输出,但无法获得所需的结果

<Poll>
    <Labor>
        <TM0 type="SHIFT">
        <TM1 e="0007" j="630" tips="23" sales="256" in="12-03-2017 11:07:00 AM" out="12-03-2017 01:24:00 PM"/>
        <TM1 e="0007" j="630" tips="0" sales="0" in="12-03-2017 06:04:00 AM" out="12-03-2017 10:36:00 AM" />
        <TM1 e="0071" j="500" tips="47.59" sales="357.61" in="12-03-2017 04:07:00 PM" out="12-03-2017 08:24:00 PM"/>
        <TM1 e="0071" j="400" tips="0" sales="0" in="12-03-2017 12:05:00 PM" out="12-03-2017 03:18:00 PM" />
        </TM0>
    </Labor>
</Poll>

所需输出的解释

如果 "e" 和 "j" 相同,那么顶行包含每个属性,但第二个记录仅包含 "in" 和 "out" 时间else 属性在记录中显示“0”(零) 像: 第一条记录完成它有"e","j","tips","sales","in","out"所有属性:

 <TM1 e="0007" j="630" tips="23" sales="256" in="12-03-2017 11:07:00 AM" out="12-03-2017 01:24:00 PM"/>

但是同一个 e="0007" 的第二条记录只有 "e"、"j"、"in"、"out" 和 0(零)的值"tips" 和 "sales" 喜欢 :

<TM1 e="0007" j="630" tips="0" sales="0" in="12-03-2017 06:04:00 AM" out="12-03-2017 10:36:00 AM" />

通过在 XSLT 中进行一些更改它可以实现,但我的逻辑不起作用,我无法这样做。

请看一下!

谢谢!

您共享的 XSLT 包含对示例中未包含的元素的一些额外处理 XML 因此,下面的解决方案中包含了一个新的 XSLT,而不是修改共享的 XSLT,以提供关于如何实现所需分组的想法。

您可以使用 <Row> 元素的 @e@j 属性创建复合键。

<xsl:key name="ej-key" match="Row" use="concat(@e,'|', @j)" />

使用此键,将<Row>generate-id()函数匹配,即可实现所需的分组。

<xsl:template match="Row[generate-id() = generate-id(key('ej-key', concat(@e,'|',@j))[1])]">

下面是 XSLT。 XSLT 不包含计算 @in@out 属性值的逻辑。您可以在模板中添加该逻辑。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" />
    <xsl:strip-space elements="*" />

    <xsl:key name="ej-key" match="Row" use="concat(@e,'|', @j)" />

    <xsl:template match="Poll">
        <xsl:copy>
            <Labor>
                <xsl:apply-templates />
            </Labor>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Data">
        <xsl:element name="TM0">
            <xsl:attribute name="type">
                <xsl:value-of select="'SHIFT'" />
            </xsl:attribute>
            <xsl:apply-templates />
        </xsl:element>
    </xsl:template>

    <xsl:template match="Row[generate-id() = generate-id(key('ej-key', concat(@e,'|',@j))[1])]">
        <xsl:variable name="varKey" select="key('ej-key', concat(@e,'|', @j))" />
        <xsl:element name="TM1">
            <xsl:attribute name="e">
                <xsl:value-of select="format-number($varKey/@e, '0000')" />
            </xsl:attribute>
            <xsl:attribute name="j">
                <xsl:value-of select="$varKey/@j" />
            </xsl:attribute>
            <xsl:attribute name="tips">
                <xsl:value-of select="$varKey/@tips" />
            </xsl:attribute>
            <xsl:attribute name="sales">
                <xsl:value-of select="$varKey/@sales" />
            </xsl:attribute>
            <xsl:attribute name="rh">
                <xsl:value-of select="$varKey/@rh" />
            </xsl:attribute>
        </xsl:element>
    </xsl:template>

    <xsl:template match="Row" />
</xsl:stylesheet>

输出

<Poll>
    <Labor>
        <TM0 type="SHIFT">
            <TM1 e="0007" j="630" tips="0" sales="0" rh="4.1833" />
            <TM1 e="0071" j="400" tips="47.59" sales="357.61" rh="7.5" />
            <TM1 e="0071" j="500" tips="47.59" sales="357.61" rh="7.5" />
        </TM0>
    </Labor>
</Poll>