前段時間無意間看到一個博客的RSS可以用XSL格式輸出並且能在Firefox裡浏覽,想到自己以前寫的一個XML留言簿因為不兼容Firefox所不了了之了,現在看到他的能在Firefox浏覽就覺得很好奇,看了一下代碼,一句一句的比對,最後終於找到了原因,也就把這個留言簿給完成了。因為是一個簡單的XML留言簿,所以取名SXGB(Simple XML GuestBook)。
留言本演示,管理密碼為test:http://home.goofar.com/hotheart/gbook/gbook.asp
首先定義留言簿的XML文檔的格式。作為一個留言簿,不需要太復雜的內容,於是我就給留言內容分為3個部分:留言者姓名、留言者主頁和留言內容。另外,一個留言簿還需要有使用者的一些信息,包括用戶名和用戶主頁。再有,在留言比較多時還需要分頁信息。大致結構完成後就可以開始寫XML文檔模板了。
XML文檔根元素定義為gbook
XML文檔模板gbook.xml
CODE:
xml version="1.0" encoding="utf-8"?>
<!-- DTD file -->
<!DOCTYPE gbook SYSTEM "sxgb.dtd">
<!-- XSL file -->
<?xml-stylesheet type="text/xsl" href="gbook.xsl"?>
<gbook>
<!-- 留言簿相關信息 -->
<info>
<!-- 用戶名 -->
<user>HotHeart</user>
<!-- 用戶主頁 -->
<home>http://www.xujiwei.cn</home>
<!-- 分頁信息,分別為目前所在頁,總頁數,上一頁,下一頁 -->
<pagenow>1</pagenow>
<pagetotal>1</pagetotal>
<pageprev>1</pageprev>
<pagenext>2</pagenext>
<!-- 是否已經登陸,用來處理是否顯示登陸框 -->
<logined>NO</logined>
</info>
<!-- 留言列表 -->
<messages>
<!-- 一個留言 -->
<message>
<!-- 留言ID -->
<id>1</id>
<!-- 留言者姓名 -->
<username>Admin</username>
<!-- 留言時間 -->
<time>2005-08-09 12:00</time>
<!-- 留言者主頁 -->
<homepage>http://www.xujiwei.cn/</homepage>
<!-- 留言內容 -->
<content><![CDATA[ 留言內容 ]]></content>
</message>
</messages>
</gbook>
要注意在引用XSL時不能用
<?xml:stylesheet type="text/xsl" href="gbook.xsl"?>
xml和stylesheet之間應該用一槓(-)而不能用冒號(:),在Firefox裡是不支持用冒號的。
一個好的XML文檔,除了要有結構性,還應該要有有效性,所以在XML文檔的一開頭就定義了文檔類型定義(DTD) sxgb.dtd,下面就來把這個文檔類型定義給完成。因為已經設計好留言簿XML文檔的結構,所以寫出DTD是很方便的。
文檔類型定義sxgb.dtd
CODE:
<?xml version="1.0" encoding="utf-8"?>
<!ELEMENT gbook (info,messages)>
<!ELEMENT info (user,home,msgtotal,pagenow,pagetotal,pageprev,pagenext,logined)>
<!ELEMENT messages (message+)>
<!ELEMENT message (id,username,time,homepage,content)>
<!ELEMENT user (#PCDATA)>
<!ELEMENT home (#PCDATA)>
<!ELEMENT msgtotal (#PCDATA)>
<!ELEMENT pagenow (#PCDATA)>
<!ELEMENT pagetotal (#PCDATA)>
<!ELEMENT pageprev (#PCDATA)>
<!ELEMENT pagenext (#PCDATA)>
<!ELEMENT logined (#PCDATA)>
<!ELEMENT id (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT username (#PCDATA)>
<!ELEMENT time (#PCDATA)>
<!ELEMENT homepage (#PCDATA)>
<!ELEMENT content (#PCDATA)>
<!ELEMENT messages (message+)>中+號表示留言列表中至少有一條留言,但實際應用可能會出現沒有留言的情況,為了應對這種情況,我在輸出XML文檔的ASP程序輸出一條系統產生的留言,提示目前還沒有留言。
接下來是很重要的部分,XSL的編寫了。
XSL文檔gbook.xsl
點擊這裡查看XSL文檔gbook.xsl
在定義XSL名稱空間時,應該用http://www.w3.org/1999/XSL/Transform,即
CODE:
xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
而不能用http://www.w3.org/TR/WD-xsl,不知為什麼如果使用這個名稱空間,在Firefox會顯示錯誤:分析 XSLT 樣式表單失敗。
在XSL裡,一個很重要的概念就是模板。一個模板就對應一塊內容的格式化輸出,在構建模板時,可以從大到小,即先構建全局的模板,然後再處理每一塊細分的內容,也可以從小到大,先構建好細分內容的模板,然後將它們組合起來形成整體的模板。在XSL裡,創建一個模板使用下面的標記:
[code[<xsl:template match="/gbook">
<!-- 模板內容 -->
</xsl:template>[/code]
其中match表示的是這個模板對應那個標記。
使用模板有兩種方法:
第一種是直接應用:
CODE:
<xsl:apply-templates select="info"/>
這種方法是選擇當前標記下的info標記並使用match為info的模板進行處理
第二種是循環選擇:
CODE:
<xsl:for-each select="message">
<!-- 模板內容 -->
</xsl:for-eace>
在循環選擇中,模板直接寫在for-each之中,但是當前上下文已經轉到message。
至於在select中使用的表達式,屬於XPath部分,可以參考W3C的XPath文檔(XML Path Language) 。在gbook.xsl中還使用到的標記有:
<xsl:value-of select="content"/>
這是在XSL中常用的標記之一,輸出結果是選擇節點的值,通過用它來輸出節點的值,在這個留言本中,它用來輸出用戶名、留言者姓名、留言內容等。
<xsl:attribute name="href">gbook.asp?page=1</xsl:attribute>
用來給當前標簽添加一個屬性,在留言簿中用來給分頁導航添加網址。其中name]屬性表示要添加屬性的名字,標記包含的內容為要添加屬性的值。
<xsl:if test="id!=''"><!-- 處理內容 --></xsl:if>
判斷test中的表達示結果,如果為真則處理包含的內容,假則忽略。要注意是,如果是判斷小於,就不能用“<”,而應該用“<”,因為“<”是標簽起始標志,如果不進行轉換則在浏覽器中會出現錯誤。
然後就是ASP輸出留言簿需要的XML文檔了,這個只要按照前面定義的格式,從數據庫中讀取記錄按照模板輸出即可,不過需要在輸出之前定義MIME類型:
Response.ContentType="application/xml"
指明這是一個XML文檔。另外,因為整個留言簿都使用的UTF-8編碼,需要在ASP中指定編碼:
CodePage="65001"
這句應該放在ASP文件的開頭。
最後還有CSS,這個屬於定義留言簿的顯示效果了,具體可以查看CSS的內容。另外,為了防止用戶誤操作提交了空表單,我在客戶端加了一段JS代碼來檢查留言姓名和留言內容是否為空,如果為空則提示用戶並停止提交表單,具體內容可以查看JS腳本文件。
完整留言簿系統SXGB打包下載
參考資料:
1. XML及WAP開發手冊(李建國等編著)
2. xml ,xsl,css 之亂搞