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=_blankhttp://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那么就是处理所选取得节点。