XML+XSL也是近幾年大家才開始關注的數據與表示分離的的方式,在國外已經有了不錯的應用,但在國內可能應用的范圍還不是很廣泛。就我自己來看,最早看到的此類應用當然是CSDN的論壇貼子顯示頁面了。可能大多數朋友都和我一樣,第一次看到以.XML後綴名結尾的頁面顯示時更多的好奇,在查看頁面源碼時看到的只是一個一個包含著數據的標簽,怎麼回事呢?當然現在這些都已不再神奇,大家都知道這是XSL的作用。
為什麼要用XML來保存數據呢?數據庫不是更好嗎?呵呵,我們自己的做的小頁面估計不會超過一百個人同時浏覽,但是CSDN就不一樣了啊。沒有哪個程序員不知道CSDN的吧,成千上萬的人都去訪問,他的數據庫再厲害估計也是夠嗆啊。用XML其實就是提供了一個類靜態頁面的方式,因為我們去打開它的頁面時,鏈接地址是個XML文件,浏覽器會先吧XML文件Down下來,然後根據文件中提供的XSL的地址找到XSL然後進行解析再將解析生成的頁面展現給我們。在CSDN上有人戲稱,這樣做是為大多數潛水愛好者准備的,不無道理啊。
很多人都想知道xsl怎樣去構造一個那樣美妙的東西,其實一切都不困難。你只要掌握了XSLT的部分功能和一些Html的知識就可以了。你知道一些MSXMLDOM的知識?那就更好了,讓我們一步一步的把CSDN的頁面剖開來看看。你不是懂很多?也不要緊,這是初學者們學習的好東東哦,只用最基礎的語法結構就能搭建起來。你知道<xsl:
value-of select="..."/>吧,你也了解xsl:template和xsl:call-template吧,行了,足夠了。讓我們來
把CSDN的XML頁面來動手實現吧!
CSDN的論壇頁面我把它分為三個部分,問題主題、回復顯示和提交回復。用xslt解析的只是前兩部分,那麼第三部分是什麼呢?呵呵,暫不是我們討論的重點。下面我們看一下CSDN存放貼子內容的一個XML文件的事例:
<?XML version="1.0" encoding="GB2312"?>
<?XML-stylesheet type='text/xsl' href='Topic.xsl'?>
<Topic>
<Issue>
<PostUserNickName>隨風</PostUserNickName>
<rank>1</rank>
<ranknum>user1</ranknum>
<credit>100</credit>
<TopicId>3420145</TopicId>
<TopicName>在線等待XML問題(服務端接收)</TopicName>
<PostUserId>449974</PostUserId>
<PostUserName>mazying99</PostUserName>
<RoomName>Web服務 XML/SOAP</RoomName>
<ReplyNum>2</ReplyNum>
<PostDateTime>2004-9-29 23:55:18</PostDateTime>
<Point>50</Point>
<ReadNum>6</ReadNum>
<RoomId>306</RoomId>
<EndState>0</EndState>
<Content><![CDATA[.....]]></Content>
</Issue>
<Replys>
<Reply>
<PostUserNickName>坐行八萬裡</PostUserNickName>
<rank>1</rank>
<ranknum>user1</ranknum>
<credit>100</credit>
<ReplyID>24484920</ReplyID>
<TopicID>3420145</TopicID>
<PostUserId>40078</PostUserId>
<PostUserName>guiqing</PostUserName>
<Point>0</Point>
<Content><![CDATA[.....]]></Content>
<PostDateTime>2004-9-30 7:52:03</PostDateTime>
</Reply>
</Replys>
</Topic>
當然我把主題和回復內容給省略了,大家可以看到Topic是整個XML文件的主節點,其下有兩個孩子節點:Issue和Replys。
OK,顯而易見Issue存放的是提出的問題和作者以及時間等相關信息;Replys存放著一個個的回復。
首先我們先分析一下Issue節點,多數節點不用解釋都一目了然。這裡需要注意的是<rannum/>節點。user1的user是指等級較低的也就是大家看到的三角符號(數字標明了幾個符號),如果等級高的話就是star1也就是一顆五角星。為什麼存放著有表示等級的<rank/>又在<ranknum/>中最後一位也用數字標等級?可能是因為在數據庫中還有者相關信息吧。其實仔細分析大家就可以發現,那些三角、五角星都是一張張圖片,OK!它們文件名是什麼呢?就是<ranknum/>的Text值加上後綴.gif。呵呵,比如顯示一個三角的圖片就是user1.gif。這樣在用xslt解析時,就能夠直接提供給圖片信息,豈不是一舉兩得。Content節點用CDATA來存放就不用多說了。
我們來看看發布主題部分的實現:
開頭:
<?XML version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" XMLns:xsl="
http://www.w3.org/1999/XSL/Transform" XMLns:fo="' target=_blank>
http://www.w3.org/1999/XSL/Format"> 我是用的是XMLSpy,生成的是.xsl文件,所以就給多加了一個fo的名稱空間,我們不管它。因為我們要生成的是html文件,(注意:XML+XSL生成的頁面默認的是UTF的編碼),如果要指定編碼格式,我們應該緊接著寫上一句:<xsl:output method="html" encoding="GB2312"/>。因為解析時默認情況是生成XML或Html,所以也可以指定生成的文件類型。
我們繼續:
<xsl:template match="Topic">
<Html>
<link rel="stylesheet" href="topic.Css" type="text/CSS"/>
<xsl:apply-templates select="Issue"/>
<xsl:apply-templates select="Replys"/>
<xsl:call-template name="SetReplyFrame"/>
</Html>
</xsl:template>
這個就是我們的Main函數,入口就在這裡了。為什麼不用match="/"呢,因為我們主要就是顧著Topic這個節點,其余的根本不需要去管它。match="/"並沒有匹配Topic,這點要注意!
為了讓我們的網頁好看些,當然要用上CSS樣式表的喽(我的審美觀很差的啦)呵呵。直接使用<link rel="stylesheet" href="topic.css" type="text/CSS"/>在解析過程中會直接將該條語句輸出到html頁面,這也就是我們為什麼可以使用Html的標簽。
<xsl:apply-templates select="Issue"/>這句標明對於Issue可以去匹配已有可用的模版。這裡有的人就有疑問了,以前你不是說apply-templates只是匹配子節點嗎?這裡怎麼又成了Issue一個了啊。是的,如果在xsl:apply-templates中沒有使用select屬性,那麼就是匹配當前節點下的所有孩子節點,但是如果使用了select那麼就是處理所選取得節點。