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

时间:2018-01-10 20:30:13

标签: xml xslt xml-parsing xslt-1.0 xslt-grouping

当我尝试通过应用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>

期望输出的解释

这背后的逻辑如果&#34; e&#34;和&#34; j&#34;是相同的,然后顶行携带每个属性,但第二个记录只包含&#34; in&#34;和&#34; out&#34;其他属性在记录中显示&#34; 0&#34;(零)  喜欢: 第一条记录已经完成,它有&#34; e&#34;&#34; j&#34;,&#34;提示&#34;,&#34;销售&#34;,&#34;&#34;&#34; ;,&#34;列&#34;所有属性:

 <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 =&#34;&#34;只有&#34; e&#34;,&#34; j&#34;,&#34;&#34;,&#34; out&#34; &#34;提示&#34; 0和0(零)和&#34;销售&#34;喜欢:

<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中进行一些更改,它可以实现,但我的逻辑不起作用,我不能这样做。

请看一下!

谢谢!

1 个答案:

答案 0 :(得分:0)

您共享的XSLT包含对示例XML中未包含的元素的一些额外处理,因此不是修改共享XSLT,下面的解决方案中包含了一个新的XSLT,以便了解所需的内容分组可以实现。

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

<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>