在 XSLT 中用遞迴實現迴圈

2021-07-31 14:42:48 字數 2313 閱讀 8605

擴充套件 xslt 能力的技術

xslt 是一種函式式程式語言,類似於 haskell 或 scheme,但是與 c 和 fortran 不同。因此這種語言沒有迴圈,也沒有可變的變數。相反,必須用遞迴和引數來代替這些結構。這篇技巧示範了如何使用命名模板和xsl:call-templatexsl:with-paramxsl:param元素來提供這種功能。

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

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

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

f(x) = 2*x

g(x) = x - 3

設函式h(x)fg的復合函式:

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) 

}

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

void printdotsrecursively(int n) 

}

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

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

0">

.

比如要輸出 100 個點,用 100count引數值呼叫該函式:

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

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

xslt計數迴圈 在XSLT中使用遞迴進行迴圈

xslt計數迴圈 xslt已經完成。這意味著只要有足夠的記憶體,xslt就可以計算任何其他圖靈完備的語言 例如c 可以計算的任何東西。對於習慣於更傳統語言的程式設計師來說,這有點令人驚訝。畢竟,xslt缺少一些對許多演算法都很重要的功能,包括迴圈和可變變數。注意 xslt所謂的變數在大多數其他語言中...

在Delphi中用XSLT轉換xml檔案格式

uses xmldoc,xmlintf function transform xmlcontent string xslcontent string widestring var xml ixmldocument xsl ixmldocument begin xml loadxmldata xmlc...

在Delphi中用XSLT轉換xml檔案格式

uses xmldoc,xmlintf function transform xmlcontent string xslcontent string widestring var xml ixmldocument xsl ixmldocument begin xml loadxmldata xmlc...