簡介
當聽到樣式表這個詞時,您可能會想到 CSS 樣式表。XSLT 樣式表通常用於 XML 轉換,比如在 Web 服務之間映射數據。因為 XSLT 非常適合此用途,所以創建了頂層元素 <stylesheet> 的 <xsl:transform> 別名,雖然這很少使用。這種 XSLT 轉換的輸入結構與輸出結構有很大的不同。最重要的是,命名空間的不同。
XSLT 樣式表的輸入結構與輸出結構相似,但卻更簡單些。其中已經擴充了一些標記,但大部分標記只是原樣復制到輸出。輸入和輸出的命名空間是相同的 (Html)。輸入文檔也可以包含樣式表指令(比如創建腳注),這些指令屬於另一個命名空間,不會傳遞到輸出中。
常用縮略語
CSS:級聯樣式表
XHtml:可擴展超文本標記語言
XPath:XML 路徑語言
XSLT:可擴展樣式表語言轉換
在本文中,我們將學習如何使用 XSLT 樣式表擴充 XHtml 文檔。文中的示例展示了如何使用指令,如何引用其他源文檔的部分,以及如何使用鏈接在主文檔中導航。此外,我們還探索了頁面的解釋和編譯之間的區別。
CSS 樣式表的局限性
XSLT 樣式表不會阻止您使用其他技術,比如 JavaScript 或 CSS。CSS 適用於字體、加粗、顏色、間距等。它不適合將來自不同位置的信息組合在一起,比如腳注、模塊或生成一個目錄。這正是 XSLT 的用武之地,它補充而不是替代了 CSS。
XSLT 用途示例
實際上,您可以將 XSLT 代碼集中在一個文件中。為了簡單起見,本文中的每個示例均位於一個獨立的 XSLT 文件中,除了一些必要的代碼。清單 1 給出了必需的代碼。
清單 1. 必需的代碼(位於 samples/common.XML 中)
XHTML 的命名空間定義了兩次:默認定義和 h:。默認命名空間用於編寫輸出 XHtml 標記,其中應該避免使用命名空間前綴。h: 用在 XPath 表達式中。
本文使用 XSLT 1.0 版本。目前,大部分浏覽器都無法解釋 XSLT 2.0。但是,如果 XSLT 運行在服務器上,那麼它可能是一個實用的選擇。XSLT 2.0 還提供了:
XPATH 2.0(if…then…else 和許多內置的函數)
內置和用戶編寫的 XPATH 函數
分組
在 清單 1 中:
s:template match="head" 擴充了源文檔的 head 一節,添加了一個 CSS 樣式表的鏈接。即使 UTF-8 是在 XML 中的默認編碼,一些浏覽器也需要內容類型才能呈現它。
s:template match="*" 是默認的詳細副本。原則上,所有內容都會復制到目標文檔中。如果遺漏了此模板,只會將標記的文本內容復制到目標文檔。不會復制處理指令節點。
本文中的所有其他示例都是導入 common.xsl 的獨立文件。
擴充
通過擴充,添加了一個未在源文檔中顯式請求的特性。一個示例是 清單 1 中的 CSS 樣式表的鏈接。嘗試另一個示例,向每個內部鏈接添加一個小箭頭 (^ v),指明目標在它之前還是之後。清單 2 給出了該樣式表。
清單 2. 樣式表(在 samples/linkUpDown.xsl 中)
首先,導入清單 2 中的通用樣式表。模板與內部鏈接(以 '#' 開頭)相匹配。如果鏈接指向的錨點位於鏈接之前,那麼使用一個向上箭頭擴充該鏈接(如果情況相反,則使用向下箭頭)。
s:copy-of 和 s:apply-templates 可確保不會沿途丟下任何內容。
清單 3 給出了一個示例文檔(其中包含內部鏈接),它經過了清單 2 中的樣式表進行擴充。
清單 3. 源文檔(在 samples/linkUpDown.XML 中)
目標文檔看起來相同,除了清單 4 中的條目。
清單 4. 目標文檔(在 samples/linkUpDown.Html 中)
指令
您可以在源文檔中添加一些指令,告訴樣式表執行何種操作。它們屬於另一個命名空間(在本例中為前綴 a:),不會被復制到目標文檔。
在清單 5 中,源文檔中任何地方的指令標記 a:ref 都會創建一個腳注。
清單 5. 樣式表(在 samples/footnote.xsl 中)
使用源文檔中的 a:references 指令,名為 references 的模板會在模板與該指令匹配的地方分配腳注。如果缺少這樣一個指令,第一個與 body 匹配的模板會在 body 的末尾分配腳注,方法是調用名為 references 的相同模板。在兩種情況下,都會列出腳注的內容,並生成一個由向上箭頭表示的向上鏈接。
第二個模板(匹配 a:ref)使用向下箭頭創建腳注的鏈接。腳注具有編號。這裡忽略了它的內容。
class="footnote" 屬性在 XSLT 轉換之後由一個 CSS 樣式表解析,該樣式表鏈接在 XSLT 樣式表 common.xsl 中。
清單 6 中的源文檔使用 a:ref 指令創建腳注。
清單 6. 源文檔(在 samples/footnote.XML 中)
目標文檔將腳注列表包含在底部,如清單 7 所示。
清單 7. 目標文檔(在 samples/footnote.Html 中)
突破源文檔的邊界
也可引用其他源文檔的其中一些部分。a:include 指令包含一個可能屬於另一個源文檔的元素並轉換它,如清單 8 所示。
清單 8. 樣式表(在 samples/include.xsl 中)
源文檔中的一個 a:include 指令引用源元素的 id。包含該元素的文檔可在一個 src 屬性中命名。如果缺少該屬性,將使用 a:default 指令的 src 屬性。如果在任何地方都沒有 src 屬性,則使用同一個源文檔。因此,refid 會引用 id 來避免無限的遞歸。
導入的元素可能具有一種復雜的類型,並在包含 (apply-templates)之後進行轉換。清單 9、清單 10 和清單 11 給出了示例。
清單 9. 源文檔(在 samples/include.XML 中)
清單 10. 源文檔的部分(在 samples/includeY.XML 中)
清單 11. 目標文檔(在 samples/include.Html 中)
主文檔和導航
如果您有一個包含多個頁面的演示,有一個主文檔包含頁面標題及其鏈接。您可以生成完整的導航,從每個頁面到任何其他頁面,以及到前一個和後一個頁面。這些細節不屬於本文的介紹范圍,但 參考資料 中提供了使用主文檔的 HTML 演示的鏈接。可將 .XML 替換為 .Html 來獲得編譯後的版本。讓浏覽器向您顯示 .XML 的整潔源代碼。您會對它生成的源代碼量感到驚奇。
解釋與編譯的對比
解釋意味著頁面為 XML 格式(其文件擴展名為 .xml,其內容類型為文本/xml 或應用程序/XML),並且處理指令所引用的 XSLT 樣式表可在浏覽器中執行。
編譯意味著浏覽器看到的是 HTML(其文件擴展名為 .html,內容類型為文本/Html),它是在請求頁面之前從您的開發環境中或服務器上的 XML 轉換而來的。Xalan 和 Saxon 都是著名的 XSLT 處理器。
解釋是未來的發展方向。所有現代浏覽器都支持 XSLT,並且它具有一些優點:
當測試時,您會立即獲得結果。只需在您測試的每個浏覽器中按下 F5,即可反映源頁面、CSS 和 XSLT 樣式表的更改。
要傳遞給客戶端的信息量減少了。
客戶端看到的是一個干淨、整潔的網頁,因為還未生成擴充內容。
但也要注意一些缺點:
有一些舊浏覽器可能不支持 XSLT。如果向一個受控的環境(內部網)發布頁面,就不會出現問題。
一些現代浏覽器禁止 XSLT 樣式表引用另一個目錄中的另一個樣式表。
將 XSLT 域其他功能相結合(比如 SVG 或 iframe)可能在一些浏覽器中導致問題。
因為大部分浏覽器都不支持 XSLT 2.0 或即將推出的 3.0,所以您無法使用新功能。沒有 XPath 2.0 if () then … else,也沒有用戶編寫的 XPath 功能。
無論進行編譯還是解釋,頁面的其他轉換 (CSS、JavaScript) 都會在 XSLT 轉換之後執行。
結束語
在本文中,您學習了如何使用 XSLT 樣式表來擴充 XHtml 文檔。您可以使用本文中的示例作為起點,構建您自己的 XSLT 樣式表。
文章和XML示例