2009-08-15 40 views
3

需要在使用XSLT從XML文件接收數字時添加備用數字,例如,如果我正在接收123456789,則需要使用XSLT函數從最右邊計算備用數字總和,我可以對此有任何建議嗎?備用數字之和(XML/XSL)

感謝, Laxmikanth.S

回答

3

這是非常容易使用XSLT 2.0(實際上只是一個XPath 2.0表達式)做:

以下XSLT轉換:

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

    <xsl:template match="/"> 
     <xsl:sequence select= 
     "sum(for $n in reverse(string-to-codepoints('123456789')) 
            [position() mod 2 eq 1] 
      return 
       $n - string-to-codepoints('0') 
      ) 
     "/> 
    </xsl:template> 
</xsl:stylesheet> 

上的任何XML文檔(沒有應用。查閱全文時使用),產生正確的結果:

請注意使用的XPath 2.0中的功能:string-to-codepoints()codepoints-to-string()reverse()


UPDATE: 類似,但有點簡單的表達式是:

sum(for $n in reverse(string-to-codepoints('123456789')) 
           [position() mod 2 eq 1] 
     return 
     xs:integer(codepoints-to-string($n)) 
    ) 

爲了這個表達式編譯時,XS前綴必須綁定到命名空間: 「http://www.w3.org/2001/XMLSchema

-2

是;不要爲此使用XSLT或XML,這是沒有意義的。

+0

即使它是固定長度的數字,我的意思是10位數字? – 2009-08-15 03:41:50

+0

我正在使用撒克遜分析器,它具有撒克遜擴展,但我很新這個解析器,有什麼建議嗎? – 2009-08-15 03:50:39

+0

不是我已經提供的。也許別人會對你有一些評論。 – 2009-08-15 03:51:38

0

如果您有EXSL擴展名(http://exslt.org),則可以執行如下操作:

sum(str:tokenize($x,'')[position() mod 2 = 0]) 

如果不是,您可以通過循環使用子字符串函數來做類似的事情。

0

如果您無法使用XSLT 2.0,則仍然可以使用XSLT 1.0。一種方法可以遞歸調用命名模板:

<xsl:template match="number"> 
    <xsl:call-template name="sumdigits"> 
     <xsl:with-param name="number" select="." /> 
    </xsl:call-template> 
</xsl:template> 

<xsl:template name="sumdigits"> 
    <xsl:param name="number" /> 
    <xsl:param name="runningtotal">0</xsl:param> 
    <xsl:choose> 
     <xsl:when test="string-length($number) = 0"> 
      <xsl:value-of select="$runningtotal" /> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:variable name="lastdigit" select="substring($number, string-length($number), 1)" /> 
      <xsl:variable name="newrunningtotal" select="number($runningtotal) + number($lastdigit)" /> 
      <xsl:call-template name="sumdigits"> 
       <xsl:with-param name="number" select="substring($number, 1, string-length($number) - 2)" /> 
       <xsl:with-param name="runningtotal" select="$newrunningtotal" /> 
      </xsl:call-template> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

它的工作原理是讓最後的數字輸入,將其添加到一個「運行總計」和遞歸調用帶的最後兩位數字的命名模板輸入被刪除。當沒有剩餘數字時,可以返回運行總數。

這XSLT片斷假定輸入是在XML命名爲「數字」

<number>123456789</number> 

結果應該是25.正如你所看到的,在XSLT2.0做這將是更加美好的元素中。

1

對於XSLT 1.0解決方案,我將使用FXSL

這種轉變首先反轉的字符串,使用「str-reverse」模板,然後執行兩次調用「str-foldl」模板,做的工作:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:dvc-foldl-func="dvc-foldl-func" 
exclude-result-prefixes="xsl dvc-foldl-func" 
> 
    <xsl:import href="str-foldl.xsl"/> 
    <xsl:import href="strReverse.xsl"/> 

    <dvc-foldl-func:delEven/> 
    <dvc-foldl-func:add/> 

    <xsl:variable name="vFoldlDelEven" 
     select="document('')/*/dvc-foldl-func:delEven[1]"/> 
    <xsl:variable name="vFoldlAdd" 
     select="document('')/*/dvc-foldl-func:add[1]"/> 

    <xsl:output method="text"/> 

    <xsl:template match="/"> 
     <xsl:variable name="vReversed"> 
     <xsl:call-template name="strReverse"> 
      <xsl:with-param name="pStr" select="'123456789'"/> 
     </xsl:call-template> 
     </xsl:variable> 

     <xsl:variable name="vOddDigits"> 
      <xsl:call-template name="str-foldl"> 
      <xsl:with-param name="pFunc" select="$vFoldlDelEven"/> 
      <xsl:with-param name="pStr" select="$vReversed"/> 
      <xsl:with-param name="pA0" select="''"/> 
      </xsl:call-template> 
     </xsl:variable> 

     <xsl:call-template name="str-foldl"> 
     <xsl:with-param name="pFunc" select="$vFoldlAdd"/> 
     <xsl:with-param name="pStr" select="$vOddDigits"/> 
     <xsl:with-param name="pA0" select="0"/> 
     </xsl:call-template> 
    </xsl:template> 

    <xsl:template match="dvc-foldl-func:add"> 
     <xsl:param name="arg1" select="0"/> 
     <xsl:param name="arg2" select="0"/> 

     <xsl:value-of select="$arg1 + $arg2"/> 
    </xsl:template> 

    <xsl:template match="dvc-foldl-func:delEven"> 
     <xsl:param name="arg1"/> 
     <xsl:param name="arg2"/> 

     <xsl:copy-of select= 
      "concat($arg1, 
        $arg2 * (string-length($arg1) mod 2 = 0) 
       ) 
      "/> 
    </xsl:template> 
