开发者

XSLT big integer (int64) handling msxml

开发者 https://www.devze.com 2022-12-24 15:37 出处:网络
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

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"/&开发者_Python百科gt;</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>


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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号