Apache FOP 中模板输出的总和值

Posted

技术标签:

【中文标题】Apache FOP 中模板输出的总和值【英文标题】:Sum value of output of template in Apache FOP 【发布时间】:2021-01-15 04:03:10 【问题描述】:

我正在使用 Apache FOP 生成 PDF 文档,为了显示某个值,我必须遍历多个节点以确定 total price 值,然后对该值求和。到目前为止,我有一个迭代数组然后检索预期值的函数,但是当我尝试对结果求和时会出现问题。

    <xsl:function name="foo:buildTotalValue">
    <xsl:param name="items" />

    <xsl:variable name="totals">
      <xsl:for-each select="$items/charge">
        <xsl:call-template name="getTotalPriceNode">
          <xsl:with-param name="itemParam" select="." />
        </xsl:call-template>
      </xsl:for-each>
    </xsl:variable>

    <xsl:value-of select="sum(exsl:node-set($totals))" />
    </xsl:function>

    <xsl:template name="getTotalPriceNode">
    <xsl:param name="itemParam" />
      <xsl:choose>
        <xsl:when test="$itemParam/Recurrance = 'OnceOff'">
          <xsl:value-of select="$itemParam/TotalValue" />
        </xsl:when>
        <xsl:when test="$itemParam/Recurrance = 'Monthly'">
          <xsl:value-of select="$itemParam/TotalValue * $itemParam/Months"/>
        </xsl:when>
        <xsl:otherwise><xsl:value-of select="0" /></xsl:otherwise>
      </xsl:choose>
    </xsl:template>

I'm hoping that when I pass in foo:buildTotalValue with entries like this:

    <Charges>
      <Charge>
        <Recurrance>OnceOff</Recurrance>
        <TotalValue>50.00</TotalValue>
      </Charge>
      <Charge>
        <Recurrance>Monthly</Recurrance>
        <TotalValue>10.00</TotalValue>
        <Months>6</Months>
      </Charge>
    </Charges>

将返回值 110.00,但我得到了错误:

Cannot convert string "50.0060.00" to double

我尝试在模板中添加&lt;value&gt; 或其他内容,然后将其用作exsl:node-set 函数的选择器,但似乎没有什么不同。

【问题讨论】:

您使用的是哪个处理器?您已将此标记为 xslt-1.0,但 xsl:function 需要 XSLT 2.0+。 OTOH,XSLT 2.0 处理器不需要exsl:node-set()。所以你有一个大杂烩的版本。同样,对于同一个任务,不需要有一个函数和一个命名模板。 您确定使用 XSLT 1 处理器吗? xsl:function 仅在 XSLT 2 及更高版本中受支持,您只需使用 XPath 2/3 的表达能力,例如sum(Charge[Recurrance = 'OnceOff']/TotalValue | Charge[Recurrance = 'Monthly']/(TotalValue * Months)) 你根本不需要任何迭代或函数。 我的错误,对版本控制感到困惑。 Apache Fop 2.2,它支持 xsl-1.1。对于实际的转换,我们使用的是支持 xslt 3.0 的 Saxon 9.8 【参考方案1】:

AFAICT,您的函数的问题在于它构建了一个由被调用模板返回的串联值字符串,而不是可以转换为节点集并求和的节点树。

尝试改变:

  <xsl:for-each select="$items/charge">
    <xsl:call-template name="getTotalPriceNode">
      <xsl:with-param name="itemParam" select="." />
    </xsl:call-template>
  </xsl:for-each>

到:

  <xsl:for-each select="$items/charge">
    <total>
      <xsl:call-template name="getTotalPriceNode">
        <xsl:with-param name="itemParam" select="." />
      </xsl:call-template>
    </total>
  </xsl:for-each>

和:

<xsl:value-of select="sum(exsl:node-set($totals))" />

到:

<xsl:value-of select="sum(exsl:node-set($totals)/total)" />

未经测试,因为(请参阅对您问题的评论)。

【讨论】:

刚刚尝试过,得到 0 的输出。它几乎就像 被从结果中剥离出来 正如我所说,我还没有测试过这个。我认为没有什么意义,因为这不是一个好方法,无论是在 XSLT 1.0 还是在 XSLT 2.0+ 中。【参考方案2】:

我最终使用了评论中 Martin 的建议 - xpath 2+ 表达式:

sum(Charge[Recurrance = 'OnceOff']/TotalValue | Charge[Recurrance = 'Monthly']/(TotalValue * Months))

它能够在不使用函数/模板/节点集的情况下实现我所需要的(并且代码更少)

【讨论】:

以上是关于Apache FOP 中模板输出的总和值的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Freemarker 和 Apache FOP 将项目列表呈现为 4 个块?

fo:external-graphic 模板文件中带有参数

如何从用户在 django 基本模板中创建的所有帖子中获取模型字段值的总和?

x-easypdf 基于pdfbox/fop 封装的框架

XSL 字体问题 - FOP

如何在 Apache FOP 中设置默认语言