在XSLT 2.0中对变量进行分组

时间:2017-02-15 04:22:52

标签: xslt xslt-2.0 xslt-grouping

对于具有相同<LineDetail>值的每个<CtryCd>节点,并使用<LineDetail>的总和填充1 <Amt>。 但是,我还需要检查<SI><TI>节点。求和的输出标记将基于<SI><TI> 节点。如果<Amt1><SI>的值均为false,则会生成<TI>,如果<Amt2>的值为true,则生成<SI> <TI>是假的。 我创建了一个XSLT并且已经得到了总结。但是我的输出中仍然缺少一些东西。

这是一个示例XML:

<Record>
<Data>
    <Process>
        <Header>
            <ID>22-BBB</ID>
            <Date>2017-02-14</Date>
            <ContactName>Abegail</ContactName>
            <!-- some other elements -->
        </Header>
        <Detail>
            <ID>22-CCC</ID>
            <RequestedDate>2017-02-14</RequestedDate>
            <!-- some other elements -->
            <LineDetail>
                <CtryCd>AF</CtryCd>
                <SI>false</SI>
                <TI>false</TI>
                <Amt>11.11</Amt>
            </LineDetail>
            <LineDetail>
                <CtryCd>SE</CtryCd>
                <SI>true</SI>
                <TI>false</TI>
                <Amt>22.22</Amt>
            </LineDetail>
            <LineDetail>
                <CtryCd>AF</CtryCd>
                <SI>false</SI>
                <TI>false</TI>
                <Amt>33.33</Amt>
            </LineDetail>
            <LineDetail>
                <CtryCd>AF</CtryCd>
                <SI>true</SI>
                <TI>false</TI>
                <Amt>55.55</Amt>
            </LineDetail>       
        </Detail>
    </Process>
</Data>
</Record>

生成输出:

<Record>
<Data>
    <Process>
        <Header>
            <ID>22-BBB</ID>
            <Date>2017-02-14</Date>
            <ContactName>Abegail</ContactName>
            <!-- some other elements -->
        </Header>
        <Detail>
            <LineDetail>
                <CtryCd>AF</CtryCd>
                <Amt1>99.99</Amt1>
            </LineDetail>
        </Detail>
        <Detail>
            <LineDetail>
                <C<Amt2>22.22</Amt2>
            </LineDetail>
        </Detail>
    </Process>
</Data>
</Record>

预期输出:

<Record>
<Data>
    <Process>
        <Header>
            <ID>22-BBB</ID>
            <Date>2017-02-14</Date>
            <ContactName>Abegail</ContactName>
            <!-- some other elements -->
        </Header>
        <Detail>
            <ID>22-CCC</ID>
            <RequestedDate>2017-02-14</RequestedDate>
            <!-- some other elements -->
            <LineDetail>
                <CtryCd>AF</CtryCd>
                <Amt1>44.44</<Amt1>
                <Amt2>55.55</Amt2>
            </LineDetail>
            <LineDetail>
                <CtryCd>SE</CtryCd>
                <Amt1>0</<Amt1>
                <Amt2>22.22</Amt2>
            </LineDetail>           
        </Detail>
    </Process>
</Data>
</Record>

XSLT:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="CtryCd" match="LineDetail" use="CtryCd"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
<xsl:template match="Detail">
    <xsl:for-each-group select="LineDetail" group-by="CtryCd">
        <Detail>
            <LineDetail>
                <CtryCd>
                    <xsl:value-of select="CtryCd"/>
                </CtryCd>
                <xsl:if test="lower-case(SI)='false' and lower-case(TI)='false'">
                    <Amt1>
                        <xsl:value-of select="sum(current-group()/Amt)"/>
                    </Amt1>
                <xsl:if test="lower-case(SI)='true' and lower-case(TI)='false'">
                    <Amt2>
                        <xsl:value-of select="sum(current-group()/Amt)"/>
                    </Amt2>
                </xsl:if>
                </xsl:if>
                <xsl:if test="lower-case(SI)='true' and lower-case(TI)='false'">
                    <Amt2>
                        <xsl:value-of select="sum(current-group()/Amt)"/>
                    </Amt2>
                </xsl:if>
            </LineDetail>
        </Detail>
    </xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

你当前条件只会检查组中的第一项。你真的需要它作为实际sum语句的一部分,作为组中每个节点的一个条件。

<Amt1>
    <xsl:value-of select="sum(current-group()[lower-case(SI)='false' and lower-case(TI)='false']/Amt)"/>
</Amt1>

然后你会对Amt2有一个类似的声明,测试“true”和“false”

试试这个XSLT

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

<xsl:key name="CtryCd" match="LineDetail" use="CtryCd"/>

<!-- identity transform -->
<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Detail">
    <xsl:for-each-group select="LineDetail" group-by="CtryCd">
        <Detail>
            <LineDetail>
                <CtryCd>
                    <xsl:value-of select="CtryCd"/>
                </CtryCd>
                <Amt1>
                    <xsl:value-of select="sum(current-group()[lower-case(SI)='false' and lower-case(TI)='false']/Amt)"/>
                </Amt1>
                <Amt2>
                    <xsl:value-of select="sum(current-group()[lower-case(SI)='true' and lower-case(TI)='false']/Amt)"/>
                </Amt2>
            </LineDetail>
        </Detail>
    </xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>