如何比较每个节点中的元素,并在xsl中为每个循环求和值

时间:2017-08-04 14:24:43

标签: xml xslt foreach sum

我有一个像下面这样的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>

1 个答案:

答案 0 :(得分:0)

在StackOverflow上的XSLT标记下有很多关于分组的详细说明的示例。基于用于转换的XSLT版本,XSLT 1.0和XSLT 2.0的答案是不同的。

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

XSLT 1.0

必须为分组

定义<xsl:key>
<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])]">

然后可以根据需要访问和使用匹配元素的子节点。下面是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通过提供<xsl:for-each-group>功能为分组提供了一种更简单,更紧凑的解决方案。

<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相同的示例输出。