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



源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。

我知道是否必须检查一个值并对行项目求和,但在这种情况下,我必须检查每个记录中的3个值,并对其求和。你能告诉我如何使用xslt进行操作吗。我有XSLT1.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>

最新更新