【问题标题】:How to compare elements in each node and sum values if same in xsl for each loop如果每个循环的 xsl 中相同,如何比较每个节点中的元素和总和值
【发布时间】:2017-08-04 14:24:42
【问题描述】:

我有一个像下面这样的 xml,它有多个节点。我必须遍历每个节点,看看其他节点是否有wd:day_of_week,然后为所有匹配的值添加所有wd:calculated_quatity

例如对于下面的 xml 有两个 wd:day_of_week 值作为 'Monday' ,那么我们需要将这两个关联的 wd:calculated_quantity 添加为 4.75 + 4.08333

XML:

<wd:Time_Blocks_for_Worker>
            <wd:Day_of_the_Week>Monday</wd:Day_of_the_Week>
            <wd:Calendar_Date>2017-07-10-07:00</wd:Calendar_Date>
            <wd:Time_Type wd:Descriptor="Hours Worked">
                <wd:ID wd:type="WID">da128ce5a1dc103f5656dad4dad70868</wd:ID>
                <wd:ID wd:type="Time_Code_Reference_ID">CA Hours Worked In/Out</wd:ID>
            </wd:Time_Type>
            <wd:Calculated_Quantity>4.75</wd:Calculated_Quantity>
        </wd:Time_Blocks_for_Worker>
        <wd:Time_Blocks_for_Worker>
            <wd:Day_of_the_Week>Monday</wd:Day_of_the_Week>
            <wd:Calendar_Date>2017-07-10-07:00</wd:Calendar_Date>
            <wd:Time_Type wd:Descriptor="Hours Worked">
                <wd:ID wd:type="WID">da128ce5a1dc103f5656dad4dad70868</wd:ID>
                <wd:ID wd:type="Time_Code_Reference_ID">CA Hours Worked In/Out</wd:ID>
            </wd:Time_Type>
            <wd:Calculated_Quantity>4.083333</wd:Calculated_Quantity>
        </wd:Time_Blocks_for_Worker>
        <wd:Time_Blocks_for_Worker>
            <wd:Day_of_the_Week>Tuesday</wd:Day_of_the_Week>
            <wd:Calendar_Date>2017-07-11-07:00</wd:Calendar_Date>
            <wd:Time_Type wd:Descriptor="Hours Worked">
                <wd:ID wd:type="WID">da128ce5a1dc103f5656dad4dad70868</wd:ID>
                <wd:ID wd:type="Time_Code_Reference_ID">CA Hours Worked In/Out</wd:ID>
            </wd:Time_Type>
            <wd:Calculated_Quantity>4.75</wd:Calculated_Quantity>
        </wd:Time_Blocks_for_Worker>
        <wd:Time_Blocks_for_Worker>
            <wd:Day_of_the_Week>Tuesday</wd:Day_of_the_Week>
            <wd:Calendar_Date>2017-07-11-07:00</wd:Calendar_Date>
            <wd:Time_Type wd:Descriptor="Hours Worked">
                <wd:ID wd:type="WID">da128ce5a1dc103f5656dad4dad70868</wd:ID>
                <wd:ID wd:type="Time_Code_Reference_ID">CA Hours Worked In/Out</wd:ID>
            </wd:Time_Type>
            <wd:Calculated_Quantity>4.5</wd:Calculated_Quantity>
        </wd:Time_Blocks_for_Worker>

我正在尝试如下的 XSL 循环和比较。

<Calculated_Quantity>
            <xsl:for-each select="wd:Time_Blocks_for_Worker">
            <xsl:choose>
                <xsl:if test="translate(wd:Day_of_the_Week, $smallcase, $uppercase) = wd:Day_of_the_Week">
                <xsl:when test="wd:Day_of_the_Week = wd:Day_of_the_Week">
                <xsl:value-of
                                            select="sum(wd:Time_Blocks_for_Worker/wd:Calculated_Quantity_1 | wd:Time_Blocks_for_Worker/wd:Calculated_Quantity)"/>
                </xsl:when>
             </xsl:choose>
            </xsl:for-each>    
       </Calculated_Quantity>

【问题讨论】:

  • 这是一个分组问题。搜索一下——这可能是这里最常被问到的 XSLT 问题。请注意,XSLT 1.0 或 2.0 的答案是不同的。

标签: xml xslt foreach sum


【解决方案1】:

StackOverflow 上有很多例子,在 XSLT 标签下的 grouping 有详细的解释。根据用于转换的 XSLT 版本,XSLT 1.0 和 XSLT 2.0 的答案不同。

问题中提供的示例 XML 在删除命名空间前缀 wd: 后已用于转换。已生成示例输出以演示 分组 的使用。

XSLT 1.0

必须为分组定义一个&lt;xsl:key&gt;

<xsl:key name="weekday" match="Time_Blocks_for_Worker" use="Day_of_the_Week" />

然后匹配与定义的key相似的模板。

<xsl:template match="Time_Blocks_for_Worker[generate-id() = generate-id(key('weekday', Day_of_the_Week)[1])]">

然后可以根据需要访问和使用匹配元素的子节点。下面是 XSLT,它产生一个计算工作日工作时间总和的示例输出。

<xsl:stylesheet exclude-result-prefixes="xsl"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:key name="weekday" match="Time_Blocks_for_Worker" use="Day_of_the_Week" />
    <xsl:template match="Time_Blocks_for_Worker[generate-id() = generate-id(key('weekday', Day_of_the_Week)[1])]">
        <xsl:variable name="timeBlock" select="key('weekday', Day_of_the_Week)" />
        <WeekDay>
            <Name>
                <xsl:value-of select="$timeBlock/Day_of_the_Week" />
            </Name>
            <Hours>
                <xsl:value-of select="sum($timeBlock/Calculated_Quantity)" />
            </Hours>
        </WeekDay>
    </xsl:template>
    <xsl:template match="Time_Blocks_for_Worker[not(generate-id() = generate-id(key('weekday',Day_of_the_Week)[1]))]" />
</xsl:stylesheet>

此 XSLT 生成下面的示例输出

<WeekDay>
    <Name>Monday</Name>
    <Hours>8.833333</Hours>
</WeekDay>
<WeekDay>
    <Name>Tuesday</Name>
    <Hours>9.25</Hours>
</WeekDay>

XSLT 2.0

XSLT 2.0 通过提供&lt;xsl:for-each-group&gt; 功能为分组提供了一种更简单、更紧凑的解决方案。

<xsl:stylesheet exclude-result-prefixes="xsl"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:template match="/*">
        <xsl:for-each-group select="Time_Blocks_for_Worker" group-by="Day_of_the_Week">
            <WeekDay>
                <Name>
                    <xsl:value-of select="current-grouping-key()" />
                </Name>
                <Hours>
                    <xsl:value-of select="sum(current-group()/Calculated_Quantity)" />
                </Hours>
            </WeekDay>
        </xsl:for-each-group>
    </xsl:template>
</xsl:stylesheet>

此 XSLT 2.0 还产生与 XSLT 1.0 相同的示例输出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-30
    • 1970-01-01
    • 2020-10-03
    • 2014-12-17
    相关资源
    最近更新 更多