關於本系列教程
W3C 發布的最新規范 XSLT 2.0 是一種轉換 XML 文檔的語言。它包括很多新的特性,部分是為克服 XSLT 1.0 的不足而設計的。這組文章從 XSLT 1.0 用戶的角度(希望解決老問題、學習新技術和發現值得期待的新特性),提供了對 XSLT 2.0 的高水平概述和深入剖析。我們提供了來自常見應用程序的例子,並為那些希望升級的用戶提供了實用的建議。為了幫助您開始使用 XSLT 2.0,本文還提供了相應的遷移技術。
考慮 XSLT 升級的策略
您可能聽說過 XSLT 2.0 基本兼容 1.0,並增加了很多新特性。您的 1.0 樣式表也許只用到了 1.0 的一部分,可能將用到 2.0 特性集合更小的一部分。准備升級的時候,要把精力集中到您使用的舊特性和吸引您 的新特性上。本文提出了五種選擇,代表五種經過提煉的升級觀點(也許不能說五種升級觀點,因為也包括不升級的選擇)。選擇哪種策略有兩類決策因素需要考慮:組織的能力因素和吸引您的 2.0 特性的推動因素。
需要知道什麼
XSLT 規范的 2.0 版引入了一個術語樣式表模塊來表示能夠導入或包括到稱為樣式表的集合實體的單位(通常是文件)。模塊提供了比模板劃分更強的劃分,主要因為 XSLT 聲明通常局限於單個模塊。閱讀完本文並且考慮了哪種方法最好之後,如果准備采用漸進式的方法,可以使用模塊把舊的 XSLT 代碼從新代碼中劃分出來(除了已有的模塊劃分之外)。
為了便於從 1.0 樣式表遷移到 2.0,廠商可以(根據自己的意願)提供支持向後兼容(BC)的 2.0 處理程序。在樣式表中,該特性由 version 屬性控制,它可以出現在任何元素中。(還記得嗎,在 1.0 中,version 屬性只能出現在頂層 xsl:stylesheet 元素中。)如果一個元素包含該屬性,並且值為 1.0,則對該元素本身及其中的子樹啟用 BC 特性。從概念上說類似於能夠像在 1.0 中那樣執行的代碼孤島,除了極少數例外情況。要記住,該特性是根據樣式表的文檔結構而不是運行轉換時的執行流來啟用的。比如,如果 xsl:call-template 指令包含屬性 version="1.0",但執行中調用的命名模板包含屬性 version="2.0",則執行那個被調用的模板時不會啟用 BC。
類似的,被導入或者被包括的樣式表模塊如果包含屬性 version="1.0",則對那個模塊啟用 BC 特性,即使主樣式表是 2.0 樣式表也是如此。如果執行由 2.0 處理程序在 BC 模式下執行,結果可能和 1.0 處理程序生成的結果不完全一樣。關於 1.0 處理程序和 2.0 處理程序 BC 模式的差異列表,請參閱 XSLT 2.0 (附錄 J)、F&O (附錄 D) 和 XPath 2.0 (附錄 I) 的兼容性附錄。
其他工具為 XSLT 1.0 和 XSLT 2.0 處理程序提供了不同的代碼,但是它們在更低的層次上工作。這一節的概念對於准備升級的策略來說應該足夠了。
選擇適合您的策略
每種選擇各有利弊。這一節簡要描述各種選擇,列舉了各種優點和需要付出的代價。少數選項把“可以應用當地標准調整或者代碼清理”作為一個優點,意思是說已有的代碼清理項目列表仍然有用。清理可能是關於編碼風格或策略(如關於哪些模塊擁有包含特定聲明的特權)的內部規定。
選項 1:完全按 2.0 重寫
如果選擇這種方式,那麼就類似於一切從頭開始。為了充分利用 XSLT 2.0 的語法和特性,必須為可能需要修改整個設計和重寫大部分樣式表模塊作好准備。如果當前的樣式表有很好的模塊化結構,可以選擇保留原來的結構。更常見的情況是,如果您的 1.0 樣式表已經有清晰的架構,您就可以節省一些計劃時間,這取決於您希望利用哪些 2.0 特性。
優點 缺點 因為基本上從零開始,所以可以充分利用 2.0 的語法和特性的優勢。不需要尋找支持向後兼容的 2.0 處理程序。
使用 2.0 特性可以讓代碼更容易閱讀。更多信息請參閱本系列的第 1 部分。
因為不需要向後兼容,代碼代碼更簡單直接。
結果是跨 2.0 處理程序的可移植性。
必須學習有關的所有 2.0 特性。(馬上!)馬上面臨著很多分析和准備工作要做。
等待得到回報的時間最長。
該設計很難繼續使用 1.0 代碼,必須中斷開發工作。
選項 2:將大部分樣式表轉化成 2.0 但保留 1.0 孤島
如果全部用 2.0 重寫過於激進,那麼次佳的選項就是將大部分樣式表模塊轉換到 2.0 並重用一些 1.0 模塊。可以在單個模板或者更深的層次上保留 1.0 孤島。該選項仍然需要一些規劃,特別是在什麼地方使用新的 2.0 特性,並調查在新的樣式表結構中舊模塊的可重用性。
優點 缺點 如果希望最終避免使用 BC 的話,該選項是漸進式遷移的最佳方法。該選項可以將注意力集中到向後兼容和喜歡的特性上。
可以增強代碼的可讀性。改進可讀性的例子請參閱本系列的 第 1 部分。
可以增強代碼的模塊化和可重用性。
可以像過去那樣應用本地標准調整或代碼清理。
本地版本控制和調整中容易出錯。該選項需要支持向後兼容的處理程序。
和孤島有關的代碼可能更難懂(雖然其他地方改進了)。
馬上需要很多規劃工作以便切實地改進代碼。
如果避免觸及薄弱的部分,這種方法可能延長混合使用多種版本的時間。
選擇不同版本的分支代碼可能需要更多的編碼時間。
選項 3:建立 2.0 孤島或者重寫需要全面修訂的模塊
如果需要特定的 2.0 特性,可以嘗試在 1.0 樣式表中補上 2.0 版的孤島,使用支持向後兼容的 2.0 處理程序運行它。如果處理程序生成意料之外的結果,則調整 1.0 模塊直到滿意為止。該選項把目標集中到需要的 2.0 特性上,規劃和重新設計的工作量很小。自然,如果需要的新特性很容易隔離出來,那麼這種方法最有效。關於哪些特性更有可能隔離出來的一些思路,請參閱後面的 收縮選擇的余地 一節。
優點 缺點 可逐步進行修改,是否進行修改由特殊的需求或者某一特定增強是否能帶來很大好處來決定。可以逐步學習新特性。
可以把精力集中到性能瓶頸上。
可以集中提高模塊化和可重用性。
如果必須保持和純 1.0 處理程序的兼容性,這種方法更容易。
可以像過去那樣應用本地標准調整和代碼清理。
選擇該選項通常會減緩采用新的 2.0 特性的進度,也不能很快享受到相應的好處。這種打補丁的方法可能由於使用錯誤的版本而造成錯誤。
該選項需要支持向後兼容的處理程序。
使用孤島可能損害整體的可讀性(雖然孤島本身可能改進了)。
確定需要修改的地方時可能很難預測孤島的數量和分布。
更難利用具有廣泛影響的新特性,如模式感知。
支持 BC 的 2.0 處理器運行 1.0 代碼仍然面臨同樣的問題,調試的時候需要了解兩個版本。
選項 4:將樣式表的版本改為 2.0 然後調試
如果需要將已有的 1.0 樣式表快速轉化成 2.0 樣式表,為何不將樣式表版本屬性設置為 2.0 看看能否從 2.0 處理得到預期結果呢?如果不成功,就開始調試,逆向跟蹤每個模板的結果並進行修改直到滿意為止。調整可能涉及到使用適當的 2.0 指令,或者(如果支持 BC 特性)將版本屬性設為 1.0 看看會發生什麼。當然,該選項不太關心利用新的 2.0 特性。
優點 缺點 可以采用漸進式方法進行轉換。如果 1.0 樣式表沒有出現兼容性異常,那麼這種轉換方法可能最快。好的測試集可以保證成功轉化。
如果幸運的話,不需要尋找支持向後兼容的 2.0 處理程序。
該選項很容易起步,開始的時候不需要費多少腦筋,因為不需要計劃,也不需要知道需要使用什麼新特性。
該選項可以將注意力集中到向後兼容和喜歡的特性上。
可以像過去那樣應用本地標准調整和代碼清理。
如果出現問題時選擇將版本設置為 1.0,該選項需要支持向後兼容的處理程序。本地版本控制和調整中很容易出現錯誤,因而延長了調試周期。
由於向後兼容和調整,得到的樣式表可能很難讀懂。
沒有啟動計劃,更難利用具有廣泛影響的新特性,如模式感知。
很難預料轉化需要多長時間。采用這種危機驅動的方法,一開始的 bug 列表可能很長。
選項 5:繼續使用 1.0
您可能會問,既然 1.0 樣式表工作得很好,那麼何必改變呢?不需要學習 2.0 語法,不需要規劃 2.0 樣式表結構,也不需要安裝 2.0 處理程序。對於您也許可行,但是要記住 2.0 能夠完成 1.0 處理程序根本做不到的事情,而且 2.0 克服了 1.0 的很多不足之處。
優點 缺點 什麼也不用做,也不需要新的處理程序(直到您再也雇不到人來編寫純 1.0 代碼)。不需要閱讀六個新規范。
如果您正在使用開放源代碼產品,尤其是具有內部編寫的擴展的開源產品,並且您對這種能夠訪問源代碼的情況感到滿意,那麼您可以繼續保持這種滿足感。
1.0 處理程序已經成熟,經過仔細的調試。
不能利用新的 2.0 特性(請參閱 第 1 部分)。處理程序 bug 修正的周期可能延長,因為 XSLT 產品開發人員可能不會再 1.0 上花費更多時間。
隨著時間的變化,知道存在一種可讀性更強的 2.0 替代品,XSLT 1.0 中的老技術可能變得更加面目可憎。
混合各種選項
前面的選項有意用單純的觀點闡述,可以混合使用這些方法來適應您的需要。比方說,可以采用選項 1 和 2 的方法制定宏大的計劃,但采用選項 4 試試看的辦法來實施。如果不喜歡當前的樣式表模塊化,可能希望從功能出發重構所有的模塊,然後進一步重構打破使用指定 XSLT 版本的模塊,就像選項 2 和 3 那樣。另一種可能是選擇一個誘人的特性,如樣式表函數(更多信息請參閱本系列的第 1 部分),確定能夠使用它的所有地方,然後決定是否將這些部分隔離出來(選項 3)或者徹底重構(選項 1)。
XQuery 怎麼樣?
如果目標是從數據存儲中提取數據,然後以帶標簽或者格式化的形式呈現數據,不需要大量改變結構,那麼您可能會發現 XQuery 能夠滿足這些需要。其他 developerWorks 文章討論了 XQuery 1.0 並和 XSLT 作了比較。
做決定之前問問自己這些問題
除了把您推向某個選項的技術因素以外,還要考慮企業文化的因素。
為什麼這麼做?
升級到 2.0 常常是因為受到 1.0 中所沒有的那些 2.0 特性的吸引。這是您准備把樣式表升級到 2.0 的原因嗎?如果是,那麼最吸引您的是什麼 2.0 特性?哪些好的新特性需要在時機成熟的時候部署?
企業如何管理開發?
企業文化在規劃方面做得怎麼樣?企業能夠承受多大的風險?有沒有人善於浏覽整個代碼庫,發現普遍的問題和機會?更喜歡代價低的調整和刪改還是第一次就把事情做好(但是代價高)?有沒有維護(bug 修正)的資源?bug 修正是主動進行的嗎,過去的效果如何?
資源在哪個階段是可用的?
您有多少時間來學習新規范?做遷移計劃呢?重新設計樣式表結構呢?相對而言,又有多少時間重新編寫樣式表模塊?部署需要的 2.0 特性是否有時間要求?如果不能承受全部升級的成本,那麼企業選擇漸進式的遷移(如選項 3)還是采用快速修正的辦法?
全部重寫對企業來說是否負擔太重?
選項 1,即使用 2.0 全部重寫,對您的企業而言是否過於冒進?另一方面,是否有架構師要求層次清晰的樣式表設計?如果不能采用其他選項是否這是唯一的辦法?如果希望進行層次清晰的設計,可以把 2.0 的擴展特性集一並考慮進來。
關心跨 XSLT 處理程序的互操作性嗎?
事先要確定樣式表是否能用於多種處理程序,比如來自不同的廠商、在不同的平台上、甚至遵循不同 XSLT 版本的處理程序。
能找到支持向後兼容的 2.0 處理程序嗎?
如果在您的操作環境中不能使用支持 BC 的 2.0 處理程序,就不能選擇選項 2 和 3。此外,選項 4 也會受到更多限制,因為所有的 bug 修正都必須使用 2.0 的方法。
限制選擇的余地
上一節列出了每種方法的優缺點,供您權衡。下面的提示可能有助於排除一些選項。要采用這些快速排除法,需要知道最希望使用 2.0 中哪些具體的特性:
如果沒有支持向後兼容的 2.0 處理程序,就必須采用選項 1、5 或者選項 4 的一個子集,所有的 bug 修正必須采用 2.0 方式。
如果對模式感知、新的數據類型、選擇整理、增強的類型匹配或者操作名稱空間前綴有興趣,則首選選項 1 或者考慮選項 2。這是那些影響范圍最廣的特性。
如果對頻道參數、樣式表函數、XPath 中的 forExpr(FLWOR 的一個子集)、next-match 或者模式(mode)的改進感興趣,首選選項 1 和 2,選項 3 可能也夠了。在整個代碼庫中尋找使用這些特性的機會是不錯的做法,但這不是必需的。
如果對 ifExpr、rangeExpr、正則表達式函數和指令、臨時樹的改進、更好地控制輸出字符或者多重結果文檔感興趣,選項 3 可能就夠了。這些特性的影響范圍通常比較小。本系列的第 1 部分討論了後面的三種特性。
如果樣式表比較小或簡單,作為一種快速修改方法選項 4 可能就夠了。
如果主要希望使用分組、序列、限定表達式或者指定一個命名模板作為啟動模板的選項,單憑這些不能說明哪種選項更好。選項 1、2 和 3 都有可能,但需要進一步分析對樣式表的影響范圍是大是小。
結束語
回答了對企業的評估問題並審視 2.0 特性之後,可利用本文提出的決策因素制定升級的初步計劃。當然,這只是高層次的戰略分析,隨著計劃的深入還要重新審查這些問題。