2010-12-16 54 views

回答

7

我覺得這有一些做什麼用的理解push vs. pull風格處理的不僅僅是比較xsl:for-eachxsl:template match="..."。您經常會看到另一個學科的程序員使用很多xsl:if,xsl:choose和for-loops,當問題可以用更優雅的XSLTish方式解決時。

不過的問題:在我看來,如果你考慮使用xsl:for-each,而不是處理數據,你需要重新考慮xsl:apply-templates。在某些情況下,for循環適用於XSLT,但每當匹配的模板執行相同操作時,模板就是要走的路。根據我的經驗,您通常可以用xsl:apply-templates代替大多數xsl:for-each

,因爲我看到使用匹配模板在for循環它的一些好處是:

  • 的樣式表更容易維護和擴展,特別是如果源數據發生變化。
  • 正如@chiborg所提到的,模板可以被重用,因爲它們沒有內置到特定的模板中。與XSLT 2.0中的xsl:next-match一起,您可以以強大的方式將模板鏈接在一起。
  • 您不必模擬已經內置於所有XSLT處理器的行爲,也就是說,使用xsl:apply-templates並讓處理器爲您工作。
  • 此外,我發現更容易理解和調試推式樣式表。如果您將樣式表信息劃分爲一小部分或幾部分,並編寫特定的匹配模式,可以很容易地看出哪個模板正在做什麼並追蹤問題的根源。
+0

我同意你容易看到每個模板中發生了什麼,但很難看到哪個模板將以什麼順序(使用apply-templates)被調用。 – LarsH 2010-12-16 16:08:15

+0

@LarsH:這就是你使用Oxygens奇妙的調試...;) – 2010-12-16 19:39:42

+0

你是對的,我這樣做:-),有時候它是一種生命保護。但是,只有掌握了XML輸入數據,調試才能起到幫助作用......並且它只能爲特定數據實例提供幫助。然而,如果你可以通過理解閱讀樣式表,那麼無論具體的輸入如何,與不能閱讀樣式表的理解相比,你都可以得出更多關於什麼可以發生和不可能發生的結論。 – LarsH 2010-12-16 19:48:49

1

for-each只能在模板中的一個位置使用。模板可以通過不同的apply-templates調用重新使用。由於增加了靈活性,我大多使用模板而不是每個模板。

3

這其實並不重要,但你可能要考慮它的規則下拇指,我發現:

  • 如果代碼依賴於上下文 位置(位置()),把它放在 <xsl:for-each>
  • 如果代碼取決於上下文 節點(。或任何位置路徑),則將其放入一個匹配模板中 。
  • 否則,請使用命名模板。

參考和閱讀更多: http://www.jenitennison.com/blog/node/9

1

這些是完成不同的XSLT指令。

除了推拉式和拉式之外,這更像迭代與遞歸。

xsl:for-each是一個迭代器指令,它具有無狀態聲明範例中迭代的所有優點和約束:好的處​​理器不應該監聽調用棧。

xsl:apply-templates是一般的遞歸指令。一般意義上它比xsl:call-template更強大:你將所選節點「拋出」到模式匹配機制,這是一個真正的「動態函數調用」。

5

無論是 '的for-each' 和 '模板' 是 用於檢索從XML節點中 在xsl。但在基本

它們之間的區別 是什麼下面是一些最重要的區別

  1. xsl:apply-templates也更加豐富,比xsl:for-each更深,甚至 只是因爲我們不知道將在 的節點上應用什麼代碼 - 在一般情況下,這個代碼將不同於 的n個不同節點ODE列表。

  2. 將應用於 可寫的方式xsl:apply template S爲書面後由 人不知道原作者的代碼。

FXSL library的實現在XSLT高階函數(HOF)是不可能的,如果 XSLT沒有足夠的<xsl:apply-templates>指令。

摘要:模板和<xsl:apply-templates>指令是XSLT如何實現和處理多態性。

參考:看到這個整個主題:http://www.stylusstudio.com/xsllist/200411/post60540.html

+0

在「這整個線程」Dimitre什麼也沒有寫在這個SO頁面上。 – Roland 2013-05-22 09:25:06

+0

