XSLT中用遞迴實現迴圈

來源:互聯網
上載者:User

XSLT 是圖靈完成的(Turing complete)。也就是說,如果有足夠的記憶體,那麼 XSLT 可以完成其他任何圖靈完成語言(如 C++)所能完成的計算。對於屬性更傳統的語言的程式員來說,這可能有點奇怪。畢竟 XSLT 缺少對很多演算法來說極其重要的特性,其中包括迴圈和可變的變數。

注意:XSLT 所謂的變數在其他多數語言中稱為常量。它們更像是代數變數而不是傳統的編程變數。

函數式編程

上述的遺漏並非疏忽所致。XSLT 是一種函數式語言而不是過程性語言。在 C 或 Pascal 這樣的過程性語言中,程式被定義成一系列的步驟,這些步驟按照規定的順序執行,並在最後一步產生最終結果。在函數式語言中,程式被定義成由其他函數組成的函數,函數求值形成最終的結果。函數式語言的最大優點是執行的順序無關緊要。作為一個簡單的例子,考慮下面兩個(代數)函數:

f(x) = 2*x
g(x) = x - 3

設函數 h(x) 是 f 與 g 的複合函數:

h(x) = f(g(x))

對該函數求值可以先計算 g:

h(x) = f(x - 3) = 2 * (x - 3) = 2x - 6

也可以先計算 f:

h(x) = 2 * g(x) = 2 * (x - 3) = 2x - 6

兩者的結果是一樣的。語言的函數式使其更適合并行處理,因為問題的多個部分可以同時計算,無需擔心其中的一部分要先於其他部分計算。安全執行緒是自動實現的。

函數式語言套件括 XSLT,但不能包含傳統的迴圈,因為迴圈在時間上是有序的。就是說,典型迴圈的編寫和編譯必須保證 i==1 出現在 i==2 之前。當然,也可以反向而不是正向運行迴圈,或者使用 1 之外的迴圈計數器增量,甚至像 while 語句那樣完全取消迴圈計數器。但是無論什麼類型的迴圈,執行的順序都至關重要,這一點與函數式編程正好相反。

遞迴

函數式編程中,傳統語言中用迴圈完成的多數任務都可以使用遞迴來完成。參數代替了變數。比如,最近有人問我如何輸出在編譯時間不知道數量的點(句點)。比方說,格式化菜單時可能要用到,因為在菜名和價格之間常常需要不同數量的點:

Crawfish Etoufee.......$9.95
Fried Chicken..........$6.95

在 C 語言中可以編寫一個簡單的函數:

void printDots(int n) {
  int i;
  for (i = 0; i < n; i++) {
   printf(".");
  }
 
}

但是這並不是解決問題的惟一辦法。可以用遞迴代替迴圈,比如:

void printDotsRecursively(int n) {
  if (n > 0) {
   printf(".");
   printDots(n-1);
  }
 
}

在 C 中很少這樣做,但是在 XSLT 中,這是惟一的辦法。

下面的模板準確地產生 count 參數所傳遞的數量的點。邏輯很簡單:如果 $count 的值大於零,就輸出一個點,將 count 參數減去 1 後再調用這個函數;否則什麼也不做。這與 printDotsRecursively 函數採用的演算法基本相同,只不過是用 XSLT 而非 C 實現的:

 <xsl:template name="dots">
 
    <xsl:param name="count" select="1"/>
    <xsl:if test="$count > 0">
     <xsl:text>.</xsl:text>
     <xsl:call-template name="dots">
      <xsl:with-param name="count" select="$count - 1"/>
     </xsl:call-template>
    </xsl:if>
   
  </xsl:template>

比如要輸出 100 個點,用 100 count 參數值調用該函數:

  <xsl:call-template name="dots">
    <xsl:with-param name="count" select="100"/>
   </xsl:call-template>

如果不希望傳遞一個常數值,那麼還可以根據其他資料計算要列印的點數。比如,下面的指令分別計算價格和菜名的長度(更具體地說,是上下文節點中 price 和 entree 子項目的 string-values 函數值)後,輸出足夠做的點數將每個菜單行填充到 80 個字元:

  <xsl:call-template name="dots">
    <xsl:with-param name="count"
         select="80 - string-length(entree) - string-length(price)"/>
   </xsl:call-template>

結束語

無論是在 C、XSLT 中,還是在 Scheme 中,都應用了使用遞迴代替迴圈。但是這種技術非常優雅。在 XSLT 中不需要經常使用這種技術,但使用這種技術可以完成用其他任何標準 XSLT 技術都做不到的技巧性任務。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.