22 August 2005
中級
您可能會記得我以前的文章 XML 概觀, XML 是設計成攜帶資料。然而, 大部分的網路應用程式是專為使用者設計的。所以, 資訊應該要以易讀的格式呈現。這就是 XSL 派上用場的地方:從 XML 樹狀結構讀取資料, 處理之後產生成易懂的輸出。當然, 您可以使用 Perl、Java 或 PHP 自行轉換 XML 文件。可是當 XML 愈來愈成為主流, 您將必須更好地掌握 XSL 和它的運作原則。
很幸運的是 Dreamweaver 8 採用視覺化的方式處理 XSL 變形, 讓您不必親自寫程式碼處理 XML 資料。為了瞭解如何同時使用 XML 和 XSL 處理並顯示資訊, 這篇文章會回顧 XSL 和它的實際應用。我會介紹基礎的 XSL 語法規則、提供一些範例說明如何使用 XSL 改變資料的樣式, 以及解釋伺服器端變形和客戶端變形之間的差異。
XSL 之於 XML 就像 CSS 之於 HTML, XSL 代表的是「可擴展樣式表語言」(EXtensible Stylesheet Language), 這種語言是設計來用易讀的格式呈現 XML 資料。XSL 實際上包含兩個部分:
XSLT 代表「XSL 變形」(XSL Transformations), 這是 XSL 最重要的部分。
XSLT 把 XML 文件轉換成另一個 XML 文件、XHTML 輸出或是純文字。通常是把每個 XML 元素轉換成 HTML 元素。因為 XML 標籤是使用者自訂的, 瀏覽器不知道如何解譯或呈現每個標籤, 因此需要 XSL。XSL 的目的是要讓人類瞭解, 而不是機器。
XSLT 也可以對 XML 樹狀結構執行下列操作:
如果您需要 XML 語法的介紹, 請參閱我之前關於 XML 的文章裡面這一節 XML 語法。
您可能會記得 XML 概觀 這篇文章有提到, 所有 XML 文件的開頭是 XML 宣告。XSL 樣式表 (Style Sheet) 也是一樣的, 任何 XSL 文件的第一行其實就是 XML 宣告:
<?xml version="1.0" encoding="ISO-8859-1"?>
答案是肯定也是否定。是的, 因為它們有同樣的語法規則 (有一些差異, 之後會介紹)。否定的, 因為它們的目的不同:XML 攜帶資料, XSL 決定格式。
在 XML 宣告之後有一段 XSL 宣告, 例如:
<xsl:stylesheet>
或是
<xsl:transform>
然而, 真實世界的大部分案例, XSL 宣告看起來更複雜一點:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
這是因為根據全球資訊網聯盟 (W3C, W3 Consortium) 的建議, 它還要包括名稱空間和 XSL 規格的版本。
XML 宣告寫成單獨一行而且沒有結束標籤;XSL 不同, 它必須要有結束標籤, 標記 XSL 樣式表的末尾:
</xsl:stylesheet>
請注意這並沒有違反 XML 的語法規則:XSL 樣式表是完全正確的 XML 文件, 因為有單獨的根元素, 由 <xsl:stylesheet> 標籤指定。
XSL 的設計有幾個目標, 非常適合某些開發案例, 但是卻對其他的案例沒用。
XSL 如何融入更大的架構?如果要產生最後的 HTML 頁面給網站的訪客, 必須要把 XSL 樣式表套用在 XML 資料來源。實際的變形過程可以在網站伺服器或是客戶端的瀏覽器進行, 最後的輸出結果可以是完整的 HTML 頁面或只是一部分 (可以在個別頁面使用)。
伺服器端和客戶端的方式都有各自的優、缺點。伺服器端變形可以從您的伺服器或是網際網路上的其他地方處理 XML 文件, 伺服器執行真正的工作, 產生任何瀏覽器都能讀取的 HTML, 無論是舊的還是新的瀏覽器。另一方面, 要執行伺服器端的 XSL 變形, 必須要正確設定應用程式伺服器, 才可以支援 XML 和 XSL。並不是所有的代管伺服器都有準備, 這就是為什麼我要在之後的一篇文章, 解釋如何安裝和設定 PHP 伺服器需要的 XML/XSL 程式庫。即將發行的 Dreamweaver 8 有支援 ColdFusion、ASP、ASP.NET 和 PHP 頁面的 XSL 變形。
伺服器端變形的工作流程, 如下圖下所述:
請注意, XML 文件不一定要在網站伺服器上, 也可以放在遠端的網站, 需要的時候才下載到您的伺服器。
客戶端的變形, 是由客戶端的瀏覽器負責工作。這個方式的缺點在於, 並不是所有的瀏覽器都支援 XML/XSL, 所以有些客戶可能無法看到您的頁面。目前有支援 XML/XSL 功能的瀏覽器列表, 請見全球資訊網聯盟 (W3C) 網站的這一頁*。此外, 在使用客戶端的方式時, 會限制只能處理本地端 XML 檔案。例如, 如果需要讀取另一個網站的 RSS 反饋 (Feed), 必須要下載一份複本, 然後上傳到您的伺服器。如果原本在遠端網站的 RSS 有更動, 就必須再下載一次, 然後重新上傳到您的網站伺服器。
要通知瀏覽器必須使用哪個 XSL 樣式表處理 XML 文件, 必須要在 XML 檔案的 XML 宣告之後加入下面的宣告:
<?xml-stylesheet type="text/xsl" href="company.xsl"?>
href 屬性指定必須使用的 XSL 樣式表所在路徑。這個機制很像 HTML 頁面在開頭部分指定外部 CSS 樣式表的方式。下圖解釋 XSL 變形的客戶端工作流程:
我在之前曾提到, XSL 宣告也帶有文件的名稱空間。名稱空間就字面上而言:是名稱的空間。名稱空間指定元素名稱和屬性名稱的集合, 讓您可以在某個文件中使用。名稱空間的目標是避免名稱衝突, 因為 XML 和其他 XML 相關的語言是使用者自訂的, 可能會有名稱衝突。例如, <table> 可能指的是資料庫的表格、版面表格、傢俱或是餐廳中的位置。因為大部分的應用程式一次處理一個以上的 XML 文件, 混合不同的 XML 文件並不罕見, 文件之中的某個元素可以有不同的意義。在多份文件之間使用相同的名稱空間, 可以確保這個元素在這些文件中表示同樣的事情。反之, 使用不同的名稱空間, 可以確保元素有不同的意義。
在 XML 中, 名稱空間是由文件宣告的 xmlns 屬性指定, 是由統一資源識別元 (URI, Uniform Resource Identifier) 組成, 也就是網站的位址 (例如 http://www.w3.org/1999/XSL/Transform)。背後的理由是 URI 是唯一的, 所以對應的名稱空間很可能也是唯一的。
注意: 文件宣告的 URI 只是當成名稱使用, 而非代表指向任何 XML 資料結構檔的連結、或是代表文件的擁有者 (產出這份文件的公司或網站)。
現在您大概知道什麼是名稱空間了, 讓我們回頭介紹 XSL 語法。就像 XML 文件是由元素的階層集合組成, XSL 文件是由樣版或規則組成。每個樣版定義特定 XML 節點套用的規則, XSL 樣版看起來就像:
<xsl:template match="">
</xsl:template>
XSL 樣版的 match 屬性關聯一個 XML 元素, 對應的節點由 XPath 運算式指定。我會在下一節介紹 XPath。
XSL 使用 XPath 指定 XML 樹狀結構中需要處理的元素。簡單地說, XPath 是瀏覽工具, 可以指定 XML 元素的位置。XPath 使用的語法和作業系統的檔案系統路徑一樣(例如, C:\Program Files\Macromedia\ 或 /usr/bin/perl), 同樣的, company/department/employee 就是 XPath 運算式, 指向包含公司和部門資料的 XML 文件內的員工元素。Dreamweaver 8 提供視覺化的拖放使用者介面, 替您產生 XPath 陳述式, 但您還是應該瞭解 XPath 的基本原則, 才能從 XSL 樣式表內處理 XML 資料。
基本上, XPath 規格和檔案系統定址的規則一樣:
//employee 會查詢 XML 文件內所有的 employee 節點。/company/department/* 會選取一個部門的所有子節點, 也就是所有的員工。../employee。@ 字元。例如, /company/department/employee[@retired] 會選取所有指定 retired 屬性的員工。<xsl:template> 元素的內容是必須要套用的規則, 通常是一些要輸出給瀏覽器的 HTML 碼。
還記得我之前文章的 company.xml 文件嗎?假定您需要套用規則到員工節點, 用表格顯示員工資料如下:
XSL 規則看起來會像這樣:
<xsl:template match="/">
<table border="1">
<tr>
<th>Name</th>
<th>Job</th>
<th>Salary</th>
</tr>
</table>
</xsl:template>
請注意, table 標籤之間的內容是純 HTML 碼, 告訴瀏覽器, 這些員工要以表格顯示, 有下列的欄標題:姓名 (Name)、工作 (Job) 和薪資 (Salary)。
<xsl:template> 定義節點在瀏覽器中的外觀。可是, 如果要顯示節點真正的內容, 需要使用另一種 XSL 架構:<xsl:value-of>。它的名稱十分符合直覺, 要顯示節點的值是由 select 屬性指定, 把數值當成 XPath 運算式。假定您要從 company.xml 文件顯示一個員工的姓名, 程式碼看起來會像這樣:
<xsl:value-of select="/company/department/employee/name"/>
再回到先前的範例, 把 company.xml 文件顯示成表格。如果要在定義的 XSL 樣版顯示 <name>、<job> 和 <salary> 節點的值, 需要寫出下列的程式碼:
<xsl:template match="/">
<table boder="1">
<tr>
<th>Name</th>
<th>Job</th>
<th>Salary</th>
</tr>
<tr>
<td><xsl:value-of select="company/department/employee/name"/></td>
<td><xsl:value-of select="company/department/employee/job"/></td>
<td><xsl:value-of select="company/department/employee/salary"/></td>
</tr>
</table>
</xsl:template>
如果要在瀏覽器中看到這段程式碼運作的結果, 請遵照下列步驟:
<?xml version="1.0" encoding="iso-8859-1"?><?xml-stylesheet type="text/xsl" href="ex_01.xsl"?>
注意: 本文前面的客戶端變形一節, 曾經說明這段程式碼的用途, 通知瀏覽器要使用哪個 XSL 樣式表來處理 XML 文件。href 屬性指定必須使用的 XSL 樣式表所在路徑。
如果要在表格內顯示所有的員工, 必須使用另一種常用的 XSL 架構:
<xsl:for-each select=""> </xsl:for-each>
select 屬性的值是 XPath 運算式, 指定要顯示的節點集合。如果您熟悉其他的程式語言, <xsl:for-each> 架構的作用就像典型的 for 迴圈。
顯示公司的所有員工:
<xsl:template match="/">
<table border="1">
<tr>
<th>Name</th>
<th>Job</th>
<th>Salary</th>
</tr>
<xsl:for-each select="company/department/employee">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="job"/></td>
<td><xsl:value-of select="salary"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
請注意, Name (姓名)、Job (工作) 和 Salary (薪資) 的 XPath 運算式不需要包含父節點, 也不需要從文件根目錄開始。這是因為這些元素的路徑是根據 <xsl:for-each> 架構中指定的 XPath 運算式來計算的。如果要在瀏覽器中看到這段程式碼運作的結果, 請再次開啟 company.xml 檔案, 把 href 屬性的值改成 ex_02.xsl。然後在瀏覽器中預覽。應該可以看到下面的 HTML 表格:
XSL 可以讓您篩選、排序項目, 也可以根據條件顯示內容。
使用 <xsl:for-each> 架構的話, 也可以根據條件篩選輸出的內容。假定您想要只顯示當程式設計師的員工。
<xsl:template match="/">
<table border="1">
<tr>
<th>Name</th>
<th>Job</th>
<th>Salary</th>
</tr>
<xsl:for-each select="company/department/employee[job='Programmer']">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="job"/></td>
<td><xsl:value-of select="salary"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
如果要在瀏覽器中看到這段程式碼運作的結果, 請再次開啟 company.xml 檔案, 把 href 屬性的值改成 ex_03.xsl。然後在瀏覽器中預覽。請注意, company.xml 文件內的員工, 只有程式設計師才會列在 HTML 表格:
如果要定義 XML 節點的條件, 可以使用下列的運算子:
也可以按照字母順序排列項目, 只要使用 <xsl:sort /> 架構, 指定排序的節點。<xsl:sort /> 元素必須位在 <xsl:for-each> 元素之內, 確保程式會經過所有的元素。如果要根據字母順序顯示員工:
<xsl:template match="/">
<table border="1">
<tr>
<th>Name</th>
<th>Job</th>
<th>Salary</th>
</tr>
<xsl:for-each select="company/department/employee">
<xsl:sort select="name" />
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="job"/></td>
<td><xsl:value-of select="salary"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
請注意, 排序的元素不一定要有對應的結束標籤。如果要在瀏覽器中看到這段程式碼運作的結果, 請再次開啟 company.xml 檔案, 把 href 屬性的值改成 ex_04.xsl。然後在瀏覽器中預覽。請注意, company.xml 文件的所有員工在 HTML 表格內是根據字母順序排序:
當然, 您也可以輕鬆地切換遞增和遞減順序, 只要在 <xsl:sort /> 元素增加額外的屬性:
<xsl:sort select="/name" order="descending"/>
請注意, 上面的 XSL 程式碼沒有修改原始 XML 文件內的實際結構。只有在 XSL 變形後所產生給 瀏覽器的 HTML 中, 才會將員工按照字母順序排列。
就像大部分的語言一樣, XSL 可以根據條件顯示內容。
使用下列的語法可以定義簡單的條件:
<xsl:if test="expression">
</xsl:if>
如果要對多個項目執行這個條件測試, 只顯示滿足條件的節點, xsl:if 架構必須放在 xsl:for-each 元素之內。下面的範例展示如何僅列出薪資高於 $2700 的員工:
<xsl:template match="/">
<table border="1">
<tr>
<th>Name</th>
<th>Job</th>
<th>Salary</th>
</tr>
<xsl:for-each select="company/department/employee">
<xsl:if test="salary > 2700">
<tr>
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="job"/></td>
<td><xsl:value-of select="salary"/></td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>
請注意, 小於 (<) 和大於 (>) 字元要替換成對應的 HTML 逸出序列 (< 和 >), 否則很容易會和標籤的開始和結束搞混。如果要在瀏覽器中看到這段程式碼運作的結果, 請再次開啟 company.xml 檔案, 把 href 屬性的值改成 ex_05.xsl。然後在瀏覽器中預覽。請注意, 只有 company.xml 文件內的員工, 並且薪資高於 $2700, 才會出現在這個 HTML 表格中:
在測試運算式中使用的運算子是典型的條件運算子:
需要比較數值和字串的時候, 必須把字串放在單引號內 (例如, <xsl:if test="job = 'Software Analyst'">)。
也可以定義更複雜的條件, 就像大部分程式語言中的 IF-ELSE 架構。這個語法不需要解釋:
<xsl:choose>
<xsl:when test="expression">
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
如果要對多個 XML 節點測試條件的話, <xsl:choose> 架構必須放在 <xsl:for-each> 迴圈之內。
假定您想要把所有薪資低於 $2700 的員工標示成綠色、薪資高於 $2700 的標示成藍色:
<xsl:template match="/">
<table border="1">
<tr>
<th>Name</th>
<th>Job</th>
<th>Salary</th>
</tr>
<xsl:for-each select="company/department/employee">
<xsl:choose>
<xsl:when test="salary > 2700">
<tr bgcolor="#66CCFF">
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="job"/></td>
<td><xsl:value-of select="salary"/></td>
</tr>
</xsl:when>
<xsl:otherwise>
<tr bgcolor="#00CC99">
<td><xsl:value-of select="name"/></td>
<td><xsl:value-of select="job"/></td>
<td><xsl:value-of select="salary"/></td>
</tr>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</table>
</xsl:template>
如果 XML 節點不能滿足第一個測試條件, 預設會套用 <xsl:otherwise> 元素指定的規則。
如果要在瀏覽器中看到這段程式碼運作的結果, 請再次開啟 company.xml 檔案, 把 href 屬性的值改成 ex_06.xsl。然後在瀏覽器中預覽。應該可以看到下面的 HTML 表格:
請注意, 所有薪資低於 $2700 的員工標示成綠色、薪資高於 $2700 的員工標示成藍色。
<xsl:choose> 架構很容易就可以擴充成測試多個條件, 只要增加一個或多個 <xsl:when> 元素。無論會有多少個 <xsl:when> 元素, 一定只會有一個 <xsl:otherwise> 元素, 處理初始測試條件沒有包括的所有案例。讓您牛刀小試一下, 請使用下面的標記顯示員工列表:
Dreamweaver 8 可以讓程式寫得更快更容易的新功能之一, 就是程式碼提示。當您開始輸入 <xsl:Dreamweaver 會顯示一個列表, 建議可以完成輸入的選項:
選取想要的節點或是函式, 然後按 Enter (Windows) 或 Return (Macintosh)。可以使用方向鍵捲動建議列表, 程式碼提示有助於在編寫程式碼時不會出錯。
在這篇文章中, 簡短地介紹了 XSL, 提供一些準則讓您知道在網頁開發專案如何使用 XSL。這篇文章也包含一些 Dreamweaver 8 XML 編寫功能的預覽, 您會發現在開發 XML 應用程式時, 它是件很有用的工具。請盡情地探索 XML 和 XSL 能夠提供的可能性。
在接下來的兩篇文章中, 我會介紹如何使用 Dreamweaver 8, 在您的網站讀取 RSS 反饋 (Feed), 還有如何設定伺服器以執行伺服器端的 XSL 變形。Dreamweaver 8 已經開始預購了。如果您透過 Macromedia Affiliate Program from InterAKT Online* 訂購, 您還可以得到免費的 ImpAKT*。
Tutorials and samples |
Dreamweaver user forum |
More |
| 02/09/2012 | How to Remove White Space? |
|---|---|
| 09/10/2010 | How to disable some HTML and CSS property's |
| 02/10/2012 |
Difficult to place tag... Please help!
|
| 02/10/2012 | Photo Gallery for mobile devices |
Dreamweaver Cookbook |
More |