@羅蘭,「這整個線程」在這裏被引用作爲參考,結合在一起的一些明亮的人的答案。在這個答案中沒有任何聲明說人會找到不同的東西。 – 2013-05-22 13:23:58

10

我大體上同意其他的答案,但我會說,以我的經驗,與xsl:for-each寫的樣式表可以是一個更容易閱讀,理解和維護比一個嚴重依賴xsl:apply-templates ...尤其是xsl:apply-templates具有隱式選擇(或非常通用的選擇,如select="node()")。

爲什麼?因爲很容易看到每個人會做什麼。使用apply-templates,你基本上必須(a)知道所有可能的XML輸入(如果你有一個模式,這將更容易,但是你仍然需要消化模式;並且很多時候你沒有模式,特別是對於在管道的一個階段發送的臨時中間XML數據;即使您有一個模式,您的開發框架(例如ESB或CMS)也可能無法讓您在管道的每個點上驗證XML。因此,如果無效數據在你身上不會立即得到通知),那麼你可以預測將選擇哪種節點(例如上下文節點的子節點); (b)查看樣式表中的每個模板以查看哪個模板與具有最高優先級(最後以文檔順序)的節點相匹配。處理順序也可以跳過所有文件或不同文件(導入或包含)。這可能使「很難」看到發生了什麼事情。

鑑於使用for-each,您確切知道將實例化哪些代碼:for-each中的代碼。由於每一個都需要一個明確的選擇表達式,所以你可能會有一個更窄的字段來猜測哪些節點可以匹配。

現在我並不否認apply-templates比for-each更強大和更靈活。這正是關鍵:更強大和更靈活的構造,也更難約束,理解和調試(並防止出現安全漏洞)。這是Rule of Least Power:「強大的語言(或在這種情況下,構造)禁止信息重用。」 (Also discussed here

當您使用apply-templates時,每個模板都是更模塊化的,因此它本身的可重用性更強,但樣式表更復雜,模板之間的交互可預測性更低。當你使用for-each時,處理流程很容易預測和查看。

使用<xsl:apply-templates />(或使用<xsl:for-each select="node()"/>),當輸入XML的結構發生變化時,樣式表的行爲會發生變化,無需開發人員的審閱。這是好還是壞取決於你對樣式表的多少深思熟慮,以及XML模式開發人員和樣式表開發人員(可能是同一個人或可能屬於不同的組織)之間有多少良好的溝通。

對我來說,這是一個判斷的呼籲。如果您有面向文檔的XML(如HTML),其中許多元素類型實際上可以具有許多不同類型的子元素,並且具有任意深度的層次結構,並且對給定元素類型的處理並不經常取決於其上下文,那麼apply-templates是絕對必要的。另一方面,如果您有「面向數據」的XML,並且具有可預測的結構,那麼在不同的上下文中,通常不會有相同的元素類型表示相同的元素類型,因爲每個元素可以更直接地讀取和調試(並因此寫入正確和快速)。

+1

+1我認爲這是一個比公認的答案更平衡的評估 – PandaWood 2011-01-04 07:18:49

+0

@PandaWood,謝謝。 – LarsH 2011-01-06 19:05:59

1

for-each的一種用法我還沒有見過提及:可以使用它將上下文節點切換到另一個文檔。我用它將數據XML轉換爲HTML輸入表單。與數據字段相匹配的模板包含for-每個選擇單個節點:XSD中描述要變換的數據字段的xs:element

使用XSD中的描述,一個數據字段可以轉換爲單選按鈕組,下拉框或純文本輸入。沒有for-each我無法同時瀏覽這兩個文檔。

一般來說,我更喜歡匹配模板。我發現它對應於單個變換的概念,一次應用比每個節點更好,然後是下一個,然後是後一個,等等。但是這當然是個人偏好。

+0

+1。設置上下文節點是「for-each」的一個重要用途 - 好點。通常,這是設置上下文節點的最簡潔明瞭的方法。然而,你*也可以使用'apply-templates'來做同樣的事情。換句話說,我不認爲你不能在不使用for-each的情況下同時瀏覽兩個文檔。請記住'apply-templates'可以使用模式並傳遞參數。 – LarsH 2016-07-14 17:39:24

相關問題