|
神奇的XML--突破CGI权限的约束 |
来源:yesky 人气:1671 录入时间:2007-11-8 |
免费存放个人主页的网站很多,可是向普通网友提供CGI权限的却很少;要么就是要求太高,绝大部分都很难达到。XML(可扩展标记语言)的出现,虽然不是以解决上述问题为目的,却给我们提供了一条很好的不需要CGI权限的途径来实现如动态显示、查询、排序等以前只能通过CGI程序才能完成的功能,并且效果通常更好。
考虑到XML对于大多数的网友来说并不是很熟悉,所以笔者试图避开XML技术的很多复杂的概念和庞大的体系结构,介绍上述功能的傻瓜式的实现方式。如果你想让自己的网站更上一层楼,让计数器以100次/平方秒(呵呵,夸张了点!)的加速度跳动,请跟我来。
一. XML概述及实例
虽然说了不深入XML的概念和体系结构的介绍,但还是有必要讲讲在接下来的制作过程中必须理解的XML的基本思想和一个名词--XML的数据岛(Data Island)。
提到XML,大家可能马上会联想到HTML,实际上,在某种程度上可以说XML是为了解决HTML的某些局限而产生的。众所周知,HTML是用来描述数据(如文字、图片、视频等)怎么样在Web浏览器中显示出来。描述的方式是使用规定的标签如<font>、<center>、<img>等等。那么XML呢?简单的说,XML是用来描述数据的结构的,而不是这些数据怎么在浏览器中显示出来,就象数据库中的二维表一样。描述的方式也是标签,不过这些标签都是你自己定义的。自己给标签取名字,听起来好象不可思议,其实,现在你完全可以结合后文的XML文件的例子把这些标签看成是一个数据库表的表名和字段名。在定义数据库表的时候,表名和字段名肯定都是你自己取的了。一旦你这样想,那么把用XML描述的数据看作数据库表的另一种样子也是理所当然的了。继续推理下去,把XML文件上传到Web Server不就意味着在Web Server上定义了数据库表吗?再使用后文介绍的在浏览器中(即HTML文件)操纵XML文件中的数据不就意味着可以实现动态网页了吗?哈,看来我们突破CGI权限约束的信心更足了。
XML文件的例子如下(这个XML文件也作为后文介绍操纵XML数据时使用的数据源,怎样扩展这个文件相信读者看完之后比我更清楚!不过如果你的数据内容中有"<"、">"、 ""(双引号)"、"'(单引号)"、"&"几种符号的话,应该写成相应的"<"、">"、"""、"'"、"&"):
<?XML version = '1.0' encoding="gb2312"?>
<!-- article.XML -->
<!-- 用来保存文章的简单的描述信息和详细内容的链接地址 -->
<articlelist>
<article>
<title>这是第二篇文章</title>
<from>《XML基础教程》</from>
<author>胡许立</author>
<author>章丰</author>
<author>武娜</author>
<filename>article/1.HTML</filename>
</article>
<article>
<title>这是第三篇文章</title>
<from>《新潮电子》</from>
<author>张耀兵</author>
<filename>article/2.HTML</filename>
</article>
<article>
<title>这是第一篇文章</title>
<from>《另外一本书》</from>
<author>陈庆珩</author>
<author>郭锋涛</author>
<filename>article/3.HTML</filename>
</article>
<article>
<title>这是第四篇文章</title>
<from>《第四本书》</from>
<author>胡许立</author>
<author>武娜</author>
<filename>article/4.HTML</filename>
</article>
</articlelist>
<!-- article.XML 文件结束 -->
从例子中可以很明显的看出,除了<?XML version = "1.0" encoding="gb2312" ?>和注释标签<!-- -->以外,其他所有的标签都是笔者自己定义的。不过这里的标签都是大小写敏感的,如<author>与<Author> 是不一样的,而且,标签里的属性值都必须用引号(单引号或双引号)引起来。这与HTML是不相同的。标签<?XML version = "1.0" encoding="gb2312" ?>是一个XML处理指令(注意小写),不可缺少。"?"与"XML"之间不能有空格,属性"version"指示该XML文件符合的XML标准的版本号,"encoding"属性指定了XML文件使用的字符集,因为XML缺省的字符集为Unicode,所以我们要把字符集设为"gb2312"."gb2312"表示国标简体中文,"big5"表示繁体中文。
例子中所有的代码组成了一个数据岛(Data Island),可在HTML文件中作为一个记录集来操纵。
另外,在Notepad(或其他的编辑器或专业的XML编辑器如Visual Interdev)中编辑完后可以用IE5浏览器直接查看是否有语法错误,如下图示:
二. 显示XML文件中的数据
把XML数据引入HTML文件中很简单。通过以下的HTML代码可以把上文中的XML文件中的数据以表格的形式在浏览器中显示出来。
<!-listarticle.HTML -->
<HTML>
<body>
<XML id="XMLdso" src="http://soft.yesky.com/SoftChannel/72342376223342592/20010519/article.XML" ></XML>
<table border=1 datasrc="http://soft.yesky.com/SoftChannel/72342376223342592/20010519/#XMLdso" align=center datapagesize=3>
<thead>
<tr>
<th>文章标题</th>
<th>出处</th>
<th>作者</th>
<th>详细内容链接</th>
</tr>
</thead>
<tbody>
<tr>
<td><div datafld="title"></div></td>
<td><div datafld="from"></div></td>
<td>
<table border=0 datasrc = "#XMLdso" datafld="author">
<tr><td><span datafld="$text"></span></td></tr>
</table>
</td>
<td align=center><a datafld="filename">请点击</a></td>
</tr>
</tbody>
</table>
</body>
</HTML>
一看就明白吧。只要在使用XML数据之前通过<XML id="XMLdso" src="http://soft.yesky.com/SoftChannel/72342376223342592/20010519/article.XML" ></XML>这对特殊的HTML 标签(记住这个事实)来引入一个XML文件(数据岛),并给它赋一个唯一的ID,然后就可以在一些特定的HTML标签中通过指定这些标签的Datasrc和Datafld来把XML数据与HTML元素联系起来(技术上称为数据绑定)。这些HTML元素包括:A、APPLET、BUTTON、DIV、FRAME、IFRAME、IMG、INPUT(Type=CHECKBOX,HIDDEN,LABEL,PASSword,RADIO,TEXT)、LABEL、MARQUEE、SELECT、SPAN、TABLE和TEXTAREA。当然指定Datasrc和Datafld的时候也有些要注意的地方,如应该在ID前加上"#"号;由于<td>不在上述元素列表内,所以要在<td></td>之间增加一个容器标签<div>或<A>。另外如果遇到XML文件中含有重复标签如<author>,那么显示的时候需要使用嵌套的表格,并把每行即<td></td>之间的容器标签(<span>)的绑定数据字段设为"$text",如上例所示。
以上HTML文档可在IE5中直接观察效果,如图2示.如果使用的是IE4,方法要稍微复杂一点。
三. 增加一些导航功能
细心的读者可能已经发现,上节的HTML文档在浏览器中只显示了3条article信息,不是有4条吗?为什么另外一条没有显示呢?仔细参看HTML原文件可以发现,在<table>标签里有一条"datapagesize"的属性.从字面上就可以知道是它搞的鬼了。那么第四条信息怎么显示出来呢?这就是本节的主题.
前面已经提到,可以把数据岛在HTML文件当作一个记录集(是ASP技术里经常提到的ADO的记录集)来看待,那么自然我们可以试试用ADO的方法来操纵这个记录集了。实际上也是的。
先看怎么做.我们在上面的HTML文档listarticle.HTML的</table>和</body>标签之间插入如下的代码.
<center>
<div id=divCount></div>
<input type=button id=btnFirst value="首页" >
<input type=button id=btnPrevious value="上页" >
<input type=button id=btnNext value="下页">
<input type=button id=btnLast value="末页" >
</center>
<script language="VBScript">
sub btnFirst_onclick()
XMLtable.FirstPage
end sub
sub btnPrevious_onclick()
XMLtable.PreviousPage
end sub
sub btnNext_onclick()
XMLtable.NextPage
end sub
sub btnLast_onclick()
XMLtable.LastPage
end sub
</script>
<script language="vbscript">
dim rsArticle
set rsArticle = XMLdso.recordset
dim count
count = rsArticle.RecordCount
divCount.innerText = "总记录数:"&count&"条"
</script>
再在IE5中浏览,就如图3所示。点击"下页"或"末页"按钮是否可以看到第四条记录了?而实现的方法只是在HTML文件中增加一些简单的VBScript代码。在这些代码中我们确实是把XML数据岛作为ADO的记录集RecordSet来对待的。例如要得到XML数据岛XMLdso的总的记录条数,只是简单的把XMLdso.recordset的记录数属性传给一个容器标签如<div>就可以了。当然这里必须通过<div>的innerText特性或innerHTML,而不是直接给它的ID赋值。
需要说明的是,由于IE5实现方式的原因,table又是一种特殊的绑定数据的HTML元素,所以利用表格显示数据的时候翻页只须利用表格翻页功能就可以了,如例中的XMLtable.FirstPage等。
还要注意,并不是所有有关ADO的东西我们都可以搬来,如:1.不能直接执行SQL语句;2.不能执行在ASP中支持的ADO排序、查询功能,除此之外的ADO的RecordSet的大部分属性、方法如AbsolutePosition、AbsolutePage、PageSize、PageCount、RecordSet、Eof、Bof、Move、MovePrevious、MoveNext、MoveFirst、MoveLast等等都是支持的。
四. 实现查询功能
虽然不能直接利用ADO来执行查询功能,但是因为链接到HTML文档中的XML数据岛在被浏览之前已经下载到本地,并且在内存当中,所以可以通过VBScript字符串比较语句来实现高速的查询功能。如下所示:
<!--search.HTML-->
<HTML>
<body>
<XML id="XMLdso" src="http://soft.yesky.com/SoftChannel/72342376223342592/20010519/article.XML"></XML>
<center>根据标题查找文章</center>
<br>
输入要查找的关键字:<input type=text id=txtInput width=20>
<input type=button id=btnSearch value="查找">
<input type=button id=btnClearall value="清除">
<br>
查找的结果:<br>
在记录集中的位置:<span id=spnPosition></span><br>
文章标题:<input type=text id=txtTitle width=50><br>
文章出处:<input type=text id=txtFrom width=50><br>
文章详细内容的链接: <a id=aFilename></a>
<script language="VBScript">
sub btnSearch_onclick()
dim rsArticle,bMatched,strTitle,iPos,strSearch,str,i
strSearch = trim(txtInput.value)
if (strSearch = "") then
MsgBox "请输入要查询的字符串!"
else
bMatched = false
set rsArticle = XMLdso.recordset
rsArticle.MoveFirst
do while not rsArticle.Eof and Not bMatched
strTitle = rsArticle("title")
iPos = Instr(1,strTitle,strSearch,vbTextCompare)
if iPos<>0 then
bMatched = true
spnPosition.innerText = rsArticle.AbsolutePosition
txtTitle.value = strTitle
txtFrom.value = rsArticle("from")
aFilename.innerText = rsArticle("filename")
aFilename.href = rsArticle("filename")
end if
rsArticle.MoveNext
loop
if not bMatched then
MsgBox "找不到任何记录满足条件!"
end if
end if
end sub
sub btnClearall_onclick()
spnPosition.innerText= ""
txtInput.value = ""
txtTitle.value = ""
txtFrom.value = ""
aFilename.innerText = ""
end sub
</script>
</body>
</HTML>
文档浏览效果如图4所示。
相信大家对VBScript都很熟悉了,所以上面的程序也不是很难理解,这里就不再赘述。唯一要指出的是,上面的HTML文档没有显示XML数据岛"author"元素的内容。因为要把所有的作者显示出来,代码要稍微复杂一点,而且涉及到一个大陷阱,所以暂时从略。有一个最简单的办法就是避免使用重复标签。
五. 实现排序功能
实现查询功能看起来有点复杂,马上要介绍的排序实现起来也不是很简单的,需要借助XML相关的XSL技术(即可扩展的样式表),与CSS有相似的地方,但更多的是不同。所以说要完整的掌握XML及其相关的技术不是很容易。不过嘛,很多的方法都可以照搬的,不是说"模仿是创作的第一步"吗?嘻嘻,大家尽可以打起精神来。
下面就是排序的源代码:
1. 增加了一个独立的sort.xsl文件,如下:
<xsl:stylesheet XMLns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<articlelist>
<xsl:apply-templates select="//article" order-by="title" />
</articlelist>
</xsl:template>
<xsl:template match="article">
<article>
<title> <xsl:value-of select="title" /> </title>
<from> <xsl:value-of select="from" /> </from>
<author>
<xsl:apply-templates />
</author>
<filename> <xsl:value-of select="filename" /> </filename>
</article>
</xsl:template>
<xsl:template match="author">
<author> <xsl:value-of/> </author>
</xsl:template>
</xsl:stylesheet>
2. 在listarticle.HTML中增加一个下拉列表
<select id=selSorting onchange=sortby(options(selSorting.selectedIndex).value)>
<option value="">不排序</option>
<option value="title">按标题排序</option>
<option value="from">按出处排序</option>
<option value="author">按作者排序</option>
<option value="filename">按详细内容链接排序</option>
</select>
并增加如下VBScript代码:
<script language="vbscript">
sub sortby(whichFld)
if whichFld<>"" then
set stylesheet = CreateObject("Microsoft.XMLDom")
stylesheet.async = false
stylesheet.load "sort.xsl"
set sortNode = stylesheet.selectSingleNode("//@order-by")
sortNode.value = whichFld '注意在这里设置成了选择的排序方式
set oldXMLDoc = XMLdso
set newXMLDoc = CreateObject("Microsoft.XMLDom")
oldXMLDoc.transformNodeToObject stylesheet,newXMLDoc
XMLdso.load newXMLDoc
end if
end sub
</script>
在IE5中重新浏览listarticle.HTML,是不是如图5所示?用鼠标点击下拉列表框改变选择时,可以引起页面按照希望的方式重新排序。
为了修改源代码的方便,简单介绍一下原理:这里的排序实际上就是在内存中把引入的XML文件通过IE内置功能按照XSL定义的转换方式(包括排序方式)转换为一个新的临时XML文档对象,并引起绑定了XML数据的HTML元素刷新显示。XSL文件也是一种特殊的XML文件,在本例中定义了转换的规则。<xsl:template match="……">和</xsl:template>定义模板样式;"match"属性的值指定模板样式的影响范围,特殊值"/"的意义是匹配整个XML文档;<xsl:value-of select="……" />表示取XML元素(由"select"属性指定)的值;<xsl:apply-templates select="……"/>表示引用子样式,"select"指定影响范围。<author>与</author>之间的<xsl:apply-templates />是由于一个"article"元素可能有几个"author"子元素。
六. 结语
这不是一个关于XML的详细教程(那样足够写10本大部头了),XML的很多功能强大的东西都没有提及或深入介绍。但是学完、特别是试用了文章方法后对XML的概念和基本思想应该会有很好的感性认识。
如果大家通过本文提起了学习XML的兴趣,网上有很多的资源可以利用,如www.microsoft.com/msdn、www.w3.org/XML、www.XML.com.cn等等
|
|
|