是否使用计算的xsl:variables运行Total



我的会计XML包含两个独立的元素,一个仅用于正数,另一个用于负数。我想使用XSL为传入和传出传输创建一个HTML表,再加上每行的运行总计。我找到了sum(preceding-sibling::Buchungszeile/Betrag) + Betrag),如果所有元素都包含一个数字,它就可以正常工作。不幸的是,对于正值,负元素不是0,而是空的,反之亦然。

<Buchungszeile>
<Buchungstag>2019-12-05</Buchungstag>
<Soll-Betrag>100</Soll-Betrag>
<Haben-Betrag></Haben-Betrag>
</Buchungszeile>
<Buchungszeile>
<Buchungstag>2019-12-06</Buchungstag>
<Soll-Betrag></Soll-Betrag>
<Haben-Betrag>155</Haben-Betrag>
</Buchungszeile>
<Buchungszeile>
<Buchungstag>2019-12-07</Buchungstag>
<Soll-Betrag>50</Soll-Betrag>
<Haben-Betrag></Haben-Betrag>
</Buchungszeile>

问题1:在xsl:variable$betrag的帮助下,我只能在一个HTML列中显示所有的money值,负的值带有前导"-&";。但我找不到一种方法来访问Running Totalsum()函数的这个变量。

问题2:我找不到一种方法来生成一个新的XML元素,例如<Betrag>,它包含用于sum(preceding-sibling::Buchungszeile/Betrag) + Betrag)的所有正值和负值

问题3:我找不到使用position()访问前一行值的方法。

哪一种方法才能达到这个结果:

<table>
<tr> <td>Buchungstag</td> <td>Betrag</td> <td>Running Total</td> </tr>
<tr> <td> 2019-12-05</td> <td>  -100</td> <td>         -100</td> </tr>
<tr> <td> 2019-12-06</td> <td>   155</td> <td>           55</td> </tr>
<tr> <td> 2019-12-07</td> <td>   -50</td> <td>            5</td> </tr>
</table>

我建议使用一种完全不同的方法,它不仅可以处理空节点,还可以避免对以前的同级值进行昂贵的重复求和:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/*">
<table>
<tr> 
<th>Buchungstag</th>
<th>Betrag</th>
<th>Running Total</th>
</tr>
<xsl:call-template name="generate-rows">
<xsl:with-param name="nodes" select="Buchungszeile"/>
</xsl:call-template>
</table>
</xsl:template>
<xsl:template name="generate-rows">
<xsl:param name="nodes"/>
<xsl:param name="prev-balance" select="0"/>
<xsl:if test="count($nodes)">
<xsl:variable name="node" select="$nodes[1]"/>
<xsl:variable name="amount" select="concat('0', $node/Haben-Betrag) - concat('0', $node/Soll-Betrag)"/>
<xsl:variable name="balance" select="$prev-balance + $amount"/>
<tr> 
<td>
<xsl:value-of select="$node/Buchungstag"/>
</td>
<td>
<xsl:value-of select="$amount"/>
</td>
<td>
<xsl:value-of select="$balance"/>
</td>
</tr>
<!-- recursive call -->
<xsl:call-template name="generate-rows">
<xsl:with-param name="nodes" select="$nodes[position() > 1]"/>
<xsl:with-param name="prev-balance" select="$balance"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>

在XSLT3中(由Saxon 9.8或更高版本、Saxon JS 2或AltovaXML 2017 R3及更高版本支持(,您可以使用累加器:

<xsl:mode on-no-match="shallow-copy" use-accumulators="total"/>

<xsl:accumulator name="total" as="xs:decimal" initial-value="0">
<xsl:accumulator-rule match="Buchungszeile/Soll-Betrag[. castable as xs:decimal]"
select="$value - xs:decimal(.)"/>
<xsl:accumulator-rule match="Buchungszeile/Haben-Betrag[. castable as xs:decimal]"
select="$value + xs:decimal(.)"/>
</xsl:accumulator>

<xsl:template match="transaktionen">
<table class="buchung">
<thead>
<tr>
<th>Buchungstag</th>
<th>Betrag</th>
<th>Running Total</th>
</tr>
</thead>
<tbody>
<xsl:apply-templates/>
</tbody>
</table>
</xsl:template>

<xsl:template match="Buchungszeile">
<tr>
<td>{Buchungstag}</td>
<td>{if (Soll-Betrag castable as xs:decimal) then -xs:decimal(Soll-Betrag) else xs:decimal(Haben-Betrag)}</td>
<td>{accumulator-after('total')}</td>
</tr>
</xsl:template>

https://xsltfiddle.liberty-development.net/6pS2B6P

最新更新