XML的顯示——XSL樣式表單(zz)

 

XML文檔的一大特點是可以向多種格式的文檔進行轉換。比如,從一種邏輯結構的XML向另一種邏輯結構的XML轉換,或是轉換爲可瀏覽的HTML文檔等。這種XML文檔的數據格式轉換功能由可擴展樣式單語言(XSL)完成。

XML文檔轉換原理

數據格式轉換的重要思想是要把XML文檔視爲一種樹結構,轉換的過程就是從源樹生成結果樹的過程。XSL樣式單定義了源樹和結果樹中對應部分的轉換規則,每條規則中包含了一個模板,並對應着一種模式。模板定義了轉換的結果,而模式則規定了需要進行轉換的元素或屬性對象。

XML中引用XSL的語法格式如下:

<?xml-stylesheet type=“text/xsl” href=“Employees.xsl” ?>

如果在聲明部分引用了多個XSL樣式單,則只有第一個樣式單會生效,其餘的都會被忽略掉。

XSL的格式轉換功能在複雜的電子商務解決方案中大有用武之地。比如,A公司和B公司都是生產機器零件的廠家,在貨物清單中都包含了產品序列號以及質量等級評分。A公司的文件格式如下:

<Order>

<OrderItem>

<ItemID>12980-235</ItemID>

<Quantity>200</Quantity>

</OrderItem>

</Order>

而B公司的文件格式有所不同,相關信息都出現在元素的屬性中:

<Order>

<OrderLine PartNo=“12980-235” NumRequired=“200”/>

</Order>

這樣,雖然兩個公司的產品完全一樣,但由於文檔格式的差異給雙方的貿易往來設置了障礙。而使用XSL樣式單可以輕鬆地把A公司的文檔轉換成B公司的格式,反之亦然。

XML文檔轉換步驟

XML文檔的轉換過程分爲兩步:

● 首先是根據XML文檔構造源樹,然後根據XSL規則將源樹轉換爲結果樹。目前,這種轉換協議已經日趨完善,並從XSL中獨立出來,成爲W3C正式推薦的標準,稱爲XSLT(XSL Transformations);

● 生成結果樹後,就可以對其進行解釋,產生一種適合顯示、打印或是播放的格式,這一步稱爲格式化(Formatting)。

XSL處理器負責實現轉換過程。首先,XML文檔被解析成DOM樹存放在內存中,接着對文檔進行分析,每一個DOM樹中的節點都會與一個模式相比較,當二者匹配時,就會按照模板中定義的規則進行轉換,否則繼續往下匹配。如此循環,直至整個文檔處理完畢。

XSL文檔標準格式

XSL文檔的標準格式如下:

<xsl:stylesheet xmlns:xsl=“http://www.w3.org/TR/WD-xsl”>

template rule i

output template

</xsl:stylesheet>

XSL文檔本身是格式良好的XML文檔,所以在書寫時要注意標籤的匹配問題。<xsl:stylesheet>既是XSL的聲明語句,也是根元素,必須位於文件的首部。通常也要利用xmlns屬性指明XSL的名稱空間。樣式單中所有的模板規則都由標籤<xsl:temlplate>標明。模板規則可以說明處理的對象(元素/屬性)、處理的方式或是轉換的結果。此時,我們可以把該標籤類似地理解爲編程語言中函數的概念。

XSL的語法結構

XSL的邏輯語法結構包括循環和條件判斷。這兩種結構使用戶能夠靈活地書寫轉換規則。循環判斷是通過<xsl:for-each>元素實現的,它的可選屬性包括select和order-by。循環結構能夠遍歷整個結果集合,而不必針對每一條結果都單獨書寫轉換規則。它的標準語法格式爲:

<xsl:for-each select=“pattern” order-by=“patternlist”>

......

</xsl:for-each>

條件判斷結構分爲if語句和Case語句兩種形式。if語句是簡單地對條件進行判斷,結果爲真就執行條件內部的規則,因此可以把if條件與簡單的布爾表達式聯合使用。下面這個例子就是對薪水超過100萬元的職員輸出“Overpaid employee”信息:

