XSLT 大整数 (int64) 处理 msxml

发布于 2024-08-26 13:21:34 字数 5476 浏览 8 评论 0原文

当尝试在 xslt 模板中对大整数 (int64) 进行数学运算时,我得到了错误的结果,因为 xslt 中没有本机 64 位整数支持(xslt 数字是 64 位双精度)。我在 Windows XP SP3 上使用 msxml 6.0。 Windows 上有解决这个问题的方法吗?

<tables>
  <table>
    <table_schem>REPADMIN</table_schem>
    <table_name>TEST_DESCEND_IDENTITY_BIGINT</table_name>
    <column>
      <col_name>COL1</col_name>
      <identity>
        <col_min_val>9223372036854775805</col_min_val>
        <col_max_val>9223372036854775805</col_max_val>
        <autoincrementvalue>9223372036854775807</autoincrementvalue>
        <autoincrementstart>9223372036854775807</autoincrementstart>
        <autoincrementinc>-1</autoincrementinc>
      </identity>
    </column>
  </table>
</tables>

由于 64 位双精度数中大整数的不精确表示(我假设),此测试返回 true,但如果我可以以某种方式告诉 xslt 处理器使用 int64 而不是默认的 64 位双精度数数据,则实际上返回 false因为大整数是 xml 输入中数字的实际数据类型。

          <xsl:when test="autoincrementvalue = 
                (col_min_val + autoincrementinc)">
            <xsl:value-of select="''"/>
          </xsl:when>

这是完整的模板

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <!--Reseed Derby identity column-->
  <xsl:output omit-xml-declaration='yes' method='text' />
  <xsl:param name="stmtsep">;</xsl:param>
  <xsl:param name="schemprefix"></xsl:param>
  <xsl:template match="tables">
    <xsl:variable name="identitycount" select="count(table/column/identity)"></xsl:variable>
    <xsl:for-each select="table/column/identity">
      <xsl:variable name="table_schem" select="../../table_schem"></xsl:variable>
      <xsl:variable name="table_name" select="../../table_name"></xsl:variable>
      <xsl:variable name="tablespec">
        <xsl:if test="$schemprefix">
          <xsl:value-of select="$table_schem"/>.</xsl:if><xsl:value-of 
                        select="$table_name"/></xsl:variable>
      <xsl:variable name="col_name" select="../col_name"></xsl:variable>
      <xsl:variable name="newstart">
        <xsl:choose>
          <xsl:when test="autoincrementinc > 0">
            <xsl:choose>
              <xsl:when test="col_max_val = '' and 
                        autoincrementvalue = autoincrementstart">
                <xsl:value-of select="''"/>
              </xsl:when>
              <xsl:when test="col_max_val = ''">
                <xsl:value-of select="autoincrementstart"/>
              </xsl:when>
              <xsl:when test="autoincrementvalue =
                    (col_max_val + autoincrementinc)">
                <xsl:value-of select="''"/>
              </xsl:when>
              <xsl:when test="(col_max_val + autoincrementinc) &lt; 
                        autoincrementstart">
                <xsl:value-of select="autoincrementstart"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="col_max_val + autoincrementinc"/>
              </xsl:otherwise>              
            </xsl:choose>
          </xsl:when>
          <xsl:when test="autoincrementinc &lt; 0">
            <xsl:choose>
              <xsl:when test="col_min_val = '' and
                    autoincrementvalue = autoincrementstart">
                <xsl:value-of select="''"/>
              </xsl:when>
              <xsl:when test="col_min_val = ''">
                <xsl:value-of select="autoincrementstart"/>
              </xsl:when>
              <xsl:when test="autoincrementvalue = 
                    (col_min_val + autoincrementinc)">
                <xsl:value-of select="''"/>
              </xsl:when>
              <xsl:when test="(col_min_val + autoincrementinc) >
                        autoincrementstart">
                <xsl:value-of select="autoincrementstart"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="col_min_val + autoincrementinc"/>
              </xsl:otherwise>              
            </xsl:choose>
          </xsl:when>          
        </xsl:choose>
      </xsl:variable>
      <xsl:if test="not(position()=1)"><xsl:text>
