XSLT - 使用round()函数

时间:2016-07-15 03:54:36

标签: xml xslt xslt-2.0

我有像这样的xml,

<doc>
    <p>20</p>
    <p>20</p>
    <p>20</p>
    <p>100</p>
    <t>160</t>
</doc>

有4个<p>元素包含数字,<t>代表上述4个<p>元素的总和。

我的目标是计算这些<p>元素的百分比并显示。

这是为我编写的xsl代码,

    <xsl:variable name="val1" select="abc:get-int-value(doc/p[1]/text())" as="xs:double"/>
    <xsl:variable name="val2" select="abc:get-int-value(doc/p[2]/text())" as="xs:double"/>
    <xsl:variable name="val3" select="abc:get-int-value(doc/p[3]/text())" as="xs:double"/>
    <xsl:variable name="val4" select="abc:get-int-value(doc/p[4]/text())" as="xs:double"/>
    <xsl:variable name="valTotal" select="abc:get-int-value(doc/t/text())" as="xs:double"/>

    <xsl:variable name="precentage1" select="round(($val1 div $valTotal)*100)" as="xs:double"/>
    <xsl:variable name="precentage2" select="round(($val2 div $valTotal)*100)" as="xs:double"/>
    <xsl:variable name="precentage3" select="round(($val3 div $valTotal)*100)" as="xs:double"/>
    <xsl:variable name="precentage4" select="round(($val4 div $valTotal)*100)" as="xs:double"/>

    <xsl:template match="doc">
        <xsl:value-of select="$precentage1"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="$precentage2"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="$precentage3"/>
        <xsl:text> </xsl:text>
        <xsl:value-of select="$precentage4"/>
    </xsl:template>

    <xsl:function name="abc:get-int-value" as="xs:double">
        <xsl:param name="text" as="xs:string"/>

        <xsl:analyze-string select='$text' regex='\d+'>
            <xsl:matching-substring>
                <xsl:sequence select="number(.)"/>
            </xsl:matching-substring>
        </xsl:analyze-string>
    </xsl:function>

但是,它给出的百分比值为13,13,13和63.所以这些数字的总和是102.(字面上它应该是100,99或101)。似乎p [4]的百分比值已经四舍五入到63而不是62。

为什么会发生这种情况,我该如何解决这个问题?

4 个答案:

答案 0 :(得分:1)

  

为什么会这样?

您的预期价值是错误的,甚至没有意义。 20 div 160为12.5,100 div 160为62.5。 12.5轮到13轮,62.5轮到63轮,这些是你看到的值。

舍入固有地产生不精确的值,因此您不能指望四个舍入百分比总是加起来为100。

  

我该如何解决这个问题

我认为您需要决定如何解决这种差异。 round()函数的工作方式正是如此。

答案 1 :(得分:1)

  

我该如何解决这个问题?

正如其他人已经解释过的那样,你无法“解决”这个问题。

但是,您可以使用round-half-to-even()代替round()轻微缓解此问题。碰巧的是,在给定的例子中,它只会将问题转移到另一侧 - 即结果将是12,12,12,62,总共98.但平均而言,舍入误差将更小。

答案 2 :(得分:1)

有关对一组百分比进行舍入的算法的一些讨论,总计加起来为100(但不是特别在XSLT上下文中),请参阅

How to make rounded percentages add up to 100%

答案 3 :(得分:0)

round函数如何工作:它返回一个与参数最接近的整数,这意味着round(62.5) = 63

你可以做的是从100中提取percenatge1,percentage2和percentage3并获得百分比4,因为所有这三个百分比值应该总共给你100%,即:

<xsl:variable name="precentage4" select="100 - $precentage1 - $precentage2 - $precentage3" as="xs:double"/>