</xsl:stylesheet> 

當上述改造應用於任何源XML(忽略),獲得所需結果

請注意

  1. 第一個模板調用反轉的字符串。
  2. 第二模板呼叫替換反轉串的用0
  3. 最後模板呼叫每隔偶數放置位產生的所有數字的總和由第二模板呼叫所生成的字符串中
3

萬一你這樣做,因爲你需要計算Luhn (mod 10) checksum的東西,這是發佈在IBM developerWorks

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:regexp="http://exslt.org/regular-expressions" xmlns:tns="http://www.example.org/tns" xmlns:dp="http://www.datapower.com/extensions" extension-element-prefixes="dp" exclude-result-prefixes="dp regexp" xmlns:fn="http://www.w3.org/2005/02/xpath-functions"> 
    <xsl:template match="/"> 
    <xsl:call-template name="recLuhn"> 
     <xsl:with-param name="index" select="1"/> 
     <xsl:with-param name="parity" select="string-length(CreditCard) mod 2"/> 
    </xsl:call-template> 
    </xsl:template> 
    <xsl:template name="recLuhn"> 
    <xsl:param name="index"/> 
    <xsl:param name="parity"/> 
    <xsl:choose> 
     <xsl:when test="$index &lt;= string-length(CreditCard) "> 
     <xsl:variable name="sum"> 
      <xsl:call-template name="recLuhn"> 
      <xsl:with-param name="index" select="$index + 1"/> 
      <xsl:with-param name="parity" select="$parity"/> 
      </xsl:call-template> 
     </xsl:variable> 
     <xsl:variable name="thisSum"> 
      <xsl:choose> 
      <xsl:when test="$index mod 2 != $parity"> 
       <xsl:choose> 
       <xsl:when test="substring(CreditCard, $index, 1)*2 &gt; 9"> 
        <xsl:value-of select="(number(substring(CreditCard, $index, 1)) * 2) - 9"/> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:value-of select="number(substring(CreditCard, $index, 1)) * 2"/> 
       </xsl:otherwise> 
       </xsl:choose> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:value-of select="number(substring(CreditCard, $index, 1))"/> 
      </xsl:otherwise> 
      </xsl:choose> 
     </xsl:variable> 
     <xsl:value-of select="$thisSum + $sum"/> 
     </xsl:when> 
     <xsl:otherwise> 
     <xsl:value-of select="0"/> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 
</xsl:stylesheet>