XSLT:多次相加并打印小计 [英] XSLT: add up number and print subtotal multiple times

查看:32
本文介绍了XSLT:多次相加并打印小计的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 XSLT 的初学者,并发现我不能只是将数字与变量相加并以任何方式更改其值.

I'm a beginner in XSLT and figured out that I cannot just add up numbers to a variable and change its value in any way.

我有一个 XML 文档,其中包含一个数字列表,我需要将这些数字相加,直到元素与特定属性值匹配,然后打印该数字将其重置为 0,然后继续将其余数字相加,直到我再次看到该特定属性.

I have a XML document with a list of numbers i need to add up until the element matches a specific attribute value, then print that number reset it to 0 and continue adding up the rest until i see that specific attribute again.

例如我有这个 XML:

For example i have this XML:

<list>
 <entry>
  <field type="num" value="189.5" />
 </entry>
 <entry>
  <field type="num" value="1.5" />
 </entry>
 <entry>
  <field type="summary" />
 </entry>
 <entry>
  <field type="num" value="9.5" />
 </entry>
 <entry>
  <field type="num" value="11" />
 </entry>
 <entry>
  <field type="num" value="10" />
 </entry>
 <entry>
  <field type="summary" />
 </entry>
</list>

现在我想让我的 XSLT 打印这个:

Now i want my XSLT to print this:

189.5
1.5
#191#
9.5
11
10
#30.5#

我已经读到我可以通过使用 sum() 和条件来做到这一点.我知道如何使用 for-each 并相对地指向元素,我也可以通过简单地总结所有具有 type=num 的元素来使用 sum(),但是如何只对第一个 num 求和,直到出现 type=summary,然后才求和从上一个 type=summary 到下一个?

I have read that i can do that by using sum() with conditions. I know how to use for-each and point to the elements relatively and iam also able to use sum() by simply summarizing all having type=num, but how to sum only first num until type=summary comes up, then next sum only from last type=summary until the next one?

我希望是这样的:

<xsl:for-each select="list/entry">
 <xsl:if test="field[@type='summary']">
  <!-- we are now at a type=summary element, now sum up -->
  #<xsl:value-of select="sum(WHAT_TO_PUT_HERE?)" />#
 </xsl:if>
 <xsl:if test="field[@type='num']">
  <xsl:value-of select="field/@value" />
 </xsl:if>
</xsl:for-each>

感谢任何帮助.

推荐答案

就像注释中建议的分组的不同解决方案 - 您也可以使用匹配模式来获取总和:

Just as a different solution to the grouping suggested as comment - you could also use match patterns to get the sums:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="field[@type='num']">
  <xsl:value-of select="@value"/>
<xsl:text>&#x0A;</xsl:text>
  </xsl:template>
  <xsl:template match="entry[field[@type='summary']]">
  <xsl:variable name="sumCount" select="count(preceding-sibling::entry[field[@type='summary']])"/>
     <xsl:text>#</xsl:text>
     <xsl:value-of select="sum(preceding-sibling::entry[count(preceding-sibling::entry[field[@type='summary']]) = $sumCount]/field[@type='num']/@value)"/>
    <xsl:text>#&#x0A;</xsl:text>     
  </xsl:template>
</xsl:transform>

当应用于您的输入 XML 时,这会产生输出

When applied to your input XML this produces the output

189.5
1.5
#191#
9.5
11
10
#30.5#

模板匹配 field[@type='num'] 打印值并添加换行符,模板匹配 entry[field[@type='summary']] 使用变量

The template matching field[@type='num'] prints the value and adds a newline, and the template matching entry[field[@type='summary']] uses the variable

<xsl:variable name="sumCount" select="count(preceding-sibling::entry[field[@type='summary']])"/>

检查出现了多少个 summary 类型的先前字段.然后只打印 num 类型的条目的所有值的总和,前面的 summary 字段数量相同:

to check how many previous fields of the type summary occured. Then only the sum of all values of entries of the type num with the same amount of preceding summary fields is printed:

<xsl:value-of select="sum(preceding-sibling::entry[
                      count(preceding-sibling::entry[field[@type='summary']]) = $sumCount
                      ]/field[@type='num']/@value)"/>

更新:要更详细地解释它是如何按要求工作的:在模板中匹配 entry[field[@type='summary']] 变量 sumCount 计算所有具有 summary 类型字段的先前条目:

Update: To explain in more detail how this works as requested: In the template matching entry[field[@type='summary']] the variable sumCount counts all previous entries that have a field of type summary:

count(preceding-sibling::entry[field[@type='summary']])

所以当模板匹配第一个summary字段时,sumCount的值为0,当匹配第二个summary时 字段,sumCount1.
第二行使用sum函数

So when the template matches the first summary field, the value of sumCount is 0, and when matching the second summary field, sumCount is 1.
The second line using the sum function

sum(
    preceding-sibling::entry
     [
      count(preceding-sibling::entry[field[@type='summary']]) = 
      $sumCount
     ]
     /field[@type='num']/@value
   )

对所有具有相同数量的先前 summary 类型字段的先前(前面)条目的所有 field[@type='num']/@value 求和summary 类型的 current 字段:

sums all field[@type='num']/@value for all previous (preceding) entries that have the same amount of previous fields of type summary as the current field of type summary:

count(preceding-sibling::entry[field[@type='summary']]) = $sumCount

所以当第二个 summary 匹配时,只有 num 字段的值具有 9.5, 1011 将被汇总,因为它们具有与当前 summary 字段相同数量的先前 summary 字段.
对于值为 189.51.5num 字段,

So when the second summary is matched, only the values of the num fields with the values 9.5, 10 and 11 will be summarized as they have the same amount of previous summary fields as the current summary field.
For the num fields with the values 189.5 and 1.5,

count(preceding-sibling::entry[field[@type='summary']]) 

0,所以这些字段在sum函数中被省略了.

is 0, so these fields are omitted in the sum function.

这篇关于XSLT:多次相加并打印小计的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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