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