在Xpath / XSLT中,xs:double转换为xs:decimal,自定义vs内置?

时间:2015-01-29 15:53:12

标签: xml xslt xpath saxon

我过去没有处理敏感数字,所以想检查一下。 我有输入,表示为xs:double:

<do:amount>1.60</do:amount>

XSL / XPath的:

<dec:amount><xsl:value-of select="xs:decimal(do:amount)"/></dec:amount>

,输出应为:

<dec:amount>1.60</dec:amount>

编写一个可以处理的自定义函数是否有任何好处:将金额作为文本,用点字符分割,然后将其转换为十进制? 是否有任何我应该注意的场景,投射或计算可能不精确?

1 个答案:

答案 0 :(得分:2)

似乎将xs:double转换为xs:decimal很容易导致浮点后有大量数字的数字,例如当我评估时

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  exclude-result-prefixes="xs" default-validation="lax">

<xsl:output indent="yes"/>

<xsl:import-schema>
  <xs:schema>
    <xs:element name="double-amount" type="xs:double"/>
    <xs:element name="dec-amount" type="xs:decimal"/>
  </xs:schema>
</xsl:import-schema>

<xsl:template match="/" name="main">
  <xsl:variable name="doubles" as="element(double-amount)*">
    <xsl:for-each select="1 to 10">
      <double-amount>
        <xsl:value-of select="1E0 + 1E-1 * ."/>
      </double-amount>
    </xsl:for-each>
  </xsl:variable>
  <xsl:copy-of select="$doubles"/>
  <xsl:apply-templates select="$doubles"/>
  <xsl:apply-templates select="$doubles" mode="cast"/>
</xsl:template>

<xsl:template match="double-amount">
  <dec-amount>
    <xsl:value-of select="."/>
  </dec-amount>
</xsl:template>

<xsl:template match="double-amount" mode="cast">
  <dec-amount>
    <xsl:value-of select="xs:decimal(.)"/>
  </dec-amount>
</xsl:template>

</xsl:stylesheet>

使用Saxon 9.6 EE或使用Saxon 9.5 EE(参见http://xsltransform.net/gWmuiJj),结果是

<double-amount>1.1</double-amount>
<double-amount>1.2</double-amount>
<double-amount>1.3</double-amount>
<double-amount>1.4</double-amount>
<double-amount>1.5</double-amount>
<double-amount>1.6</double-amount>
<double-amount>1.7000000000000002</double-amount>
<double-amount>1.8</double-amount>
<double-amount>1.9</double-amount>
<double-amount>2</double-amount>
<dec-amount>1.1</dec-amount>
<dec-amount>1.2</dec-amount>
<dec-amount>1.3</dec-amount>
<dec-amount>1.4</dec-amount>
<dec-amount>1.5</dec-amount>
<dec-amount>1.6</dec-amount>
<dec-amount>1.7000000000000002</dec-amount>
<dec-amount>1.8</dec-amount>
<dec-amount>1.9</dec-amount>
<dec-amount>2</dec-amount>
<dec-amount>1.100000000000000088817841970012523233890533447265625</dec-amount>
<dec-amount>1.1999999999999999555910790149937383830547332763671875</dec-amount>
<dec-amount>1.3000000000000000444089209850062616169452667236328125</dec-amount>
<dec-amount>1.399999999999999911182158029987476766109466552734375</dec-amount>
<dec-amount>1.5</dec-amount>
<dec-amount>1.600000000000000088817841970012523233890533447265625</dec-amount>
<dec-amount>1.70000000000000017763568394002504646778106689453125</dec-amount>
<dec-amount>1.8000000000000000444089209850062616169452667236328125</dec-amount>
<dec-amount>1.899999999999999911182158029987476766109466552734375</dec-amount>
<dec-amount>2</dec-amount>

表明在xs:decimal(.)中执行.而不是简单xsl:value-of会导致浮点后面有大量数字的数字,这可能是xs:decimal的精确xs:double表示原始xs:decimal(.)但可能不是您要存储的值。所以我想知道你是否通过{{1}}获得任何东西,而不是简单地复制价值。