XSLT:多次相加并打印小计 [英] XSLT: add up number and print subtotal multiple times
问题描述
我是 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>
</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>#
</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时
字段,sumCount
为 1
.
第二行使用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
, 10
和 11
将被汇总,因为它们具有与当前 summary
字段相同数量的先前 summary
字段.
对于值为 189.5
和 1.5
的 num
字段,
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屋!