</xsl:text></xsl:if>
      <xsl:choose>
        <!--restart with ddl changes both the next identity value AUTOINCREMENTVALUE and
        the identity start number AUTOINCREMENTSTART eventhough in this casewe only want 
        to change only the next identity number-->
        <xsl:when test="$newstart != '' and 
                        $newstart != autoincrementvalue">alter table <xsl:value-of 
select="$tablespec"/> alter column <xsl:value-of 
select="$col_name"/> restart with <xsl:value-of 
select="$newstart"/><xsl:if test="$identitycount>1">;</xsl:if></xsl:when>
        <xsl:otherwise>-- reseed <xsl:value-of select="$tablespec"/> is not necessary</xsl:otherwise>
          </xsl:choose>
</xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

When trying to do math on an big integer (int64) large number in xslt template I get the wrong result since there is no native 64-bit integer support in xslt (xslt number is 64-bit double). I am using msxml 6.0 on Windows XP SP3. Are there any work around for this on Windows?

<tables>
  <table>
    <table_schem>REPADMIN</table_schem>
    <table_name>TEST_DESCEND_IDENTITY_BIGINT</table_name>
    <column>
      <col_name>COL1</col_name>
      <identity>
        <col_min_val>9223372036854775805</col_min_val>
        <col_max_val>9223372036854775805</col_max_val>
        <autoincrementvalue>9223372036854775807</autoincrementvalue>
        <autoincrementstart>9223372036854775807</autoincrementstart>
        <autoincrementinc>-1</autoincrementinc>
      </identity>
    </column>
  </table>
</tables>

This test returns true due to the inexact representation of the large integer in 64-bit double (I am assuming) but actually is false if I could tell the xslt processor somehow to use int64 rather than the default 64-bit double for the number data since big integer is the actual data type for numbers in the xml input.

          <xsl:when test="autoincrementvalue = 
                (col_min_val + autoincrementinc)">
            <xsl:value-of select="''"/>
          </xsl:when>

here is the complete template

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <!--Reseed Derby identity column-->
  <xsl:output omit-xml-declaration='yes' method='text' />
  <xsl:param name="stmtsep">;</xsl:param>
  <xsl:param name="schemprefix"></xsl:param>
  <xsl:template match="tables">
    <xsl:variable name="identitycount" select="count(table/column/identity)"></xsl:variable>
    <xsl:for-each select="table/column/identity">
      <xsl:variable name="table_schem" select="../../table_schem"></xsl:variable>
      <xsl:variable name="table_name" select="../../table_name"></xsl:variable>
      <xsl:variable name="tablespec">
        <xsl:if test="$schemprefix">
          <xsl:value-of select="$table_schem"/>.</xsl:if><xsl:value-of 
                        select="$table_name"/></xsl:variable>
      <xsl:variable name="col_name" select="../col_name"></xsl:variable>
      <xsl:variable name="newstart">
        <xsl:choose>
          <xsl:when test="autoincrementinc > 0">
            <xsl:choose>
              <xsl:when test="col_max_val = '' and 
                        autoincrementvalue = autoincrementstart">
                <xsl:value-of select="''"/>
              </xsl:when>
              <xsl:when test="col_max_val = ''">
                <xsl:value-of select="autoincrementstart"/>
              </xsl:when>
              <xsl:when test="autoincrementvalue =
                    (col_max_val + autoincrementinc)">
                <xsl:value-of select="''"/>
              </xsl:when>
              <xsl:when test="(col_max_val + autoincrementinc) < 
                        autoincrementstart">
                <xsl:value-of select="autoincrementstart"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="col_max_val + autoincrementinc"/>
              </xsl:otherwise>              
            </xsl:choose>
          </xsl:when>
          <xsl:when test="autoincrementinc < 0">
            <xsl:choose>
              <xsl:when test="col_min_val = '' and
                    autoincrementvalue = autoincrementstart">
                <xsl:value-of select="''"/>
              </xsl:when>
              <xsl:when test="col_min_val = ''">
                <xsl:value-of select="autoincrementstart"/>
              </xsl:when>
              <xsl:when test="autoincrementvalue = 
                    (col_min_val + autoincrementinc)">
                <xsl:value-of select="''"/>
              </xsl:when>
              <xsl:when test="(col_min_val + autoincrementinc) >
                        autoincrementstart">
                <xsl:value-of select="autoincrementstart"/>
              </xsl:when>
              <xsl:otherwise>
                <xsl:value-of select="col_min_val + autoincrementinc"/>
              </xsl:otherwise>              
            </xsl:choose>
          </xsl:when>          
        </xsl:choose>
      </xsl:variable>
      <xsl:if test="not(position()=1)"><xsl:text>
