通过检查记录中的2个以上值来对金额求和

时间:2013-02-13 08:56:07

标签: xslt xslt-1.0

来源xml:

<?xml version="1.0" encoding="UTF-8"?>
<Emp>
    <EmpDetail>
        <ProjectDetails>
            <Code>Project</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>PROJ1</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <ProjectDetails>
            <Code>Element</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>ELEM1</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <Period>
            <PeriodNo>1</PeriodNo>
        </Period>
        <AmountDetails>
            <Currency>EUR</Currency>
            <Amount>
                <Value>100.00</Value>
            </Amount>
        </AmountDetails>
    </EmpDetail>
    <EmpDetail>
        <ProjectDetails>
            <Code>Project</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>PROJ1</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <ProjectDetails>
            <Code>Element</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>ELEM1</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <Period>
            <PeriodNo>1</PeriodNo>
        </Period>
        <AmountDetails>
            <Currency>EUR</Currency>
            <Amount>
                <Value>5000</Value>
            </Amount>
        </AmountDetails>
    </EmpDetail>
    <EmpDetail>
        <ProjectDetails>
            <Code>Project</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>PROJ2</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <ProjectDetails>
            <Code>Element</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>ELEM2</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <Period>
            <PeriodNo>2</PeriodNo>
        </Period>
        <AmountDetails>
            <Currency>EUR</Currency>
            <Amount>
                <Value>200.00</Value>
            </Amount>
        </AmountDetails>
    </EmpDetail>
    <EmpDetail>
        <ProjectDetails>
            <Code>Project</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>PROJ2</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <ProjectDetails>
            <Code>Element</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>ELEM2</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <Period>
            <PeriodNo>3</PeriodNo>
        </Period>
        <AmountDetails>
            <Currency>EUR</Currency>
            <Amount>
                <Value>500</Value>
            </Amount>
        </AmountDetails>
    </EmpDetail>
</Emp>

目标xml:

<?xml version="1.0" encoding="UTF-8"?>
<Emp>
    <EmpDetail>
        <ProjectDetails>
            <Code>Project</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>PROJ1</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <ProjectDetails>
            <Code>Element</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>ELEM1</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <Period>
            <PeriodNo>1</PeriodNo>
        </Period>
        <AmountDetails>
            <Currency>EUR</Currency>
            <Amount>
                <Value>5100.00</Value>
            </Amount>
        </AmountDetails>
    </EmpDetail>
    <EmpDetail>
        <ProjectDetails>
            <Code>Project</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>PROJ2</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <ProjectDetails>
            <Code>Element</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>ELEM2</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <Period>
            <PeriodNo>2</PeriodNo>
        </Period>
        <AmountDetails>
            <Currency>EUR</Currency>
            <Amount>
                <Value>200.00</Value>
            </Amount>
        </AmountDetails>
    </EmpDetail>
    <EmpDetail>
        <ProjectDetails>
            <Code>Project</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>PROJ2</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <ProjectDetails>
            <Code>Element</Code>
            <ProjectReference>
                <Reference>
                    <RefCode>ELEM2</RefCode>
                </Reference>
            </ProjectReference>
        </ProjectDetails>
        <Period>
            <PeriodNo>3</PeriodNo>
        </Period>
        <AmountDetails>
            <Currency>EUR</Currency>
            <Amount>
                <Value>500</Value>
            </Amount>
        </AmountDetails>
    </EmpDetail>
</Emp>

查询:如果PeriodNo,Project的RefCode和Element的RefCode相同,那么我必须对金额值求和,并且应该只生成一条记录。在我的源文件中,前两行项目的periodno,项目的refcode和元素的refcode是相同的,所以想要在输出中只获得一条记录,金额值应为(100 + 5000)= 5100。

我知道如果我必须检查一个值并执行lineitem的总和,但在这种情况下,我必须检查每个记录中的3个值,我总结了它。你能告诉我,如何使用xslt继续它。我有XSLT 1.0版本。

1 个答案:

答案 0 :(得分:0)

我不知道你现在是否已找到解决方案,但由于此处没有发布解决方案,我发布的是我的Muenchian Grouping。

我试图用注释解释代码,希望它有所帮助。

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>

    <!-- Copy by default attributes, elements and text -->    
    <xsl:template match="*|@*">
        <xsl:copy><xsl:apply-templates select="node()|@*" /></xsl:copy>
    </xsl:template>


    <!-- Key which is going to allow us to identify each EmpDetail by the
         following id (which is a string): ProjectRefCode-ElementRefCode-PeriodNo

         Using the key function we are going to be able to select the set of
         EmpDetail nodes which have the described structure. So elements with
         the same id (i.e. same ProjectRefCode, ElementRefCode and PeriodNo)
         are going to be matched using: key('detail-key', $id), where $id holds
         the id to be matched. -->
    <xsl:key name="detail-key"
             match="Emp/EmpDetail"
             use="concat(ProjectDetails[Code = 'Project']/ProjectReference/Reference/RefCode, '-',
                         ProjectDetails[Code = 'Element']/ProjectReference/Reference/RefCode, '-',
                         Period/PeriodNo)" />

    <xsl:template match="Emp">

        <!-- Copy the current node and process its children EmpDetail elements -->
        <xsl:copy>
            <!-- We use key('detail-key', $id)[1] where the $id is the concat
                 expression to select one element per group, i.e. we iterate
                 over a set of unique EmpDetail elements -->
            <xsl:apply-templates select="EmpDetail[generate-id(.) = generate-id(key('detail-key',
                                               concat(ProjectDetails[Code = 'Project']/ProjectReference/Reference/RefCode, '-',
                                               ProjectDetails[Code = 'Element']/ProjectReference/Reference/RefCode, '-',
                                               Period/PeriodNo))[1])]" />
        </xsl:copy>
    </xsl:template>

    <!-- When the Value element is found, we perform the sum of all the Value elements
         which are contained in the group matched by the id described above-->
    <xsl:template match="Value">

        <!-- Cache parent node to avoid repeated operations -->
        <xsl:variable name="current-detail"
                      select="../../.." />

        <!-- Generate the id for the current EmpDetail element as described
             above -->
        <xsl:variable name="detail-id"
                      select="concat($current-detail/ProjectDetails[Code = 'Project']/ProjectReference/Reference/RefCode, '-',
                                     $current-detail/ProjectDetails[Code = 'Element']/ProjectReference/Reference/RefCode, '-',
                                     $current-detail/Period/PeriodNo)" />

        <!-- Wrap the sum with the Value element -->
        <xsl:copy>
            <!-- We use the key function to fetch all the EmpDetail elements with the
             same id as the current one and sum them -->
            <xsl:value-of select="sum(key('detail-key', $detail-id)/AmountDetails/Amount/Value)" />
        </xsl:copy>

    </xsl:template>    
</xsl:stylesheet>
相关问题