<xsl:if match=“.[Salary $gt$ 1000000]”>

Overpaid employee

</xsl:if>

Case語句是對多種情況的分支判斷。該語句包括<xsl:choose>、<xsl:when>和<xsl:otherwise>三個元素。下面的例子是對薪水不足1萬元的職員輸出“No tax”,對超過5萬元的職員輸出“High tax rate”,對介於其間的職員輸出“Normal tax rate”信息:

<xsl:choose>

<xsl:when match=“.[Salary $lt$ 10000]”>

No tax </xsl:when>

<xsl:when match=“.[Salary $gt$ 50000]”>

High tax rate </xsl:when>

<xsl:otherwise> Normal tax rate </xsl:otherwise>

</xsl:choose>

XSL的模板規則

<xsl:template>標籤內的文本內容描述了轉換結果的形式,稱爲輸出模板。屬性match的取值把模板規則與指定的元素或屬性相比較,只有匹配的DOM節點纔會被處理,其餘的節點將被忽略。整個過程中最先匹配的是樹的根節點,根節點用“/”表示:

<xsl:template match=“/”>

output template for root element

</xsl:template>

然後匹配其他節點,此時,只要在引號中指明要處理的元素對象名稱即可。如果在引號中出現的是“*”,那麼表示該規則適用於所有的未單獨指定處理的元素節點。比如下例中的第二個模板就表示要處理除<Employee>元素之外的所有節點:

<xsl:template match=“Employee”>

output template

</xsl:template>

<xsl:template match=“*”>

output template

</xsl:template>

此外,XSL中還可以使用路徑指示符來指定一些特殊位置的元素與模板相匹配。“//”代表任意深度位置,如<xsl:template match=“//Employee”>用來匹配文檔中任何位置的<Employee>元素;而如果是<xsl:template match=“Employee//Name”>,則表明是匹配<Employee>元素的後繼節點中所有<Name>元素。另外一個路徑指示符是“/”,表示直接的父子節點關係。將剛纔例子中的“//”換爲“/”,就意味着匹配的是<Employee>元素子節點中的<Name>元素。

很顯然,某些樹節點在XSL中可能會對應多個模板,在這種情況下,只有最後一個對應模板會生效,前面的模板規則都會被XSL處理器忽略掉。

XSL模板的使用

XSL在輸出模板中描述輸出格式,這些格式可以是各種字符串、標籤符號、節點值或者是一些XSL語法結構,如條件判斷、循環處理等。在許多應用場合中,輸出模板中需要使用節點的取值,此時可以根據需要使用<xsl:value-of>元素輸出節點值,最直接的使用方式是<xsl:value-of />,這樣可以輸出當前節點及其所有後繼節點的取值。而如果僅僅是想輸出指定節點的取值,可以利用select屬性進行限定(select屬性可以是任意合法的路徑表達式):

<xsl:value-of select = “Name” />

<xsl:value-of select = “//Employee” />

上述第一個表達式匹配的對象是當前節點的所有子節點中名稱爲<Name>的元素,第二個表達式匹配的對象則是當前節點中所有後繼節點中名爲<Employee>的元素。注意: 在XSL樣式單中必須有一個模板規則與根元素相匹配。

在確定了模板規則與元素相匹配之後,就可以激活模板,這項任務由<xsl:apply-templates>元素完成。它和<xsl:templates>元素相結合就如同編程中的函數調用:前者是調用指令,而後者就是函數體。對於不同的元素需要調用不同的模板進行處理。爲了激活樣式單中的模板規則,要在根元素模板規則中使用<xsl:apply-templates>元素,這樣就會層層作用使整個樣式單文件生效:

<xsl:template match=“/”>

<xsl:apply-templates /></xsl:template>

直接使用<xsl:apply-templates>元素表示不加區分地對當前節點的所有子節點應用模板,而在select屬性中書寫匹配式則能夠限定作用對象:

<xsl:stylesheet xmlns:xsl=“http://www.w3.org/TR/WD-xsl”>

