2010-03-27 70 views
1

當試圖在xslt模板中的大整數(int64)大數字上進行數學運算時,我得到錯誤的結果,因爲xslt中沒有本機64位整數支持(xslt number is 64位雙)。我在Windows XP SP3上使用msxml 6.0。 Windows上有沒有解決這個問題的方法?處理msxml的XSLT大整數(int64)

<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位數double的數字數據,因爲big integer是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> 

回答

1

是否有這方面的任何工作,圍繞 的Windows?

否,除非你使用XSLT 2.0處理器,諸如撒克遜或AltovaXML

在XSLT 2.0中使用了XPath 2.0,它支持xs:decimal,並且這可以提供所需的精度。使用Saxon,人們也可以使用xs:integer,因爲Saxon和Altova都實現Big Integer算法。

下面是一個XSLT 2.0樣式表(即使用的xs:默認整數)

<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> 

兩者撒克遜9.x和AltovaXML2010產生以下正確結果

9223372036854775804 

這是一個XSLT 2.0樣式表,它使用xs:明確的小數點

<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> 

兩個撒克遜9.x和AltovaXML2010再次產生正確的結果

+0

感謝您的信息。恐怕我現在被困在msxml 6.0中。由於我從sql select語句的結果集中生成輸入xml,因此正確執行數學運算的一種可行方法是在數據庫select語句中執行數學運算,並將newstart元素添加到輸入xml;那麼xslt processer將根本不會做數學計算,只需檢查$ newstart的空字符串以生成輸出 – 2010-03-27 16:27:09