【问题标题】:Need to calculate value in each loop and sum together in XSLT 1.0需要在每个循环中计算值并在 XSLT 1.0 中求和
【发布时间】:2012-10-30 22:55:12
【问题描述】:

假设我有一个简单的输入 XML 文档,例如:

<Amounts>
    <item>
        <Base>4750</Base>
        <Tax1>2800</Tax1>
        <Tax2>50</Tax2>
    </item>
    <item>
        <Base>4750</Base>
        <Tax1>2800</Tax1>
        <Tax2>50</Tax2>
    </item>
</Amounts>

XSLT 为:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output  version="1.0" method="xml" omit-xml-declaration="yes" indent="yes"/>
    <xsl:template match="/">
      <xsl:element name="MyTax">
        <xsl:variable name="bf" select="sum(//item/Base)"/>
        <xsl:variable name="discount" select="$bf * 0.08"/>
        <xsl:variable name="bf1" select="$bf - $discount"/>
        <xsl:variable name="yq1" select="sum(//item/Tax1)"/>
        <xsl:variable name="yr1" select="sum(//item/Tax2)"/>
        <xsl:variable name="stax">
            <xsl:value-of select="round(format-number((($bf1 + $yq1 + $yr1) * 0.0495),'#.##'))"/>
        </xsl:variable>
        <xsl:element name="Stax"><xsl:value-of select="$stax"/></xsl:element>
      </xsl:element>
    </xsl:template>
</xsl:stylesheet>

我们得到一个输出 XML:

<MyTax>
    <Stax>715</Stax>
</MyTax>

但是,现在我想为每个项目分别计算 stax,然后将这些项目相加 - 这是因为在上面的示例中,我最终会出现舍入错误,因为单个 stax 的总和实际上是 714 - 值我正在寻找,而不是上面的 715。

所以我正在寻找的输出是:

<MyTax>
         <item>
    <Stax>357</Stax>
         </item>
         <item>
            <Stax>357</Stax>
         </item>
         <TotalStax>714</TotalStax>
</MyTax>

虽然我可以设置一个 for-each,但如何将 stax 计算为每次传递的变量,然后对单个 stax 求和?我受限于 XSLT 1.0,看到了一些使用键和节点集的答案,但无法理解如何应用它们。

【问题讨论】:

  • 您的 XSLT 只对整个输入进行一次 stax 计算。它无法产生您显示的输出。 stax 的计算值为 714.78,您已要求处理器对其进行舍入。这四舍五入为 715。为什么要输出 714?
  • 吉姆,我实际上需要产生 714 的总和 - 只能通过在每次运行中分别计算 stax (357) 并将所有单独的 stax 相加 - 给我 357+357 = 714如果我对单个项目的总和进行计算,则为 715。我无法为此所需的输出创建 XSLT...

标签: xslt sum accumulate


【解决方案1】:

这个 XSLT 1.0 转换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common" exclude-result-prefixes="ext">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
     <xsl:variable name="vrtfTaxSeq">
       <xsl:apply-templates/>
     </xsl:variable>

     <xsl:value-of select="sum(ext:node-set($vrtfTaxSeq)/*)"/>
 </xsl:template>

 <xsl:template match="item">
  <ttax>
   <xsl:value-of select="round(0.0495*(Base - 0.08*Base + Tax1 + Tax2))"/>
  </ttax>
 </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时:

<Amounts>
    <item>
        <Base>4750</Base>
        <Tax1>2800</Tax1>
        <Tax2>50</Tax2>
    </item>
    <item>
        <Base>4750</Base>
        <Tax1>2800</Tax1>
        <Tax2>50</Tax2>
    </item>
</Amounts>

计算每个item 的总和并产生想要的结果:

714

请注意xxx:node-set() 扩展函数是必需的(这可以通过递归来避免)。

【讨论】:

  • 抱歉回复晚了。这确实为上述数据产生了正确的结果,但我很好奇当我需要根据我们对结果计算的要求进行四舍五入然后总结时,你为什么使用 floor(以及它为什么有效?) - 我也需要如果答案产生这样的值,则能够四舍五入。
  • @Surge,没有办法得到714——实际结果是> 714.5
  • 我想要得到的是 round(4750 - 4750*0.08 + 2800 + 50) = round(357.39) = 357 对于上面的每个项目,然后 sum (357, 357) = 714 . 而不是我以前做的 round(0.0495*(8740+5600+100)) = round(714.78) = 715 这对我的应用程序不正确。此外,折扣是一个参数,所以不是 0.08(8% 折扣),我可以得到 12% 的收益 round(0.0495*(4750*0.88+2800+50)) = 348。总和为 348+348 = 696。在您的 xsl 中,该值将变为 695,而我需要 696。如何对每个项目进行四舍五入,然后对每个结果求和?
  • 您需要编辑您的问题并解释这一要求——强迫人们猜测会导致不需要的答案。
  • 对不起,我没有注意到我取消了接受。我试图将其投票为有用。 @Dimitre,您的回答为我提供了解决方案的充分方向,因此肯定会有所帮助。我以为我一开始就已经澄清了我试图通过所需的输出 XML 作为项目的两组 Stax 和最后的 TotalStax,这将是单个 Stax 的简单总和。我提供的示例 XSL 是针对我目前正在做的事情,即添加所有内容,然后计算 round(0.0495*....) ,同时说明我想得到什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多