<xsl:template match=“/”>

<xsl:apply-templates select=“//Employee” />

</xsl:template>

<xsl:template match=“Employee”><P>

<xsl:apply-templates select=“Name” />

<xsl:apply-templates select=“Salary” />

</P></xsl:template>

<xsl:template match=“Name”>

<SPAN style=“font-size:36pt”>

<xsl:value-of /> </SPAN></xsl:template>

<xsl:template match=“Salary”>

<I><xsl:value-of /></I></xsl:template>

</xsl:stylesheet>

上述第一個模板與XML文檔的根元素相匹配,並對根節點以下的所有<Employee>元素應用模板規則。然後,一旦遇到<Employee>標籤,就插入一個<P>標籤作爲空白段落,接着對<Name>元素和<Salary>元素分別應用模板規則。最後,經過轉換顯示的結果是36磅字體的職員名字和用斜體字表示的職員薪水。

XSL的擴展規則

1. 路徑指示符

除了前面介紹的“//”和“/”路徑指示符,以及統配符“*”,還有幾個符號可以用來對模板的匹配對象進行限制:

● 當前節點指示符爲“.”;

● 父節點指示符爲“..”;

● 屬性指示符爲“@”。

上述“@”表示對指定元素中的某個屬性進行匹配,如<xsl:apply-templates select=“Employee/@ID” />語句表示對<Employee>元素中的<ID>屬性應用模板規則。

2. 過濾匹配符

除了路徑指示符之外,還可以對作用對象進行條件過濾或是排序,以進一步調整應用效果。過濾時,一般是以子元素(或屬性)是否存在(或其取值)爲標準:

● 子元素存在:即//Employee[Salary]存在,選擇含有<Salary>子元素的所有<Employee>元素;

● 子元素取值:即Employee[Salary > 25000],選擇含有<Salary>子元素,且Salary取值大於25000的所有<Employee>元素;

● 屬性存在: 即Employee[@ID]存在,選擇含有<ID>屬性的<Employee>元素;

● 屬性取值: 即Employee[@ID =“1234”],選擇所有屬性ID值爲1234的<Employee>元素。

3. 其他擴展過濾

其他的一些附加功能的過濾符,按功能分爲:比較操作符、布爾操作符和集合索引。

比較操作符的書寫格式和功能如下所示:

操作符 功能

$eq$ 等於

$ne$ 不等

$lt$ 小於

$le$ 小於或等於

$gt$ 大於

$ge$ 大於或等於

需要說明的是:表格中的操作符在比較字符時對大小寫是敏感的,如果要忽略大小寫的不同含義,在每個操作符前面加上前綴字母“i”即可,如“$ieq”。

布爾操作符書寫格式和功能說明如下:

操作符 功能

$and$ 邏輯與

$or$ 邏輯或

$not$ 取非

對過濾的結果可以通過集合索引進行再過濾。例如,Employee[Salary][2]就是選擇第2個含有<Salary>子元素的所有<Employee>元素。此外,XSL還提供了集合索引函數供用戶使用:index方法表示過濾結果的索引號,end方法表示最後一個過濾結果。使用方法如下所示:

Employee[index() $lt$ 2]

Employee[end()]

上述第一個表達式的選擇結果是<Employee>元素的第1和第2個子元素,第二個表達式的選擇結果是<Employee>元素的最後一個子元素。在缺省狀態下,模板規則對元素的匹配順序是按照節點在XML文檔中出現的前後次序排定的。但在特定的應用場合中,可能需要對原有的順序進行調整,此時需要使用order-by屬性。使用方法如下所示:

<xsl:apply-templates select=“//Employee” order-by=“+Name”/>

<xsl:apply-templates select=“//Employee”

order-by=“number(Salary)”/>

上述第一個例子表示應按姓名的字母升序排列,比如“Bob”應當排在“Tom”之前,而第二個例子則表示按照薪水的多少對職員進行排序。

發佈了75 篇原創文章 · 獲贊 1 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章