我有一个包含工人和金额的XML。在输出中,文件将包含一个工人的行 - 如果他有EX则为一行,如果他有ER则为一行。如果他在xml文件中有amount1,他有EX,如果他有amount2,他有ER。这在我目前的XSLT中运行得非常好。
主要问题是如何在分组后正确获取正确的总行数和所有金额(金额1和金额2)的总和,并应添加到标题中。
这是示例XML:
<Report_Data>
<Report_Entry>
<Worker>
<Name>User1</Name>
<ID>1234</ID>
</Worker>
<amount1>-200</amount1>
<amount2>100</amount2>
</Report_Entry>
<Report_Entry>
<Worker>
<Name>User1</Name>
<ID>1234</ID>
</Worker>
<amount1>100</amount1>
<amount2>-50</amount2>
</Report_Entry>
<Report_Entry>
<Worker>
<Name>User2</Name>
<ID>5678</ID>
</Worker>
<amount1>-20</amount1>
<amount2>100</amount2>
</Report_Entry>
<Report_Entry>
<Worker>
<Name>User1</Name>
<ID>1234</ID>
</Worker>
<amount1>0</amount1>
<amount2>0</amount2>
</Report_Entry>
</Report_Data>
这是我的样本XSLT(我在柜台上工作,但不能正确。尝试了很多,但我最终得到了变量的计数,但它得到所有的行而不是3.我认为它是因为当前组看起来xml上的所有行值...):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
xmlns:saxon="http://saxon.sf.net/" xmlns:ns0="urn:com.foo" extension-element-prefixes="saxon"
version="2.0">
<xsl:output method="text"/>
<xsl:variable name="SumOfAmount1" saxon:assignable="yes"/>
<xsl:variable name="SumOfAmount2" saxon:assignable="yes"/>
<xsl:variable name="countEX" as="xs:string*">
<xsl:for-each-group select="Report_Data/Report_Entry" group-by="Worker/ID">
<saxon:assign name="SumOfAmount1" select="sum(current-group()/Report_Data/Report_Entry/amount1)"/>
<xsl:if test="$SumOfAmount1 >= 0.00">
<xsl:sequence select="current-group()"></xsl:sequence>
</xsl:if>
</xsl:for-each-group>
</xsl:variable>
<xsl:variable name="countER" as="xs:string*">
<xsl:for-each-group select="/Report_Data/wd:Report_Entry" group-by="ID">
<saxon:assign name="SumOfAmount1" select="sum(current-group()/Report_Data/Report_Entry/amount2)"/>
<xsl:if test="$SumOfAmount1 >= 0.00">
<xsl:sequence select="current-group()"></xsl:sequence>
</xsl:if>
</xsl:for-each-group>
</xsl:variable>
<xsl:template match="node() | @*">
<xsl:copy>
<xsl:apply-templates select="node() | @*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Report_Data">
<Header>
<!--Total count of rows!-->
//add countER and countEX
<xsl:text>,</xsl:text>
<!--Sum of amount1 and amount2 !-->
//add total amounts
</Header>
<ReportData>
<xsl:for-each-group select="Report_Entry" group-by="Worker/ID">
<ReportEntry>
<xsl:copy-of select="current-group()[1]/*[starts-with(name(), 'ID')]"/>
</ReportEntry>
<saxon:assign name="SumOfAmount1" select="sum(current-group()/amount1)"/>
<saxon:assign name="SumOfAmount2" select="sum(current-group()/amount2)"/>
<xsl:if test="$SumOfAmount1 >= 0.00">
<xsl:call-template name="EX"></xsl:call-template>
</xsl:if>
<xsl:if test="$SumOfAmount2 >= 0.00">
<xsl:call-template name="ER"></xsl:call-template>
</xsl:if>
</xsl:for-each-group>
</ReportData>
</xsl:template>
<xsl:template name="EX">
<Name>
<xsl:value-of select="Worker/Name"/>
</Name>
<xsl:text>,</xsl:text>
<ID>
<xsl:value-of select="Worker/ID"/>
</ID>
<xsl:text>,</xsl:text>
<amount1>
<xsl:value-of select="$SumOfAmount1"/>
</amount1>
<xsl:text>,</xsl:text>
<xsl:value-of select="'EX'"></xsl:value-of>
<xsl:value-of select="'
'"></xsl:value-of>
</xsl:template>
<xsl:template name="ER">
<Name>
<xsl:value-of select="Worker/Name"/>
</Name>
<xsl:text>,</xsl:text>
<ID>
<xsl:value-of select="Worker/ID"/>
</ID>
<xsl:text>,</xsl:text>
<amount1>
<xsl:value-of select="$SumOfAmount2"/>
</amount1>
<xsl:text>,</xsl:text>
<xsl:value-of select="'ER'"></xsl:value-of>
<xsl:value-of select="'
'"></xsl:value-of>
</xsl:template>
</xsl:stylesheet>
预期产出:
2,150
User1,1234,50,ER
User2,5678,100,ER
其中:2是行数,150是所有金额(amount1和amount2)的总和。
P.S。负数不包含在文件中。如果amount1或amount2为负数,则它们仍包含在添加中,但如果总和为负数,则将被排除,不会显示在文件中。
感谢您的帮助。
答案 0 :(得分:2)
我会按ID分组一次,然后根据是否有amount1/amount2
元素存储行数据。为了计算总和,我只需再次选择元素:
<xsl:template match="/">
<xsl:variable name="rows" as="element(row)*">
<xsl:for-each-group select="Report_Data/Report_Entry" group-by="Worker/ID">
<xsl:if test="current-group()/amount1">
<row>
<xsl:value-of select="Worker/Name, current-grouping-key(), sum(current-group()/amount1), 'EX'" separator=","/>
</row>
</xsl:if>
<xsl:if test="current-group()/amount2">
<row>
<xsl:value-of select="Worker/Name, current-grouping-key(), sum(current-group()/amount2), 'ER'" separator=","/>
</row>
</xsl:if>
</xsl:for-each-group>
</xsl:variable>
<xsl:value-of select="count($rows), sum(Report_Data/Report_Entry/*[starts-with(local-name(), 'amount')]), $rows" separator=" "/>
</xsl:template>
http://xsltfiddle.liberty-development.net/bdxtpA
似乎我没有完全正确的格式,请参阅http://xsltfiddle.liberty-development.net/bdxtpA/1了解使用
的更正 <xsl:value-of select="concat(count($rows), ',', sum(Report_Data/Report_Entry/*[starts-with(local-name(), 'amount')])), $rows" separator=" "/>
对于消除总和金额为负数的群体的精细要求,我认为
<xsl:template match="/">
<xsl:variable name="rows" as="element(row)*">
<xsl:for-each-group select="Report_Data/Report_Entry" group-by="Worker/ID">
<xsl:variable name="sum1" select="sum(current-group()/amount1)"/>
<xsl:if test="current-group()/amount1 and $sum1 > 0">
<row sum="{$sum1}">
<xsl:value-of select="Worker/Name, current-grouping-key(), $sum1, 'EX'" separator=","/>
</row>
</xsl:if>
<xsl:variable name="sum2" select="sum(current-group()/amount2)"/>
<xsl:if test="current-group()/amount2 and $sum2 > 0">
<row sum="{$sum2}">
<xsl:value-of select="Worker/Name, current-grouping-key(), $sum2, 'ER'" separator=","/>
</row>
</xsl:if>
</xsl:for-each-group>
</xsl:variable>
<xsl:value-of select="concat(count($rows), ',', sum($rows/@sum)), $rows" separator=" "/>
</xsl:template>