对XML应用,一般从两个角度来实现,一个是建立一个基于XML的Web服务器,这个我们在上面的关于基于XML的数据库系统分析中已经有详细的介绍,客户端可以是任意的浏览器,比如PC机上的浏览器或者是手机、PDA和其他移动设备上的浏览器。IBM的WebSphere服务器部分达到了这个要求。另一种就是建立一个功能强大的可以对XML,XSL进行解析的浏览器,比如微软的IE5.0以及NetScape等等。下面我们主要从客户端这个角度进行讨论。
IE5实际上是第一个支持XML的浏览器,IE支持下面的XML相关的特征:
· XML 页面浏览:当一个URL是指向一个XML的文档的时候,IE内在的解析器(实际上是用MSXMLDLL组件实现的,MSXML.DLL内部封装了解析XML文档相关的COM对象集合)把XML文档以树的形式展现出来。如果出现错误的话,IE浏览器能够提示错误所在的行和错误原因。
· XML 1.0 和名字空间标准: IE5 支持这些有W3C提出的标准。通过名字空间,我们可以准确的知道一个属性或元素的作用范围,比如<stock:quote>和 <speech:quote>是两个完全不同的属性。
· 文档对象模型 (DOM):通过对象模型能够展示XML文档的所有元素和属性,以便应用程序做相应的处理。
· Extensible Stylesheets (XSL):前面提到,我们可以用XSL来对文档内容做不同样子的展示,这里IE支持用XSL来展现XML的内容。
· 在HTML中的XML 数据:XML能够通过<XML>标签被包含在HTML文档中。
· XML Schema:Schema和DTD都是对文档进行格式化的工具,但Schema支持更加灵活的格式化。
· XML Parser:IE支持用两种对XML文档解析的方法,DOM和SAX。
这里,我们主要通过微软的IE浏览器来讨论浏览器对XML的支持,事实上,早在IE4.0的时候,就提供了两个XML解析器,一个是ActiveX控件,另外一个就是Java Applet。ActiveX版本提供了一个处理XML的接口,也就是文档对象模型(DOM)。Applet版本是作为数据源对象(DSO)实现的。因为它是一个DSO,所以你可以把applet绑定到任意的数据消费者上,比如HTML表格。
尽管在IE4.0中出现的XML解析器可以做很多事情,但是,存在它的限制。首先,没有办法来在数据源中查找一个指定的数据。为了发现你感兴趣的额数据,你必须遍历整个XML数据树并且手工的进行比较。第二,这些初级的解析器不能提供任何过滤功能,这样你不得不手工进行数据得过滤。
但是有好消息,好消息是在IE5.0中提供了增强的XML支持用来解决这些用户。IE5.0把解析器集成到了浏览器中,这样就不需要这两个分离得组件了。并且,新得查询语言允许你查询和过滤XML数据。在IE5.0中,查询语言支持是通过一个XSL模式匹配来进行的。IE5.0同时支持XML数据岛的概念,为了在你的Web应用中利用IE5.0的XML解析器,你只要在Web页面中嵌入一个XML数据岛,并利用剧本操作IXMLDOMDocument等DOM接口就可以了。
在XML数据岛中你可以遍历所有的子节点,可以用如下的VBScript语句表示:
<SCRIPT LANGUAGE=vbscript>
sub traverseChildNodes(nodelist)
for each node in nodelist
' 对该节点做一些操作
if node.hasChildNodes then
traverseChildNodes node.childNodes
end if
next
end sub
sub window_onload()
traverseChildNodes xmlData.childNodes
end sub
</SCRIPT>
在IE5.0中,增加了两个新的DOM方法:selectNodes和selectSingleNode。这两个方法都采用一个模式字符串作为唯一的输入参数,selectNodes返回一个对IXMLDOMNodeList的引用,而selectSingleNode返回一个对IXMLDOMNode的引用。两个方法唯一的不同是selectNodes返回所有匹配的节点,而selectSingleNode只返回符合匹配模式的第一个节点。
下面是使用selectNodes方法遍历XML数据岛的所有订货项目的例子:
<SCRIPT LANGUAGE=vbscript>
sub traverseAllOrderItems(ordernode)
set nodelist = ordernode.selectNodes("//item")
for each node in nodelist
' 这里可以对节点进行一些处理
next
end sub
sub window_onload()
traverseAllOrderItems xmlData.documentElement
end sub
</SCRIPT>
传递给方法selectNodes的字符串//item是模式的一个例子,事实上,你可以对任何IXMLDOMNode 对象调用selectNodes或者是selectSingleNode方法。
在具体查询的时候,你可以把新的查询语言应用到XSL模板上。模式可以被用来匹配和选择在XSL中的属性,需要注意的是,缺省的XSL模板指定匹配XML文档的根节点(/)。上面的代码for-each循环只对订单项目进行操作。
我们知道,XML被设计成在一个层次格式中描述数据的结构,一个XML文档包括一个单一的根节点,它能够包含多个子节点,在XML文档中的任何的根节点也可以包含更多的子节点,当然也可以不包含子节点。因此,XML实际上是以树的形式来组织数据的。
XSL模式匹配语言提供了遍历一个XML文档树结构的语义。XSL模式匹配语言有点象在文件系统外壳下,遍历文件系统。比如你在C盘的根目录下键入:
cd windows\system32
当前的目录将转换成c:\windows\system32,XSL模式匹配语言基本上以相同的方式进行工作。比如,一个模式orders/order/item表示在orders元素下的order元素下的item元素。这个匹配是在当前节点的上下文下进行解析的。
调用selectNodes 和selectSingleNode的节点变成当前节点。前面在讲述XSL标准的时候,已经提到,在一个匹配模式前面加上"/",表示模式匹配是丛根节点开始的,用"./"表示从当前的节点开始匹配。用"//"表示对在节点下的所有子节点进行匹配,不管它在那个层上。你也可以使用"*"来匹配所有的元素。你也可以使用"@"符号来执行一个给定元素的属性。比如,为了识别项目元素的类型属性,可以采用下面的匹配模式:
file://item/@type
一般来说,你可以把属性当成是元素的子节点。除非在名字前面加上了符号"@"集合。在这里讨论的基本匹配模式能够识别元素的集合,比如匹配模式//item指定了一个项目元素的集合,该集合可能存在于文档的任何位置。因为你需要在一个集合内找出特定的元素,模式匹配提供了一个标准的操作符"[]",表示对一个集合的索引。该索引是从0开始的。比如匹配模式//item/price[0]表示每一个项目元素的第一个价格元素。而模式//item[0]/price[0]表示在所有的项目集合中的第一个项目元素的第一个价格元素。同时需要注意的是,可以用括号对操作进行分组。
下面我们讨论一下过滤模式,过滤模式也包含了表达式用来指定如何在一个集合中对项目进行过滤。实际上存在许多操作符,你可以使用它们来创建过滤表达式,这些操作符允许你创建标准的比较表达式,逻辑表示式和集合表达式。一般来说,操作符的起始和结尾都用"$"符号表示,其中很多符号都是借用了C++中的符号表示,比如下面的两个表达式是等价的:
file://item[index() >= 3]
file://item[index() $ge$ 3]
下面我们来分析一个相对比较复杂的过滤表达式:
(orders//order[customer/lastname $ieq$ "Skonnard" && @itemcount > 1]/ item[price > 20])[index() < 10]
这个表达式表示从满足条件的集合中选择前十个订单,这个条件就是价格大于20美金,订单的客户的姓是Skonnard,并且他的订单数超过一个。从这个表达式中你可以发现,利用过滤表达式你可以做非常复杂和精确的查询。
必须要指出的是,IE是第一个提供高级XML支持的浏览器,为了充分利用IE浏览器的性能,你必须熟悉XSL模式匹配语言的语义并且在执行复杂查询和过滤操作的时候使用它们。