</xsl:text></xsl:if>
      <xsl:choose>
        <!--restart with ddl changes both the next identity value AUTOINCREMENTVALUE and
        the identity start number AUTOINCREMENTSTART eventhough in this casewe only want 
        to change only the next identity number-->
        <xsl:when test="$newstart != '' and 
                        $newstart != autoincrementvalue">alter table <xsl:value-of 
select="$tablespec"/> alter column <xsl:value-of 
select="$col_name"/> restart with <xsl:value-of 
select="$newstart"/><xsl:if test="$identitycount>1">;</xsl:if></xsl:when>
        <xsl:otherwise>-- reseed <xsl:value-of select="$tablespec"/> is not necessary</xsl:otherwise>
          </xsl:choose>
</xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风为裳 2024-09-02 13:21:34

有没有解决这个问题的方法
Windows?

否,除非您使用 XSLT 2.0 处理器,例如 Saxon 或 AltovaXML

在 XSLT 2.0 中,使用 XPath 2.0,它支持 xs:decimal,这为您提供了所需的精度。对于 Saxon,也可以只使用 xs:integer,因为 Saxon 和 Altova 都实现 Big Integer 算术。

这是一个 XSLT 2.0 样式表(默认情况下使用 xs:integer)

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output method="text"/>

 <xsl:template match="/">
   <xsl:value-of select=
     "9223372036854775805 + (-1)"/>
 </xsl:template>
</xsl:stylesheet>

Saxon 9.x 和 AltovaXML2010 都会生成以下正确结果

9223372036854775804

这是一个 XSLT显式使用 xs:decimal 的 2.0 样式表

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output method="text"/>

 <xsl:template match="/">
   <xsl:value-of select=
     "xs:decimal(9223372036854775805) + (-1)"/>
 </xsl:template>
</xsl:stylesheet>

Saxon 9.x 和 AltovaXML2010 再次生成正确的结果

Are there any work around for this on
Windows?

No, unless you use an XSLT 2.0 processor, such as Saxon or AltovaXML.

In XSLT 2.0 XPath 2.0 is used, which has support for xs:decimal and this gives you the required precision. With Saxon one can also use just xs:integer, because both Saxon and Altova implement Big Integer arithmetic.

Here is an XSLT 2.0 stylesheet (that uses xs:integer by default):

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output method="text"/>

 <xsl:template match="/">
   <xsl:value-of select=
     "9223372036854775805 + (-1)"/>
 </xsl:template>
</xsl:stylesheet>

Both Saxon 9.x and AltovaXML2010 produce the following correct result:

9223372036854775804

Here is an XSLT 2.0 stylesheet that uses xs:decimal explicitly:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output method="text"/>

 <xsl:template match="/">
   <xsl:value-of select=
     "xs:decimal(9223372036854775805) + (-1)"/>
 </xsl:template>
</xsl:stylesheet>

Both Saxon 9.x and AltovaXML2010 again produce the correct result

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文