如何在 XSL for-each 循环中 XPath sum() 所有以前的节点? [英] How to XPath sum() all previous nodes in a XSL for-each loop?

查看:28
本文介绍了如何在 XSL for-each 循环中 XPath sum() 所有以前的节点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

源 XML(这只是 foobar 数据,实际上它是数千行,可以是正数和负数):

The source XML (this is just foobar data, in reality it is thousands of rows wich can be both positive and negative):

<accounting>
    <entry id="1">
        <accounting_date>2010-10-29</accounting_date>
        <transfer_date>2010-10-29</transfer_date>
        <description>Start balance</description>
        <vat>0</vat>
        <sum>87287</sum>
    </entry>
    <entry id="2">
        <accounting_date>2011-01-24</accounting_date>
        <transfer_date>2011-02-17</transfer_date>
        <description>Bill 1</description>
        <vat>175</vat>
        <sum>875</sum>
    </entry>
    <entry id="3">
        <accounting_date>2011-01-31</accounting_date>
        <transfer_date>2011-01-18</transfer_date>
        <description>Bill 2</description>
        <vat>350</vat>
        <sum>1750</sum>
    </entry>
</accounting>

我想将此 XML 转换为 HTML 表格以显示给用户.大多数转换只是将值放在正确的位置,但平衡字段让我头疼.

I want to transform this XML to an HTML table to display to the user. Most of the transformation is just putting values in the right places, but the balance-field is giving me headache.

我的 XSLT(不起作用):

My XSLT (that does not work):

<table>
    <tr>
        <th>Accounting date</th>
        <th>Description</th>
        <th>Sum</th>
        <th>Balanche</th>
    </tr>
    <xsl:for-each select="/accounting/entry">
        <tr>
            <td><xsl:value-of select="accounting_date" /></td>
            <td><xsl:value-of select="description" /></td>
            <td><xsl:value-of select="sum" /></td>
            <td><xsl:value-of select="sum(../entry[position() &lt; current()/position()]/sum)" /></td><!-- This XPath is the problem! -->
        </tr>
    </xsl:for-each>
</table>

预期结果:

<table>
    <tr>
        <th>Accounting date</th>
        <th>Description</th>
        <th>Sum</th>
        <th>Balanche</th>
    </tr>
    <tr>
        <td>2010-10-29</td>
        <td>Start balance</td>
        <td>87287</td>
        <td>87287</td>
    </tr>
    <tr>
        <td>2011-01-24</td>
        <td>Bill 1</td>
        <td>875</td>
        <td>88162</td>
    </tr>
    <tr>
        <td>2011-01-31</td>
        <td>Bill 2</td>
        <td>1750</td>
        <td>89912</td>
    </tr>
</table>

Chrome 是空白的,而 Firefox 给了我:

Chrome is blank, and Firefox gives me:

Error loading stylesheet: XPath parse failure: Name or Nodetype test expected:

我卡住了,请帮忙.:)

I'm stuck, please help. :)

推荐答案

最佳解决方案可能在一定程度上取决于您使用的是 XSLT 1.0 还是 XSLT 2.0.您真的需要说,因为目前在该领域中使用的两者大致相同.(您似乎是在浏览器中运行它,这表明您想要 1.0 解决方案,所以这就是我给您的).

The best solution might depend a bit on whether you are using XSLT 1.0 or XSLT 2.0. You really need to say, since at present there's a roughly even mix of both in use in the field. (It seems you're running it in the browser, which suggests you want a 1.0 solution, so that's what I've given you).

但无论如何,递归都是你的朋友.在这种情况下,兄弟递归",你编写一个模板来处理一个条目,它确实应用模板来处理下一个条目,将总数作为参数传递:像这样

But either way, recursion is your friend. In this case, "sibling recursion" where you write a template to process an entry, and it does apply-templates to process the next entry, passing the total so far as a parameter: something like this

<xsl:template match="entry">
  <xsl:param name="total-so-far" select="0"/>
         <tr>
            <td><xsl:value-of select="accounting_date" /></td>
            <td><xsl:value-of select="description" /></td>
            <td><xsl:value-of select="sum" /></td>
            <td><xsl:value-of select="$total-so-far + sum"/></td><
        </tr>  
    <xsl:apply-templates select="following-sibling::entry[1]">
      <xsl:with-param name="total-so-far" select="$total-so-far + sum"/>
    </xsl:apply-templates>
</xsl:template>

然后你需要用

<xsl:template match="accounting">
 <table>
   <xsl:apply-templates select="entry[1]"/>
 </table>
</xsl:template>

如果有数千行,那么这可能会导致不进行尾调用优化的 XSLT 处理器中的堆栈溢出.我不知道当今浏览器中的 XSLT 处理器是否实现了这种优化.

If there are thousands of rows then this could cause stack overflow in an XSLT processor that doesn't do tail call optimisation. I've no idea whether the XSLT processors in today's browsers implement this optimisation or not.

这篇关于如何在 XSL for-each 循环中 XPath sum() 所有以前的节点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