第章

5

XML基础




学习要点

(1) XML文档的基本结构。

(2) 用CSS在浏览器中控制XML文档显示的方法。

(3) 用XSL控制XML文档在浏览器中显示的方法。

(4) 进行XML DOM程序设计的方法。

(5) XML文档和数据库系统之间的数据交换。

(6) XML技术的应用和发展趋势。










第
5
章

X
M
L
基
础

于1998年问世的XML是以SGML(标准通用标记语言)为基础的。SGML是一个国际标准,可以将其理解为是定义其他文档标记语言的语言。SGML难以使用,而XML的目标就是要变得更加简单易用。HTML也是基于SGML的。1999年提出了XHTML(eXtensible HTML),XHTML使用XML语法构造规则对HTML进行了改写。XHTML文档的构造规则比HTML要精确得多。这些规则的严格程度取决于在XHTML页面中所指定的文档类型声明(DOCTYPE)。

从1998年起,许多厂商(如Adobe、IBM、微软、Netscape、Oracle和Sun)开始使用XML标准,且视XML为关键技术。目前,许多工具和软件例如Navigator、Internet  Explorer及RealPlayer等,都已经在软件内部使用XML技术。XML文档使数据易于共享。一系列相关的W3C推荐标准解决了XML文档内进行转换、显示和导航的问题。



XML技术已成为Web开发中很重要的一项技术。很多读者可能存在“什么是XML?XML能做什么?使用XML能带来什么好处?XML能不能替代数据库?XML会取代什么?XML的发展前景如何?如何利用XML来进行程序设计?”等诸如此类的问题。通过本章的学习,我们可从中找到全部答案。

5.1XML文档
5.1.1XML的概念




视频讲解


今天,XML已成为W3C推荐使用的标准,是整个Web的基本结构和未来技术发展的基础。什么是XML?

 XML是一种类似于HTML的标记语言。

 XML是用来描述数据的。

 XML的标记不是在XML中预定义的,必须定义自己的标记。

 XML使用文档类型定义(DTD)或者Schema(模式)来描述数据。

 XML使用DTD或者Schema后就是自描述的语言。

从上面XML的定义来看,应清楚以下几点。

(1) 可以用XML来定义标记,它和HTML是不一样的,XML的用途比HTML广泛得多;  XML并不是HTML的替代。

(2) XML不是HTML的升级,它只是HTML的补充,为HTML扩展更多功能,我们仍将在较长的一段时间里继续使用HTML,但基于XML格式的XHTML将逐步取代HTML。

(3) 不能用XML来直接写网页。XML文档存放自描述的数据,必须转换为HTML格式后才能在浏览器上显示。

一个简单的XML文档内容如下所示: 



<?xml version="1.0"?>

<book>

<title> XML语言及应用</title>

<author> 华铨平等 </author>

<publisher> 清华大学出版社 </publisher>

<publishdate> 200509</publishdate>

</book>




其中,book、title、author、publisher、publishdate都是自定义的标记(tag)。

5.1.2XML的特点
1. XML的可扩展性

XML具有的扩展性,正是体现了XML的强大功能和弹性。在HTML中,需熟悉许多固定标记后再使用这些标记。而XML中,可建立任何需要的标记,可充分发挥想象力给文档起一些好记的标记名称。例如,文档中包含一些游戏的攻略,可以建立一个名为<game>的标记,然后在<game>下再根据游戏类别建立<RPG>、<SLG>等标记。只要清晰,易于理解,可以建立任何数量的标记。

扩展性意味着更多的选择和强大的能力,但同时也产生了一个问题,就是必须学会规划。应清楚文档由哪几部分组成、相互之间的关系和如何去识别它们。

2. XML标记的描述性

标记又叫标识,也称元素名,用于描述数据、标识文档中的元素。不论是HTML还是XML,标记的本质在于便于理解,如果没有标记,文档在计算机看来只是一个很长的字符串,每个字符串看起来都一样,没有重点之分。通过标记,文档才便于阅读和理解。XML的扩展性允许为文档建立更合适的标记。不过,标记只是用来识别信息,它本身并不传达信息。

3. XML标记的规则

要遵循特定的XML语法来标识文档。虽然XML的扩展性允许创建新标识,但它仍必须遵循特定的结构、语法和明确的定义。XML的标记有如下规则。

 所有的标记都必须有一个相应的结束标记。

 所有XML标记都必须合理嵌套。

 所有XML标记都区分大小写。

 所有标记的属性都必须用引号“"”括起来。

 名字中可以包含字母、数字以及下画线。

 名字不能以下画线开头,不能用诸如关键字XML来开头。

 名字中不能包含空格。

在XML文档中的任何差错都会得到同一个结果: 不能转换为HTML,即网页不能被显示。各浏览器开发商已经达成协议,对XML实行严格而挑剔的解析,任何细小的错误都会被报告。

4. XML文档的结构化

XML促进文档结构化,所有的信息都按某种关系排列。也就是说,结构化为XML文档建立了一个框架,就像写文章之前有一个提纲一样。结构化使文档看起来不会杂乱无章,每一部分都紧密联系,形成一个整体。结构化有下面两个原则。

 每一部分(每个元素)都和其他元素有关联,关联的级数形成了结构。

 标记本身的含义与它描述的信息相分离。

5. 允许meta数据(元数据)

专业的XML使用者都会使用meta数据来工作。HTML中我们知道可以使用meta标记来定义网页的关键字、简介等,这些标记不会显示在网页中,但可以被搜索引擎搜索到,并影响搜索结果的排列顺序。XML对这一原理进行了深化和扩展,可以用XML描述信息在哪里,可以通过meta来验证信息、执行搜索、强制显示或者处理其他的数据。

下面是一些XML meta数据在实际应用中的用途: 可用于数字签名,使在线商务的提交动作有效;  可以建立索引和进行更有效的搜索;  可以在不同语言之间传输数据。W3C组织正在研究一种名为RDF(Resource Description Framework)的meta数据处理方法,可以自动交换信息。W3C宣称,使用RDF配合数字签名,将使网络中存在“真实可信”的电子商务。

6. XML的多样显示性

单独的XML文档使用格式化技术,如CSS或者XSL,才能在浏览器中显示。XML将数据和格式分离。XML文档本身并不知道如何显示数据,而必须由辅助文件来帮助实现。XML中用来设定显示风格样式的文件类型如下。

1) XSL

XSL(Extensible Stylesheet Language,可扩展样式语言)是将来XML文档显示的主要文件类型。它本身也是基于XML格式的。使用XSL,可以灵活地设置文档显示的样式,文档将自动适应任何浏览器和PDA(掌上电脑)。XSL也可以将XML转换为HTML在浏览器中显示。

2) CSS

CSS是目前用来在浏览器上显示XML文档的主要方法。

3) Behaviors

Behaviors现在还没有成为标准。它是微软的IE浏览器特有的功能,用它可以对XML标记设定一些有趣的动作。

7. 允许XML DOM操作

XML DOM全称是XML Document Object Model(XML文档对象模型),DOM是用来干什么的呢?假设把XML文档看成一个单独的对象,DOM就是如何用脚本语言对这个对象进行操作和控制的标准。XML创建了标记,而DOM的作用就是告诉Script脚本语言如何在浏览窗口中操作和显示这些标记。

5.1.3XML与HTML的区别
1. 传统的HTML存在的问题和不足

(1) HTML的标记是固定的,有70多个。Web技术的飞速发展使新的数据格式不断产生并需要在网上展示,标准的HTML语法格式无法创建新的标记,也将无法支持那些专门的页面格式,例如数学公式、化学方程式、音乐乐谱、财务报表以及工程应用等。

(2) DHTML带来的问题。在标准HTML无法满足用户需求的情况下,人们在其基础上增加了动态的成分,如脚本程序等。但这些非标准技术制作的网页在不同的浏览器之间互不兼容。

(3) HTML只是一种表现技术,它并不能揭示HTML标签所标记的信息的任何具体含义。例如,语句<h1>Peach</h1>是表示在Web浏览器中用标题1显示文本Peach,但HTML标记却没有表明Peach究竟代表什么意思,它可能是指一种水果,也可能是某公司的名字,或者是一个别的什么东西。HTML当初在制定时并没有考虑这方面的功能。

2. HTML与XML的对比

XML技术的发展可以大幅弥补HTML的不足。表51列出了HTML与XML的对比。


表51HTML与XML的对比



比 较 内 容
HTML
XML


可扩展性
不具有扩展性
可用于定义新的标记语言
侧重点
侧重于如何表现信息
侧重于如何结构化地描述信息
语法要求
不要求标记的嵌套、配对等,不要求标记之间具有一定的顺序
严格要求嵌套、配对和遵循树形结构
可读性及可维护性
难以阅读、维护
结构清晰,便于阅读和维护
数据和显示的关系
内容描述与显示方式整合为一体
仅为内容描述,它与显示方式相分离
保值性
不具有保值性
具有保值性
编辑及浏
览工具
已有大量的编辑、浏览工具,例如FrontPage、Dreamweaver等
有较多编辑、浏览工具。例如Vervet Logic的XML Pro V2、微软的免费软件XML Notepad 2.2、ALTOVA 公司的XML SPY等


在学习XML技术的过程中,会经常遇到很多技术名词,例如XML DTD、XML Schema、XSL、CSS等,图51列出了这些技术相互之间的关系。




图51XML相关技术之间的关系



图51中,XML DTD是一种文本说明内容,既可以放在一个单独文档中,又可以直接放在某个XML文档中,用于说明XML文档中数据的类型和格式。不过由于XML DTD本身是非XML文档结构的,其对XML文档数据类型和格式的描述过于复杂,用户在使用时较难掌握,目前已逐步被XML Schema所替代。XML Schema中对XML文档中数据类型和格式的描述采用了XML文档结构。CSS和XSL分别用于说明XML文档在浏览器中以什么方式显示其中的数据。这些技术将会在后续章节中一一介绍。

5.1.4XML文档术语以及基本结构
1. XML文档术语

(1) element(元素)和tag(标识)。

元素在HTML中我们已经有所了解,它是组成HTML文档的最小单位,在XML中也一样。一个元素由一个标识来定义,包括开始和结束标识以及其中的内容,如<author> book </author>。唯一不同的是,在HTML中,标识是固定的,而在XML中,标识需要自己来创建。一般来说可以混淆标识与元素的区别。

(2) attribute(属性)。

属性是对标识的进一步描述和说明,一个标识可以有多个属性。XML元素可以像HTML一样在开始标识(start tag)中书写属性。属性用来提供关于元素的附加信息。属性常用来提供数据部分以外的信息。例如: 



<file type="gif">computer.gif</file>





从以上代码中可以看到,type是属性,computer.gif是数据。type属性与数据并不相关,只是用来附加说明该元素用了gif格式的数据。

(3) declaration(声明)。

每个XML文档的第一行都有一个XML声明<?xml version="1.0"?>。这个声明表示这个文档是一个XML文档,它遵循的是哪个XML版本的规范。

(4) DTD(Document Type Definition,文档类型定义)。

DTD是用来定义XML文档中元素、属性以及元素之间的关系的。通过DTD文档可以检测XML文档的结构是否正确,但建立XML文档并不一定需要DTD文档。

(5) Wellformed XML(良好格式的XML)。

一个遵守XML语法规则并遵守XML规范的文档称为“良好格式”。如果所有的标识都严格遵守XML规范,那么XML文档就不一定需要DTD文档来定义它。

良好格式的文档必须以一个XML声明开始,如<?xml version="1.0" standalone="yes" encoding="UTF8"?>。其中,必须说明文档遵循的XML版本目前是1.0;  其次说明文档是“独立的”,它不需要DTD文档来验证其中的标识是否有效;  最后要说明文档所使用的语言编码,默认的是UTF8。

(6) Valid XML(有效的XML)。

一个遵守XML语法规则并遵守相应的DTD文档规范的XML文档称为有效的XML文档。Wellformed XML和Valid XML的最大区别就在于,前者完全遵循XML规范,后者有自己的DTD。


2. XML文档基本结构

XML文档是一个纯文本文件,可以用任意的文本编辑器编写,如记事本、Word等。为了提高编写效率,也有一些专门的可视化XML创作及编辑工具,例如美国Altova公司的XMLSpy 2006企业版(http://www.xmlspy.com/)、Oxygen公司的XML Editor(http://www.oxygenxml.com/index.html)等,用户可从网上下载这些工具。

下面是一个典型的XML文档。



<?xml version="1.0" encoding="GB-2312" standalone="yes"?>

<?xml-stylesheettype="text/css"href="book.css"?>

<中国古典名著>

<书>

<书名>三国演义</书名>

<作者>罗贯中</作者>

<内容简介>略</内容简介>

</书>

<书>

<书名>西游记</书名>

<作者>吴承恩</作者>

<内容简介>略</内容简介>

</书>

</中国古典名著>




XML文档结构由三部分组成。

1) XML文档声明

它位于文档的第一行,一般形式为: 



<?xml version="versionNumber" [encoding="Value"][standalone="yes/no"] ?>




其中,versionNumber为XML文档所遵循的XML规范的版本号: 可选项encoding表示XML处理器使用的字符集,默认值为UFT8;  可选参数standalone取值为yes或no,默认值为yes,表明该文档是否为一个独立文档。

2) 文档显示方式或文档类型定义等的声明部分

文档类型定义部分,一般形式为<!doctype…>,如不需要可以省略。上例中第2行说明了此XML文档将由book.css定义的样式单来决定其显示方式。

3) XML标识的文档内容

XML文档内容有以下几种结构。

(1) 声明根元素。

每个有效的XML文档有且仅有一个根元素。根元素是在一个XML文档中包含所有其他元素的元素,无论是在语法上还是逻辑上,根元素位于所有数据的顶层。根元素的声明和其他元素的声明方法一样,一般形式为: 



<rootElementName>…</rootElementName>



rootElementName是根元素的名称,必须成对出现,且区分大小写。根元素在逻辑上代表了数据的顶层,它必须位于XML声明结束后的下面一行。

(2) 声明非根元素。

在XML中,是通过在容器元素中嵌套被包含元素来描述数据对象的。一个被包含元素又可以包含自己的元素。包含其他元素的元素称为容器,所有的非根元素都包含在根元素中,根元素是最上层的容器元素。



<containedElement [attributesList=""]>

<containedElement[attributesList=""]>

…

</containedElement>

…

</containerElement>




(3) 数据元素属性。

一个数据元素可以有若干属性,属性必须在一个元素的起始标记中声明,一般形式为: 



<elementName [属性名="属性值"] [属性名="属性值"] …[属性名="属性值"]>

elementValue

</elementName>





其中,元素名和属性名必须以字母或下画线开始,并且只能包含字母、数字、下画线、连字符和句点。例如,为汽车定义的三个属性为车牌号、车主和制造商,可以将<automobile>标记写为: 



<automobile number="123456"owner="Brion"manufacture="Ford" >

</automobile>




由于其中<automobile>标记中只有属性描述而没有元素值,因此可以缩写成: 



<automobile number="123456"owner="Brion"manufacture="Ford" />



可以将元素的属性名转换为元素名,例如上例中的转换结果是: 



<automobile >

<number>123456</number>

<owner>Brion</owner>

<manufacture>Ford</manufacture>

</automobile>



(4) 定义名称空间。

在XML中,用户可以自己定义标记和命名元素。因此,如果把多个XML文件合并为一个,就很可能出现冲突,名称空间就是为此设计的。

XML中名称空间(namespace)的严格定义是: 名称空间是用URI加以区别的、在XML文件的元素和属性中出现的所有名称的集合。URI是Uniform Resource Identifier(统一资源标识符)的缩写。在没有namespace的XML 1.0文件里,元素和属性中出现的名称被称为“本地名称”(local name)。XML中名称空间定义的一般形式为: 



<namespace:elementName xmlns:namespace="globalUniqueURI">

<namespace:containedElementnamespace:attributeName="Vaue">

</namespace:containedElement>

</namespace:elementName>



其中,namespace是名称空间的唯一名称;  elementName是应用名称空间的XML文档元素的名称;  globalUniqueURI是统一资源标识符,可根据实际情况设定一个作为名称空间的URI;  attributeName和attribute Value是和容器元素containedElement相关联的一个属性的名称和属性值。

定义名称空间的目的是唯一地标识一个元素或一组元素的属性。例如: 




<r:customer xmlns:r="http://www.ABCStore.com/CustomerURI">

<r:name r:Address="Beijing">Cherry</r:name>

</r:customer>



(5) 包含非标准文本。

通过预定义XML实体可以在XML文档中加入特殊符号。如果需要大量的特殊符号,可以使用CDATA段,CDATA段可以使用户在一个XML文档中引用大量的特殊符号文本块。一般形式为: 



<![CDATA[text]]>



其中,text是包含特殊字符的文本串,该文本不被XML分析器检查。XML处理器负责分析或者以一种有意义的方式使用该文本块。

【例51】Brion给Jane的便条信息使用XML格式来说明。ex_5_1.xml的文档内容为: 



<?xml version="1.0" encoding="gb2312" ?>

<note>

<to>Brion</to>

<from>Jane</from>

<heading>Reminder</heading>

<body>Don't forget me this weekend!</body>

<![CDATA[This is an example of CDATA]]>

</note>




将该文档存盘后,双击该文档将其在浏览器中以树形方式打开,如图52所示。



 
图52一个简单的XML文档在浏览器中的显示




如果XML文档标记不配对或有其他不符合XML文档格式的要求,在浏览器上将显示具体的出错信息。在这里浏览器起着XML文档分析器的作用。XML分析器有确认型和非确认型两种。确认型XML文档分析器检查XML文档的语法,将XML文档同文档类型定义DTD或模式文件进行比较,还要判断XML数据是否和预定义的确认规则相符。非确认型XML分析器也进行XML文档语法的检查,但不进行XML文档和DTD及模式文件的比较。在微软的Internet Explorer浏览器中内置XML确认型分析器,即MSXML。

5.2用CSS控制XML文档在浏览器中的显示
5.2.1XML文档的四种CSS样式定义方式




视频讲解


本书第3章已经详细介绍了在HTML文档中如何用CSS来控制其页面显示。在这里,控制XML文档显示的样式表格式是和HTML中的样式表格式相似的,只不过在样式表中,将HTML元素名换成了XML元素名。下面简要介绍控制XML文档显示的四种CSS样式定义方式。

(1) 元素名称选择符。可同时为一个或多个元素定义样式。格式如下: 



XML元素名称 { 设置的样式规则 } 




例如: 



Name,company,price,unit,details,.myclass,address#a1

{ Display:block;

Font-weight:bold;

Font-size:0.8em

}





(2) 用户自定义类选择符。通过对类名的引用,不同的元素可使用同一样式,不同位置的同一元素可使用不同的类名。格式如下: 



.类名称 { 设置的样式规则 }  /*可以被XML文档中的任何元素使用 */ 



或者




XML元素名称.类名称 { 设置的样式规则 }/*只能附加到指定名称的XML元素上*/

/*类选择符定义的样式表应用到XML元素的方法是:<XML元素名称class="类名称"> */





(3) 用户定义的id选择符。可以先为某元素指定一个id属性,再在CSS样式定义中通过“元素名#id”的方式指定样式。注意,元素名和id属性前面的#之间不能有空格。格式如下: 



#id号 { 设置的样式规则 }  /*可以被XML文档中的任何元素使用 */ 




或者



XML元素名称#id号 { 设置的样式规则 }/*只能附加到指定名称的XML元素上*/

/*id选择符定义的样式表应用到XML元素的方法是:<XML元素名称 id="id号"> */





(4) 成组选择符。格式如下: 



XML元素名称1, XML元素名称2, …, XML元素名称n { 设置的样式规则 }

.类名称1, .类名称2,…, .类名称n { 设置的样式规则 }

#id号1, #id号2,…, #id号n { 设置的样式规则 } 

/* 通过成组选择符定义样式表可集中定义多个XML文档元素的相同属性,减少了代码编写工作量。 */




5.2.2CSS 样式和XML文档联系

有三种方式可以将定义的CSS样式表和XML文档联系起来。

(1) 将定义的CSS样式表置于XML文档中,其格式为: 



1<?xml  version="1.0" encoding="utf-8"?>

2<?xml-stylesheet  type="text/css"?>

3<根元素 xmlns:html="http://www.w3.org/1999/xhtml">

4<html:STYLE>

5CSS选择符1 { 设置的样式规则 }  …

6</html:STYLE>

7<其他元素>  …  </其他元素>

8</根元素>




第二行不可缺少,告诉浏览器要用CSS来显示XML文档。第三行在根元素中定义了一个HTML名称空间,这里必须是HTML名称空间,名称空间的URI地址可以随意,即使是"abcd"也行,但要注意它的唯一性。在XML文档中插入样式单的style标志前,必须加上HTML名称空间。

(2) 将CSS样式表放在单独的扩展名为CSS的文件中,然后在XML文档声明部分通过声明语句引用CSS文件。



1<?xml  version="1.0" encoding="UTF-8"?>

2<?xml-stylesheet type="text/css"  href="CSS文件" ?>

3<根元素>

4<其他元素>  …  </其他元素>

5</根元素>




(3) 将上面两种方式结合起来: 既在XML文档中定义CSS样式,又引用外部CSS文件。

第3章已经介绍过CSS样式规则,为便于读者的学习,下面列出了XML文档常用的CSS样式规则,如表52所示。有很多辅助工具可以帮助自动生成CSS样式。


表52XML文档常用CSS样式规则




属性名
含义
取值
说明



display
显示方式
block/none
以块显示,前后换行 /不显示

inline
和前、后的元素在一行中显示(默认值)

fontsize
字体大小
56%,0.5cm,0.2in,10pc,10pt

1em,1ex,1px
取值也可以是xxsmall,xsmall,small,xxlarge,xlarge,medium,large,smaller,larger等
fontstyle
字型
italic/normal
斜体/正常字体

fontweight
字体粗细
normal
正常粗细
bold
粗体
bolder/lighter
更粗/更细
100,200,…,900
九种不同的灰度

color 
backgroundcolor
前景色

背景色
red,green,blue等
颜色的取值
rgb(a,b,c)/rgb(x,y,z)
0<=a,b,c<=255 /0%<=x,y,z<=100%
#0000FF
#000000~#FFFFFF

backgroundimage
背景图
图像的URL

backgroundrepeat
背景图重复

repeat
图像在水平和垂直两个方向上重复
rfepeatx;   repeaty
图像在水平或垂直方向上重复
norepeat
图像不垂直

backgroundposition
背景图位置

top
垂直方向的顶端 
center
垂直方向的中央
bottom
垂直方向的底端
left
垂直方向的左端
right
垂直方向的右端

letterspacing
文字间距
同fontsize取值
textalign
文本对齐
left/center/right
左对齐/居中对齐/右对齐

textdecoration
文本画线
underline/overline
下画线/上画线
linethrough/none
中画线/无画线

margin
页边距
同fontsize取值
上、下、左、右页边距
margintop
上边距
同fontsize取值
也用作段落间距和左右缩进
marginbottom

marginLeft

marginright
下边距

左边距

右边距
同fontsize取值

borderstyle
边框线样式
dotted,dashed,solid,
double,groove,ridge,
inset,outset,none
边框线
borderweight
边框线粗细
同fontsize取值
bordercolor
边框线颜色
同fontsize取值
textindent
首行缩进
同fontsize取值
lineheight
行距
同fontsize取值


【例52】CSS样式表置于XML文档中示例。将下面的代码保存为文件ex_5_2.xml。



<?xmlversion="1.0" encoding="UTF-8"?>

<?xml-stylesheettype="text/css"?>

<paper xmlns:html="http://www.w3.org/1999/xhtml">

<!-- 样式单定义 -->

<html:style>

paper { display:block;font-size:20px;line-height:160%;text-align: 

center}

author{ display:block; font-size:16px;margin-top:5px;margin-bottom:5px}

address{ display:block; font-size:16px; text-align:center}

abstract{

display:block;font-size:20px; font-weight:bold; font_style:italic; 

text-align:left}

abstract#al{

display:block; font-size:14px; font-weight:normal; font_style: normal;

line-height:150%;}

keywords{

display:block; font-size:20px; font-weight:bold;font_style: italic;}

keywords#al

{display:block;font-size:14px; font-weight:normal;font_style: normal;

line-height:150%;}

head{ display:block;font-size:20px; line-height:150%}

text{display:block;font-size:18px; text-align:left; text-indent:30pt; 

line-height:150%;}

</html:style>

<title>E-learning中的个性化技术研究</title>

<author>Hao Xingwei</author>

<address>

(Shandong University,School of Computer Science and Technology,Jinan, 

250100)

</address>

<abstract>Abstract: </abstract>

<abstract ID="al">

E-learning is now becoming a very important means in modern education,but the existing E-learning systems are short of personalization,the model of teaching is so simple that the procedures of learning are almost the same. How to build a personalization learning circumstance,…

</abstract>








<keywords>Keywords:</keywords>

<keywords ID="al">

E-learning,Knowledge point,personalized service,Web discovery

</keywords>

<head>0.前言</head>

<text>

E-learning是指基于网络的、电子化、数字化、多媒体的教学方式。在实际应用中,E-learning的范畴非常广泛,它不仅包含基于互联网的网络化学习,还包括了基于多媒体资料的数字化学习。随着Internet的快速发展和普及,以及教育的全球化和由此带来的教育竞争的加剧,基于Web的E-learning系统已经成为许多大学和教育机构实施现代化远程教育的重要手段。

</text>

</paper>




上述代码在浏览器中的运行结果如图53所示。




图53例52的运行效果


【例53】一个使用了CSS样式表的XML文档。样式文件ex_5_3.css内容如下: 



Student{Display: block}

Name.c1{Font-size: 3em;color:red}

Name.c2 Font-size:2em;color:green}

Name.c3{Font-size: 1em;color:blue}




引用ex_5_3.css样式的XML文档内容如下: 



<?xml version="1.0" encoding="GB-2312" ?>

<?xml-stylesheet type="text/css"href="ex_5_3.css" ?>

<student>

<name class="c1">张三</name>

<name class="c2">李四</name>

<name class="c3">王五</name>

</student>







图54XML使用CSS

运行该XML文档,其显示结果如图54所示。

【例54】用表格来显示学生花名册,其中有两个学生的资料。从例53中可以知道,通过CSS要用表格来表示XML文档,必须使用HTML名称空间,且每个HTML标记前必须指定HTML名称空间,例如“<html: tr>…</html: tr>”,如果标记不配对,则要用“/”表示结束,例如“<html: img src="bg.jpg" alt="it’s a background images"/>”。在指定HTML元素的样式时,必须用“html\: ”指定名称空间。ex_5_4.xml文档内容如下: 



<?xml version="1.0" encoding="gb2312" ?>

<?xml-stylesheet type="text/css" href="ex_5_4.css"?>

<roster xmlns:html="http://www.w3.org/1999/xhtml">



<html:style type="text/css">

html\:caption {font-weight:bold; text-decoration:underline} 

/*指定表格标题的样式*/

html\:table {background-image: url("images/bg.jpg")}

/* 指定表格的背景图片*/

.myclass {border-style:double;}

#myid {border-style:groove;}

</html:style>

<html:table border="1" cellPadding="2">

<html:caption> 学生花名册</html:caption>

<html:tr>

<student>

<html:td> <name>李华</name> </html:td>

<html:td> <origin id="myid">河北</origin> </html:td>

<html:td> <age>15</age> </html:td>

<html:td> <telephone>62875555</telephone> </html:td>

</student>

</html:tr>

<html:tr>

<student>

<html:td> <name>张三</name> </html:td>

<html:td> <origin class="myclass">北京</origin> </html:td>

<html:td> <age>14</age> </html:td>







<html:td> <telephone>82873425</telephone> </html:td>

</student>

</html:tr>

</html:table>

</roster>




ex_5_4.css文件内容如下: 



roster,student {font-size:15pt;font-weight:bold; color:blue; display: block; margin-bottom: 5pt;}

origin,age,telephone {font-weight:bold; font-size:12pt; display:block; color:block; margin-left: 20pt;}

name {font-weight:bold;font-size:14pt;display:block;color:red;margin-top: 5pt;

margin-left:8pt;}





此时,文件ex_5_4.xml在IE浏览器显示的结果如图55所示。




图55使用CSS将XML文档按表格输出






视频讲解


5.3用XSL控制XML文档在浏览器中的显示
5.3.1XSL概述

可扩展样式表语言(eXtensible Stylesheet Language,XSL)是由W3C于1999年11月制定的。XSL自提出以来争议颇多,前后经过了几番大的修改。2017年6月,W3C发布了XSLT的3.0版本。2021年3月,W3C发布了XSLT 2.0版本的第二版。

CSS通过创建XML元素的样式单来格式化XML文档,并且将其显示出来。而XSL采取的方式更加引人注目,它将XML文档转换为一个新的文档(包括HTML文档),通过浏览器或其他应用程序就可以显示出来。

XSL本身也是遵循XML文档格式规范的一种标识语言,它提供的强大功能远远超过CSS,如将元素再排序等。简单的XML文档可以通过CSS来转换输出,然而复杂的、高度结构化的XML文档则只能依赖于XSL极强的格式化能力展现给用户。

XSL和CSS之间的异同如下。

(1)  XSL与CSS在很多功能上是重复的,但是它比CSS功能强大。不过XSL的强大功能与其复杂性是分不开的。

(2)  CSS只允许格式化元素内容,不允许改变或安排这些内容。但XSL没有这些限制,它可以提取元素、属性值、注释文本等几乎所有的文档内容。在XML领域,用XSL来格式化文档是未来发展的方向。

(3)  CSS是一种静态的样式描述格式,其本身不遵从XML的语法规范。而XSL不同,它是通过XML进行定义的,遵守XML的语法规则,是XML的一种具体应用。也即XSL本身就是一个XML文档,系统可以使用同一个XML解释器对XML文档及其相关的XSL文档进行解释处理。

XSL由两个关键部分组成: 一个为转换引擎,将原始文档树(源树)转换为能够显示的文档树(结果树),这个过程称为树转换;  另一个为格式化符号集,该符号集可以定义应用XML数据上的复杂的格式化规则,这个过程称为格式化。格式化符号集又称为格式对象(Formatted Object,FO)。

到目前为止,W3C还未能出台一个得到多方认可的FO,但是描述树转换的这一部分协议却日趋成熟,已从XSL中分离出来,另取名为XSLT(XSL Transformation),正式推荐标准于2007年1月问世,现在所说的XSL都是指XSLT。与XSLT一同推出的还有其配套标准XPath,这个标准用来描述如何识别、选择、匹配XML文档中的各个构成元件,包括元素、属性、文字内容等。

如前所述,XSLT主要的功能就是转换,它将一个没有形式表现的XML文档作为一个源树,将其转换为一个有样式信息的结果树。在XSLT文档中定义了与XML文档中各个逻辑成分相匹配的模板,以及匹配转换方式。值得一提的是,尽管制定XSLT规范的初衷只是


图56XSLT转换过程


利用它来进行XML文档与可格式化对象之间的转换,但它的巨大潜力却表现在它可以很好地描述XML文档向任何一个其他格式的文档进行转换的方法,例如转换为另一个逻辑结构的XML文档、HTML文档、PDF文档、XHTML文档、VRML文档、SVG文档等。转换过程如图56所示。

使用XSL定义XML文档显示方式的基本思想: 通过定义转换模板,将XML源文档转换为带样式信息的可浏览文档。最终的可浏览文档可以是HTML格式、FO格式,或者其他面向显示方式描述的XML格式(如前面提到的SVG和SMIL),限于目前浏览器的支持能力,大多数情况下是转换为一个HTML文档进行显示。

在XML中声明XSL样式单的方法与声明CSS的方法大同小异: 



<?xml-stylesheet type="text/xsl" href="xsl文件" ?>



下面先来看一个XSLT的简单例子。通过剖析这个例子,读者可以掌握一些XSLT的基本语法和功能,甚至可以照葫芦画瓢写出自己的XSLT文档。

【例55】下面是描述了包括三张CD价目表的XML文件ex_5_5.xml:



<?xml version="1.0" encoding="iso-8859-1" ?>

<?xml-stylesheet type="text/xsl" href="ex_5_5.xsl"?>

<CATALOG>

 <CD ID="001">

<TITLE>Empire Burlesque</TITLE>

<ARTIST>Bob Dylan</ARTIST>

<COUNTRY>USA</COUNTRY>

<COMPANY>Columbia</COMPANY>

<PRICE>10.90</PRICE>








<YEAR>1985</YEAR>

 </CD>

 <CD ID="002">

<TITLE>Hide your heart</TITLE>

<ARTIST>Bonnie Tylor</ARTIST>

<COUNTRY>UK</COUNTRY>

<COMPANY>CBS Records</COMPANY>

<PRICE>9.90</PRICE>

<YEAR>1988</YEAR>

 </CD>

 <CD ID="003">

<TITLE>Greatest Hits</TITLE>

<ARTIST>Dolly Parton</ARTIST>

<COUNTRY>USA</COUNTRY>

<COMPANY>RCA</COMPANY>

<PRICE>9.90</PRICE>

<YEAR>1982</YEAR>

 </CD>

</CATALOG>




下面是控制价目表显示的XSL文件ex_5_5.xsl: 



<?xml version="1.0" encoding="iso-8859-1"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:template match="/">

<html>

 <body>

<table border="2" bgcolor="yellow">

 <tr><th>Title</th> <th>Artist</th></tr>

 <xsl:for-each select="CATALOG/CD"> <!--对XML文档树中根元素下的CD元素

 循环-->

<tr>

<td><xsl:value-of select="TITLE"/></td><!--提取TITLE元素的值-->

<td><xsl:value-of select="ARTIST"/></td><!--提取ARTIST元素的值-->

</tr>

 </xsl:for-each>

</table>

 </body>

</html>

 </xsl:template>

</xsl:stylesheet>







图57使用XSL显示XML文档



将上面的XML文件和XSL文件放在一个目录中,用IE浏览器打开XML文件,显示结果如图57所示。

5.3.2XSL模板元素

从例55可知,XSL样式文档的基本结构如下。

(1)  以下面的指令作为文档开头(其中还可以包含其他属性,字符集也有许多选项)。



<?xml version="1.0" encoding="utf-8">


(2)  通过xsl: stylesheet xmlns: xsl来声明XSL名称空间。为使用新版本XSLT,应将http://www.w3.org/TR/WDxsl名称空间换成http://www.w3.org/1999/XSL/Transform。特别注意,采用不同的名称空间在浏览器中显示的结果可能会不一样。

(3)  通过xsl: template定义模板来描述XML文档的显示格式。这是XSL的主要部分。

(4)  通过XML数据的引用指明显示的数据。

(5)  其中包含了大量XHTML语句的各种标记,标记必须配对。

(6)  通过xsl: foreach、xsl: if、xsl: choose等语句进行数据的循环处理、条件处理、选择处理等工作。

(7)  可以嵌入JavaScript或VBScript脚本语句或程序,使XSL具有更强大的运算功能。

在XSL中,数据的显示格式被设计细化成一个个模板,最后再将这些模板组合成一个完整的XSL。这种方法可以使用户先从整体上考虑整个XSL的设计,然后将一些表现形式细化成不同的模板,再具体设计这些模板,最后将它们整合在一起。这样,宏观与微观设计的结合,更符合人们的条理化、规范化要求。由于XML的数据保存在具有严格层次结构的各个元素中,这种结构非常适合采用模板化的格式样式。图58为用模板格式化XML文档示意。




图58用模板格式化XML文档示意


模板定义好了后,可通过calltemplate或applytemplates来调用模板,其过程就如同在C语言中定义了一个函数,就可在程序中需要的地方进行函数调用。

1. 定义模板的语法结构

定义模板的语法结构为: 



<xsl:template match="node-context" name="template name">…

</xsl: template>




其中的属性含义如下。

(1)  match确定什么样的情况下执行此模板,也即源XML文档中哪些节点应该被相关的模板所处理,在此处使用XML文档中节点的名字;  其中最上层的模板必须将match设为“/”。在一个XSL文档中必须有一个根模板,而且是唯一的。

(2)  <xsl: template>元素用match属性从XML文档中选取满足条件的节点,针对这些特定的节点形成一个特定输出形式的模板。在一个XSL文档中一般要设计多个模板,在各个模板结构中描述了不同层次元素的数据显示格式、数据引用、数据处理等内容。

(3)  name属性即是为定义的模板取一个用户自定义的名称。只能通过<xsl: calltemplate>元素来调用模板。

2. 通过name属性调用模板

通过name属性调用模板的语法格式如下: 



<xsl:call-templatename="template name"/>





其中,name属性代表的模板名称和模板定义的名称相同。

3. 通过select属性调用模板

通过select属性调用模板的语法格式如下: 



<xsl:apply-templatesselect="pattern">



其中,select属性确定应调用的模板,即选取用<xsl: template>标记建立的模板。

对于设计好的模板,是通过<xsl: applytemplates>元素调用的,这样,即使以后要对这些模板做相应的修改与扩充也很方便,不至于出现互相干扰、混杂不清的情况。这种从上至下、逐层细化的设计方法,极大地减少了工作的复杂程度,也大幅减少了差错的产生,可以实现多人协作设计。在学习XSL模板时,为便于理解,可将定义模板看成定义一个函数,调用模板看成调用函数。

【例56】下面是一个对例55中CD价目表的XML文件采用call模板处理的例子。第3~9行定义了一个根模板,它是必需的。第10~17行定义了一个模板,模板名称为myTemplate,第6行按名称通过<xsl: calltemplate>标记进行模板调用。这种方式类似于函数调用。最终在浏览器中输出“CD 001:  Empire Burlesque CD 002:  Hide your heart CD 003:  Greatest Hits”。ex_5_6.xsl文件内容如下: 



1<?xml version="1.0" encoding="utf-8"?>

2<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/ Transform">

3 <xsl:template match="/"> <!--根模板是必需的-->

4<html><head> <title>模板的调用</title></head>

5<body>

6 <xsl:call-template name="myTemplate"/>   <!-- 调用模板-->

7</body>

8</html>

9 </xsl:template>

10 <xsl:template name="myTemplate" match="CATALOG/CD" >

11 <p align="center" style="font-weight:bold;"> 

12 <!--对所有CD循环处理-->

13<xsl:for-each select="CATALOG/CD"> <!--CATALOG/CD 大小写要和XML文档中一致-->

14CD <xsl:value-of select="@ID"/>: <!--提取CD的id属性的值-->

15<xsl:value-of select="TITLE"/>   ?b<!--提取每个CD的title-->

16</xsl:for-each> </p>

17</xsl:template>

18 </xsl:stylesheet>




【例57】下面是一个对例55中CD价目表的XML文档采用apply模板处理的例子。第10~17行定义了一个模板,第6行select通过<xsl:  applytemplates>标记进行模板调用。最终输出结果和例56相同。ex_5_7.xsl文件内容如下: 



1<?xml version="1.0" encoding="utf-8"?>

2<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/ Transform">

3 <xsl:template match="/">

4 <html><head><title>模板的调用</title></head>

5<body>

6 <xsl:apply-templates select="CATALOG"/>






7</body>

8 </html>

9 </xsl:template>

10 <xsl:template match="CATALOG">

11 <p align="center" style="font-weight:bold;">

12<xsl:for-each select="./CD">

13 CD <xsl:value-of select="@ID"/>:

14 <xsl:value-of select="TITLE"/>

15</xsl:for-each>

16 </p>

17 </xsl:template>

18</xsl:stylesheet>




上面的例子中,只用了一个根模板和一个自定义的模板,可根据实际情况自定义多个模板,而且可在模板中再定义模板。此过程如同函数中再调用函数,可以嵌套很多层。

5.3.3XSL选择和测试元素

XSL选择元素的作用: 用选择的方式将数据从XML文档中提取出来。这是一种在XSL中广泛应用且操作简单的获得数据的方法。XSL测试元素的过程: 先对选择的对象进行测试,然后对符合条件的记录进行预定的处理。

1. XSL选择元素

选择元素有两种不同的方式,各自的语法格式描述如下。

(1) xsl: valueof。

语法:  



 <xsl: valueof select="模式"/>



功能:  该语法的作用是从XML文档中提取指定节点的数据输出到结果树中。select属性用来指定XML文档数据节点名称。


(2) xsl: foreach。

语法: 



 <xsl: foreach  select="模式"> … </xsl: foreach>



功能: 循环处理指定节点的相同数据。通过select属性选择XML文档中的某些元素进行循环处理。

2. XSL测试元素

测试语法有以下两种方式,各自的语法格式描述如下。

(1) xsl: if。

语法:  



<xsl:if test="测试条件"> …内容…</xsl:if>




功能: 测试test属性给定的条件,当条件的值为True时执行相关内容,否则不执行。


对于测试条件,情况比较复杂。测试条件可以为一个关系表达式或逻辑表达式,其书写规则如下面的例子所示。



姓名="张三"//表示节点元素"姓名"的值为"张三"

成绩 &gt;= 90//表示节点元素"成绩"的值大于或等于90

成绩 &gt;= 90 or 成绩 &lt; 60]//表示节点元素"成绩"的值大于或等于90或小于60

@性别="女"//表示当前节点元素的"性别"属性值为"女"时




(2) xsl: choose。

语法: 



<xsl:choose>

<xsl:when test="测试条件"> …内容… </xsl:when>

<xsl:when test="测试条件"> …内容… </xsl:when>

…

<xsl:otherwise>…内容… </xsl:otherwise>

</xsl:choose>




功能:   在有多个测试条件的情况下执行满足条件(由test指定测试条件)的内容。当所有条件都不满足时执行<xsl: otherwise>指定的内容。

5.3.4XSL 常用运算符

XSL中的运算符包括选择运算符和特殊字符、逻辑运算符、关系运算符以及集合运算符,这些运算符构成的表达式可以使用在测试条件中,常用的运算符如表53所示。


表53常用的运算符



运算符
含义
运算符
含义



/
选择子元素,返回左侧元素的直接子元素;  位于最左侧的/表示选择根节点的直接子元素

//引用任意级别的后代元素
.当前元素

*通配符,选择任意元素,不考虑名字
@属性名的前缀
!*在相关节点上应用指定方法
@*通配符,选择任意属性
()*分组,明确指定优先顺序
[]应用过滤样式
: 名字作用范围分隔符,将名字作用范围前缀与元素或属性名分隔开来
[]*下标运算符,在集合中指示元素
∣集合运算符,返回两个集合的联合
or逻辑或
>大于。在XSL中,要用&gt;   表示
and逻辑与
>=
大于或等于。在XSL中,要用&gt;  =表示
not
逻辑非
<
小于。在XSL中,要用&lt;   表示
=
相等
<=
小于或等于。在XSL中,要用&lt;  =表示
!=
不等
mod 
取模
+,-,
*,div
加、减、乘、除


【例58】该例针对存放简历的XML文档ex_5_8.xml,在ex_5_8.xsl中采用了几种不同的运算符。在应用时,只需要将ex_5_8.xsl文档中的第8行进行替换。ex_5_8.xsl中第13行演示了如何直接提取birthday的值。读者可仿照此例举一反三地练习。


(1)  <xsl: foreach select="*/resume">。

说明: 此处用通配符*代替了document元素名称。对每个resume 循环处理。

(2)  <xsl: foreach select="/document/resume [grade &lt;   60]">。

说明: [ ]表示选择条件,仅循环处理成绩小于60分的学生。

(3)  <xsl: foreach select="//resume [@id='008']">。

说明: 对简历中具有id属性编号为0008的人进行处理。

(4)  <xsl: foreach select="*/resume [cellphone]">。

说明: 对简历中具有cellphone元素的人进行处理,也即对简历中提供了手机号码的人进行处理。

(5)  <xsl: foreach select="*/resume [skill='Web开发']">。

说明: 对简历中具有“Web开发”技能的所有人进行处理。


ex_5_8.xml文档内容如下: 



<?xml version="1.0" encoding="gb2312" ?>

<?xml-stylesheet type="text/xsl" href="ex_5_8.xsl"?>

<document>

 <resume id="007">

<name>李敏</name>

<sex>男</sex>

<birthday>1971-12-30</birthday>

<skill>Web开发</skill>

<skill>游戏编程</skill>

<cellphone>13983911111</cellphone>

<grade>50</grade>

 </resume>

 <resume id="008">

<name>王甜珠</name>

<sex>女</sex>

<birthday>1981-01-30</birthday>

<skill>舞蹈</skill>

<grade>80</grade>

 </resume>

</document>




ex_5_8.xsl文档内容如下: 



1<?xml version="1.0" encoding="gb2312"?>

2<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/ Transform">

3 <xsl:template match="/">

4<html><head><title>XML 技术</title></head>

5<body bgcolor="#00CC66">

6<table border="1" cellspacing="0">

7<th>姓名</th><th>性别</th>

8<xsl:for-each select="/document/resume [grade &lt; 60]">

9<tr><td><xsl:value-of select="name"/></td>

10<td><xsl:value-of select="sex"/> </td>

11</tr>

12</xsl:for-each>

13</table> 第个人的生日是<xsl:value-of select="/*/*/birthday"/>

14</body>

15</html>

16 </xsl:template>

17</xsl:stylesheet>




5.3.5XSL内置函数

XSL提供了100多个内置函数,这些函数大大方便了开发者的使用,例如用current可获得当前节点,用currentdate、currenttime分别用来返回当前日期和时间。可参阅http://www.w3schools.com/xpath/xpath_functions.asp获取所有内置函数列表。这里主要介绍几个常用的XSLT内置函数。

1. position函数与last函数


作用: 分别表示确定当前和最后一个节点元素的位置。例如:



<xsl:if test="position()!=last()">




说明: 判断当前节点元素是否为最后一个。


2. count函数


作用: 统计计数,返回符合条件的节点的个数。例如:



<p><xsl:value-of select="count(PERSON[name=tom])"/></p>




说明: 显示PERSON元素中姓名属性值为tom的有几个。


3. number函数


作用: 将属性值中的文本转换为数值。例如:



<p> The number is: <xsl:value-of select="number(book/price)"/></p>




说明: 显示书的价格。


4. substring函数


语法: 



substring(value,start,length)




作用: 截取字符串。例如:



<p><xsl:value-of select="substring(name, 1, 3)"/></p>




说明: 截取name元素的值,从第一个字母开始直到第三个。


5. stringlength(string)函数


语法: 



string-length(string)




作用: 获取字符串的长度。例如:



<p><xsl:value-of select="string-length(name)"/></p>




说明: 获取name元素的字符串长度值。


6. concat和stringjoin串连接函数


语法: 



concat(string,string,…)



或者



string-join((string,string,…),sep)




作用: 将多个字符串连接在一起。后者在连接子串时可带分隔符号。例如:



concat('XPath ','is ','FUN!') 

string-join(('We', 'are', 'having', 'fun!'), ' ')//用空格连接字符串





说明: 前者返回 'XPath is FUN!',后者返回 'We are having fun!'。


7. sum、max、min、avg函数


作用: 分别表示求和、求最大值、求最小值、求平均值。例如:



<p>Total Price= <xsl:value-of select="sum(//price)"/></p>




说明: 计算所有价格的和。其中,//表示引用任意级别的后代元素。




视频讲解



5.4XML DOM编程基础
5.4.1XML DOM简介

XML DOM是W3C提出的针对XML的文档对象模型,它独立于平台和语言,定义了一套标准的用于XML的对象和一种标准的访问与处理XML文档的方法。

对于XML应用开发来说,DOM就是一个对象化的XML数据接口,一个与语言无关、与平台无关的标准接口规范。它定义了XML文档的逻辑结构,给出了一种访问和处理XML文档的方法。利用DOM,程序开发人员可以动态地创建XML文档,遍历文档结构,添加、修改、删除文档内容,改变文档的显示方式,等等。可以这样说,文档代表的是数据,而DOM则代表了如何去处理这些数据。无论是在浏览器中还是在浏览器外,无论是在服务器还是在客户端,只要有用到XML的地方,都可利用DOM接口进行编程应用。

DOM接口中的XML分析器,在对XML文档进行分析之后,不管这个文档有多简单或者多复杂,其中的信息都会被转换为一棵对象节点树——DOM树,也即DOM将XML文档作为树结构来看待。在这棵节点树中,有一个Document根节点,所有其他的节点都是根节点的后代节点。节点树生成之后,就可以通过XML DOM接口访问、修改、添加、删除树中的节点和属性以及文本内容等。

DOM将XML文档中的每个成分看作一个节点。例如,整个文档是一个文档节点;  每个XML标签是一个元素节点;  包含在XML元素中的文本是文本节点;  每个XML属性是一个属性节点;  注释属于注释节点。

【例59】DOM把XML文件当作一种树形结构。每个元素、属性以及XML文档中的文本都可以看成树上的节点。一个节点树可以把一个XML文档展示为一个节点集,以及它们之间的连接。在一个节点树中,最上端的节点被称为根;  每个节点,除根之外,都拥有父节点;  一个节点可以有无限的子节点;  叶是无子节点的节点;  同级节点指拥有相同的父节点。下面的ex_5_9.xml文档,其DOM节点树如图59所示。



<?xml version="1.0" encoding="UTF-8" ?>

<bookstore>

 <book category="COOKING">

<title lang="en">Everyday Italian</title>

<author>Giada De Laurentiis</author>

<year>2005</year>

<price>30.00</price>

 </book>

 <book category="CHILDREN">

<title lang="en">Harry Potter</title>

<author>J K. Rowling</author>

<year>2005</year>

<price>29.99</price>

 </book>

 <book category="Web">

<title lang="en">XQuery Kick Start</title>

<author>James McGovern</author>

<author>Per Bothner</author>

<author>Kurt Cagle</author>

<author>James Linn</author>

<author>Vaidyanathan Nagarajan</author>







<year>2003</year>

<price>49.99</price>

 </book>

 <book category="Web">

<title lang="en">Learning XML</title>

<author>Erik T. Ray</author>

<year>2003</year>

<price>39.95</price>

 </book>

</bookstore>






图59XML文档的DOM节点树


5.4.2XML DOM对象

在XML DOM接口规范中,有四个基本的XML DOM对象即Document(文档)、Node(节点)、NodeList(节点列表)和NamedNodeMap(有名节点映射)。

1. Document对象

Document对象代表了整个XML文档,因此,它是整棵DOM树的根,提供了对文档中的数据进行访问和操作的入口。通过Document节点,可以访问到文档中的其他节点,如处理指令、注释、文档类型以及XML文档的根元素节点等。

创建Document对象的语法格式为: 

JavaScript/JScript:




//MSXML 2.0版本,支持DTD的处理

var doc= new ActiveXObject("Microsoft.XMLDOM")

//MSXML 3.0版本, 支持DTD、XSD的处理

var doc= new ActiveXObject("Msxml2.DOMDocument.3.0")



VBScript:



Dim docSet doc= CreateObject("Microsoft.XMLDOM")



VB: 在VB中通过[工程]|[引用]选择Microsoft XML 6.0(msxml6.dll)




Dim doc As New MSXML2.DOMDocument60'采用XML接口6.0版本

xmlDoc.async= False

xmlDoc.Load App.Path & "\books.xml"'将XML文档加载到DOC对象中

If(xmlDoc.parseError.errorCode <> 0) Then

MsgBox("You have error " & xmlDoc.parseError.reason)

Else








MsgBox doc.childNodes(0).nodeName'显示文档中第一个节点的名称

End If

Set doc= Nothing



C#:



using System.Xml;

…

XmlDocument doc=new XmlDocument();




由此可见,可以在各种应用程序中使用DOM接口,无论是客户端还是服务器端。在ASP.NET中可以使用XMLDocument类实现对Document节点的各种操作。在这里仅讨论通过JavaScript进行XML DOM编程。

Document对象的主要属性和方法分别如表54和表55所示。表格中IE、F、O、W3C分别代表浏览器Internet Explorer、Firefox、Opera和W3C标准,表示是否支持该属性或方法、从什么版本开始支持。


表54Document对象的主要属性



属性
描述
IE
F
O
W3C




async
可规定XML文件的下载是否应当被同步处理
5
1.5
9
No
childNodes
返回属于文档的子节点的节点列表
5
1
9
Yes
doctype
返回与文档相关的文档类型声明(DTD)
6
1
9
Yes
documentElement
返回文档的根节点
5
1
9
Yes
documentURI
设置或返回文档的位置
No
1
9
Yes
firstChild
返回文档的首个子节点
5
1
9
Yes
lastChild
返回文档的最后一个子节点
5
1
9
Yes
nodeName
依据节点的类型返回其名称
5
1
9
Yes
nodeType
返回某个节点的节点类型
5
1
9
Yes
nodeValue
根据节点的类型来设置或返回某个节点的值
5
1
9
Yes
text
返回某个节点及其后代的文本(仅用于IE)
5
No
No
No
xml
返回某个节点及其后代的XML文档内容(仅用于IE)
5
No
No
No





表55Document对象的主要方法



方法
描述
IE
F
O
W3C



createAttribute
(name)
创建一个拥有指定名称的属性节点,并返回新的Attr对象
6
1
9
Yes
createCDATA
Section
创建一个CDATA区段节点
5
1
9
Yes
createComment
创建一个注释节点
6
1
9
Yes
createElement
创建一个元素节点
5
1
9
Yes
createElementNS
创建一个带有指定名称空间的元素节点
No
1
9
Yes
createTextNode
创建一个文本节点
5
1
9
Yes
getElementById(id)
返回带有给定id属性值的元素。如果不存在,则返回null
5
1
9
Yes
getElementsByTagName
返回一个带有指定名称的所有元素的节点列表
5
1
9
Yes
renameNode
重命名一个元素或者属性节点


No
Yes
load(文件名)
加载一个XML文档

Loadxml("XML文档内容")
将存储在字符串中的XML文档内容加载为Document对象

save(文件名)
保存到一个XML文档


2. Node对象

Node对象在整个DOM树中具有举足轻重的地位。在DOM树中,Node对象代表了树中的一个节点,如图510所示。




图510典型的Node对象及其相互关系


XML文档中的每个成分都是一个Node对象。从Node对象继承过来的对象有Document、Element、Attribute、Text、Comment等,这些从Node对象继承过来的子对象类型如表56所示。


表56节点对象的类型



节点对象类型
描述
子对象



Document
代表整个文件对象(DOM树根  节点)
Element(至多1个),ProcessingInstruction,Comment,DocumentType
DocumentFragment
轻型文件对象(允许嵌入另一部分文档)
Element,ProcessingInstruction,Comment,Text,CDATASection,EntityReference
DocumentType
为文档定义的实体列表对象
无
EntityReference
一个实体参数对象
Element,ProcessingInstruction,Comment,Text,CDATASection,EntityReference
Element
代表元素节点对象
Element,Text,Comment,ProcessingInstruction,CDATASection,EntityReference
Attr
代表一个属性对象(属性与其他节点类型不同,它们没有父节点)
Text,EntityReference
ProcessingInstruction
处理指令对象
无
Comment
代表注释对象
无
Text
元素中的或属性中的文本内容(字符数据)
无
CDATASection
一块包含字符的文本区,这里的字符也可以是标记
无
Entity
代表实体对象
Element,ProcessingInstruction,Comment,Text,CDATASection,EntityReference
Notation
在DTD中声明的符号对象
无



注意,尽管所有的对象都继承了用于处理子类节点或父类节点的节点属性或节点对象,但是并不是所有的对象都包含子类或是父类。例如,文本节点中可能不包含子类,所以将子类节点添加到文本节点中可能会导致一个DOM错误。

Node对象的主要属性和方法如表57和表58所示。


表57节点对象的主要属性



属性
描述
IE
F
O
W3C



baseURI
返回一个节点的绝对基准URI
No
1
No
Yes
childNodes
返回一个节点的子节点的节点列表
5
1
9
Yes
firstChild
返回一个节点的第一个子节点
5
1
9
Yes
lastChild
返回一个节点的最后一个子节点
5
1
9
Yes
localName
返回一个节点的本地名称
No
1
9
Yes
namespaceURI
返回一个节点的名称空间的URI
No
1
9
Yes
nextSibling
返回下一个同胞节点
5
1
9
Yes
nodeName
返回指定节点类型的节点名称
5
1
9
Yes
nodeType
返回节点类型
5
1
9
Yes
nodeValue
设置或返回指定节点类型的节点值
5
1
9
Yes
ownerDocument
返回节点的根元素(文档对象)
5
1
9
Yes
parentNode
返回一个节点的父节点
5
1
9
Yes
prefix
设置或返回一个节点的名称空间前缀
No
1
9
Yes
previousSibling
返回上一个同胞节点
5
1
9
Yes
textContent
设置或返回当前节点及其子节点的文本内容
No
1
No
Yes
text
返回当前节点及其子节点的文本。仅IE支持
5
No
No
No
xml
返回当前节点及其子节点的XML文档内容。仅IE支持
5
No
No






表58节点对象的主要方法



方法
描述
IE
F
O
W3C



appendChild
将一个新的子节点添加到一个节点中的子类节点列表末尾
5
1
9
Yes
cloneNode
克隆一个节点
5
1
9
Yes
compareDocumentPosition
比较两个节点的文档位置
No
1
No
Yes
hasAttributes
如果节点包含属性,则返回true,否则返回false
5
1
9
Yes
hasChildNodes
如果一个节点包含子节点则返回true,否则返回false
5
1
9
Yes
insertBefore
在当前子节点之前插入一个新的子节点
5
1
9
Yes
isEqualNode
检验两个节点是否相等
No
No
No
Yes
isSameNode
检验两个节点是否相同
No
1
No
Yes
removeChild
删除一个子节点
5
1
9
Yes
replaceChild
替换一个子节点
5
1
9
Yes


下面列出了从Node对象继承过来的对象的相关属性和方法。

(1) Element对象。

Element对象表示一个XML文档中的某个元素。元素可包含属性和文本。假如某个元素含有文本,则此文本由一个文本节点来代表。文本永远被存储于文本节点中。例如,在<year>2005</year>中,其中year为一个元素节点,此节点之下存在一个文本节点,其中含有文本2005。由于元素对象也是一种Node,因此它继承了Node对象的属性和方法。表59列出了Element对象除了继承Node对象的属性和方法外新增的属性和方法。



表59Element对象的部分属性和方法


属性
描述
IE
F
O
W3C



attributes
可返回元素的属性的一个NAMEDNODEMAP
5
1
9
Yes
SCHEMATYPEINFO
可返回与元素相关联的类型信息


No
Yes
TAGNAME
可返回元素的名称
5
1
9
Yes


方法
描述
IE
F
O
W3C


GETATTRIBUTE
返回某个属性的值
5
1
9
Yes
GETATTRIBUTENS
通过名称空间返回某个属性的值
No
1
9
Yes
GETATTRIBUTENODE
以一个Attribute对象返回一个属性节点
5
1
9
Yes
GETATTRIBUTENODENS
通过名称空间返回一个属性节点对象
No

9
Yes
GETELEMENTSBYTAGNAME
返回匹配元素节点以及它们的子节点的NodeList
5
1
9
Yes
GETELEMENTSBYTAGNAMENS
通过名称空间返回匹配元素节点以及它们的子节点的NodeList 
No
1
9
Yes
HASATTRIBUTE
返回某元素是否拥有匹配某个指定名称的属性
5
1
9
Yes
HASATTRIBUTENS
返回某元素是否拥有匹配某个指定名称和名称空间的属性
No
1
9
Yes
HASCHILDNODES
返回元素是否拥有任何子节点
5
1
9
Yes
REMOVEATTRIBUTE
删除某个指定的属性
5
1
9
Yes
REMOVEATTRIBUTENS
删除某个指定的带有某个名称空间的属性
No
1
9
Yes
REMOVEATTRIBUTENODE
删除某个指定的属性节点
5
1
9
Yes
SETUSERDATA(KEY,DATA,HANDLER)
把某个对象关联到元素上的某个键


No
Yes
SETATTRIBUTE
添加一个新属性
5
1
9
Yes
SETATTRIBUTENS
通过名称空间添加一个新属性

1
9
Yes
SETATTRIBUTENODE
添加一个新的属性节点
5
1
9
Yes



(2) Attr对象。

Attr对象表示某个Element对象的一个属性。属性的容许值通常被定义在某个DTD中。

由于Attr对象也是一种节点,因此它可继承Node对象的属性和方法。不过属性无法拥有父节点,同时属性也不被认为是元素的子节点,对于许多Node对象的属性来说都将返回null。表510列出了Attr对象除了继承Node对象的属性外新增的属性。




表510Attr对象的部分属性



属性
描述
IE
F
O
W3C



name
返回属性的名称
5
1
9
Yes
specified
如果属性值被设置在文档中,则返回true;  如果其默认值被设置在某个DTD/Schema中,则返回false
5
1
9
Yes
value
设置或返回属性的值
5
1
9
Yes


(3) Text对象。

Text对象表示元素或属性的文本内容。Text对象的部分属性和方法如表511所示。




表511Text对象的部分属性和方法



属性描述
IE
F
O
W3C



属
性

data
设置或返回元素或属性的文本
6
1
9
Yes
isElementContentWhitespace
如果文本节点包含空白字符内容,则返回true,否则返回false
No
No
No
Yes
length
返回元素或属性的文本长度
6
1
9
Yes
wholeText
以文档中的顺序从此节点返回相邻文本节点的所有文本
No
No
No
Yes



方
法


appendData
向节点追加数据
6
1
9
Yes
deleteData
从节点删除数据
6
1
9
Yes
insertData
向节点中插入数据
6
1
9
Yes
replaceData
替换节点中的数据
6
1
9
Yes
replaceWholeText(text)
使用指定的文本来替换此节点以及所有相邻的文本节点
No
No
No
Yes
splitText
在指定的偏移处将此节点拆分为两个节点,同时返回包含偏移处之后的文本的新节点
6
1
9
Yes
substringData
从节点提取数据
6
1
9
Yes


(4) CDATASection对象和Comment对象。

CDATASection对象表示某个文档中的CDATA区段。CDATA区段包含了不会被解析器解析的文本。一个CDATA区段中的标签不会被视为标记,同时实体也不会被展开。其主要目的是包含诸如XML片段之类的材料,而无须转义所有的分隔符。在一个CDATA中唯一被识别的分隔符是]]>,它可标识CDATA区段的结束。CDATA区段不能进行嵌套。Comment对象表示文档中注释节点的内容。CDATASection对象和Comment对象的属性和方法相同,如表512所示。


表512CDATASection对象的部分属性和方法



属性描述
IE
F
O
W3C



属
性

data设置或返回此节点的文本61NoYes
length返回CDATA区段的长度/可返回此节点的文本的长度61NoYes

方
法

appendData
向节点追加数据
6
1
No
Yes
deleteData
从节点删除数据
6
1
No
Yes
insertData
向节点中插入数据
6
1
No
Yes
replaceData
替换节点中的数据
6
1
No
Yes
splitText
把CDATA分拆为两个节点
6
1
No

substringData
从节点提取数据
6
1
No
Yes


(5) DocumentType文档类型对象。

每个文档都包含一个DOCTYPE属性,该属性值可以是一个空值或是一个文档类型DocumentType对象。DocumentType对象提供了一个用于定义XML文档的实体对象。DocumentType对象属性如表513所示。



表513DocumentType对象的属性




属性
描述
IE
F
O
W3C



entities
返回一个包含DTD声明实体的NamedNodeMap(指定节点映射)
6
No
9
Yes
internalSubset
以字符串的形式返回内部DTD
No
No
No
Yes
name
返回DTD名称
6
1
9
Yes
notations
返回一个包含DTD声明符号的NamedNodeMap(指定节点映射)
6
No
9
Yes
systemId
返回用于确认外部DTD的系统
No
1
9
Yes


(6) parseError对象。

微软的parseError对象可被用来从微软的XML解析器中取回错误信息。在试图打开一个XML文档时,就可能发生一个解析器错误(parsererror)。通过parseError 对象可取回错误代码、引起错误的行为等。parseError对象不属于W3C DOM标准,其属性如表514所示。


表514parseError对象的属性




属性
描述



errorCode
返回一个长整数(LONG INTEGER)形错误代码
reason
返回包含错误原因的字符串
line
返回一个指明错误行数的长整数(LONG INTEGER)
linepos
返回一个指明错误位于哪个行位置的一个长整数(LONG INTEGER)
srcText
返回错误所在行的一个字符串
uri
返回指向已加载文件的URI
filepos
返回指明错误所在文件中的位置的一个长整数(LONG INTEGER)


ProcessingInstruction、DocumentImplementation以及其他对象由于不常用,此处略。

3. NodeList对象

NodeList对象是一个节点的集合,它包含了某个节点中的所有子节点对象,可用于表示有顺序关系的一组节点(例如某个节点的子节点序列)。可用GetNodeByName方法返回节点的值。可通过节点列表中的节点索引号来访问列表中的节点(索引号由0开始)。节点列表可保持其自身的更新。如果节点列表或XML文档中的某个元素被删除或添加,则列表也会被自动更新。在一个节点列表中,节点被返回的顺序与它们在XML被规定的顺序相同。NodeList对象的属性length可返回某个节点列表中的节点数目,NodeList对象的方法item可返回节点列表中处于某个指定的索引号的节点。

4. NamedNodeMap对象

NamedNodeMap对象也是一个节点的集合,利用该对象可建立节点名和节点之间的一一映射关系,从而利用节点名可以直接访问特定的节点。

NamedNodeMap对象类似于NodeList对象,主要区别是: NamedNodeMap通过名称来描述节点,而不是通过序数索引。另一个显著区别正如图510所示,NamedNodeList只应用于属性。NamedNodeList也只有一个返回节点数量的length属性,而方法如表515所示。



表515NamedNodeMap对象的方法



方法
描述
IE
F
O
W3C



getNamedItem
可返回指定的节点(通过名称)
5
1
9
Yes
getNamedItemNS
可返回指定的节点(通过名称和名称空间)


9
Yes
item
可返回处于指定索引号的节点
5
1
9
Yes
removeNamedItem
可删除指定的节点(根据名称)
6
1
9
Yes
removeNamedItemNS
可删除指定的节点(根据名称和名称空间)


9
Yes
setNamedItem
设置指定的节点(根据名称)


9
Yes
setNamedItemNS
设置指定的节点(通过名称和名称空间)


9
Yes


5.4.3XML DOM实例

XML DOM所包含的内容很多,有兴趣的读者可参阅http://www.w3school.com.cn/xmldom/index.asp和http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconXMLDocumentObjectModelDOM.asp获取详细资料。为引导读者迅速入门,下面通过具体的带有详细注解的例子来说明怎样使用XML DOM进行对XML文档的操作。

【例510】建立一个JavaScript文件ex_5_10.js用于创建Document对象。内容如下: 



function loadXMLDoc(dname) {//创建XML DOM Document 对象xmlDoc

var xmlDoc;

if(window.ActiveXObject)// 针对IE 浏览器

xmlDoc=new ActiveXObject("Microsoft.XMLDOM");

//针对 Mozilla, Firefox, Opera等浏览器

else if(document.implementation && document.implementation.createDocument) 

xmlDoc=document.implementation.createDocument("","",null);

else 

alert('Your browser cannot handle this script');

xmlDoc.async=false;

xmlDoc.load(dname); //加载XML文档到Document对象






If(xmlDoc.parseError.errorCode <> 0) alert(("You have error:" & xmlDoc. parseError.reason))

return(xmlDoc);

}




针对例59中的ex_5_9.xml文档,下列代码用XML DOM实现了对它的各种操作,可仔细阅读并理解其代码含义。



<html><head>

<script type="text/javascript" src="loadxmldoc.js"></script>

</head><body>

<script type="text/javascript">

//确认最后一个子节点为元素节点

function get_lastchild(n){

var x=n.lastChild;

while (x.nodeType!=1){

x=x.previousSibling;}

return x;

}

xmlDoc=loadXMLDoc("books.xml");  //装入books.xml文档内容到内存

var root=xmlDoc.documentElement;  //选择XML文档根节点



document.write("<h2>根节点:" + root.nodeName+"</h2>");



//1.返回第二个book元素节点中的price的文本值

var bookNode= root.childNodes[1];//得到根节点下的第二个book元素节点

var priceNode= bookNode.childNodes[3]; //得到book节点下的price子节点,处
//于第4个位置。从0开始计数

var textNode= priceNode.childNodes[0]; //得到price元素的文本节点

var textValue= textNode.nodeValue; //得到price元素的文本节点值

document.write(textValue+"<br/>") ; //输出文本节点值



//2.如何遍历XML文档 

var x=xmlDoc.getElementsByTagName('book'); //返回所有book元素的节点集合

for(i=0;i<x.length;i++){ //对每一个book元素循环

var bookChildNodeList= x[i].childNodes;

 document.write("第"+i+"个book节点下包含的元素:");

 for(j=0;j<bookChildNodeList.length;j++) {//对book节点下的各子元素循环

 var elNode= bookChildNodeList.item(j);

 var textNode= elNode.childNodes[0];//得到title元素的文本节点

 var textValue= textNode.nodeValue;//得到title元素的文本节点值

 document.write(elNode.nodeName +":"+textValue+" ; " );

 }

 document.write("<br/>");

}



//3.获取XML文档中的所有书名

var x=xmlDoc.getElementsByTagName('title'); //得到所有title元素对象

for (i=0;i<x.length;i++){

document.write(x[i].childNodes[0].nodeValue +"<br/>")//对每个title输出内容

}



//4.获取book节点的属性category的值的第一种方法

var x=xmlDoc.getElementsByTagName('book');

for(i=0;i<x.length;i++){

document.write(x[i].getAttribute('category')+"<br/>"); }








//5.获取book节点的属性category的值的第二种方法

var x=xmlDoc.getElementsByTagName('book');

for(i=0;i<x.length;i++){

var att=x.item(i).attributes.getNamedItem("category");

document.write(att.value + "<br />")

}



//6.为book节点设置一个新的属性edition和属性值

var x=xmlDoc.getElementsByTagName('book');

for(i=0;i<x.length;i++){

x.item(i).setAttribute("edition","FIRST");

}

var x=xmlDoc.getElementsByTagName("title");

for(i=0;i<x.length;i++){

//输出book中所有title和edition值

document.write(x[i].childNodes[0].nodeValue);

document.write(" - Edition:"+x[i].parentNode.getAttribute('edition')+"<br

/>");

}



//7.修改book节点中category属性的值,即设置成新值,然后删除属性值

var x=xmlDoc.getElementsByTagName('book');

for(i=0;i<x.length;i++){

x.item(i).setAttribute("category","BESTSELLER");

}

for(i=0;i<x.length;i++){

document.write(x[i].getAttribute('category')+"<br/>"); //输出所有属性值

}

for(i=0;i<x.length;i++){

y= x.item(i);

y.removeAttribute('category');

}

for(i=0;i<x.length;i++){

document.write(x[i].getAttribute('category')+"<br/>"); 

//输出所有category属性值为null

}



//8.删除末尾的<book>元素

document.write("book 节点的数量为:"+ xmlDoc.getElementsByTagName('book'). length +"<br />");



var lastNode=get_lastchild(root);

var delNode=root.removeChild(lastNode);

document.write("执行removeChild后的 book 节点数量:");

document.write(xmlDoc.getElementsByTagName('book').length);



//9.编辑文本节点内容

//得到title元素的文本节点

var x=xmlDoc.getElementsByTagName("title")[0].childNodes[0];

document.write("<br/>"+ x.nodeValue);

//从文本节点中删除从0开始的9个字符 Everyday Italian==〉Italian

x.deleteData(0,9);

//在文本节点中0位置开始添加字符 Italian==〉Easy Italian

x.insertData(0,"Easy ");

//替换文本内容中从0开始的8个字符为Lovable Easy

x.replaceData(0,8,"Lovable Easy");








document.write("==> "+x.nodeValue +"<br/>");//==〉Lovable Easy Italian



//10.在节点列表的末端添加一个节点(生成book的一个子节点)

var x=xmlDoc.getElementsByTagName('book');

var newel,newtext

for(i=0;i<x.length;i++){

newel=xmlDoc.createElement('edition');

newtext=xmlDoc.createTextNode('First');

newel.appendChild(newtext);

x[i].appendChild(newel);

}

document.write(root.xml+"<br/>");



//11.在指定的现存节点前添加一个新的子元素。增加一个book节点

var newNode=xmlDoc.createElement("book");//新建元素节点book

var newTitle=xmlDoc.createElement("title"); //新建元素节点title

var newText=xmlDoc.createTextNode("A Notebook"); //新建文本节点

newTitle.appendChild(newText); //形成title元素的文本节点

newNode.appendChild(newTitle); //形成book节点的子节点

root.insertBefore(newNode,get_lastchild(root)); //放到DOM树末节点之前

document.write(root.xml+"<br/>");



//12.替换节点列表中的一个节点

root.replaceChild(newNode,get_lastchild(root));

</script>

</body></html>




5.5XML与数据库
5.5.1SQL Server对XML的支持
1.  SQL Server 2000对XML的支持




视频讲解


(1) 使用SELECT语句中的FOR XML子句提取XML数据。

例如: 



SELECT * FROM Northwind.dbo.customersFOR XML AUTO





在一个SELECT语句中运用FOR XML子句,它有三种模式可以以不同的格式来返回XML: RAW、AUTO和EXPLICIT。RAW模式将结果中的每个记录作为一个普通的行元素来返回,它被包含在一个标签中,并将每个列的值作为一个属性。AUTO模式将每个记录作为行元素返回,根据源表或视图名称对它的元素进行命名。如果查询从一个表返回多个列,那么每个列的值就会被作为表元素的属性返回。但如果SELECT语句执行了合并操作,那么AUTO模式就代表的是子行,它们作为元素嵌套在父行下。EXPLICIT模式有几个参数,可以通过这些参数来定义返回的XML的样式。可以为每个元素定义标签,明确确定数据是如何嵌套的。FOR XML语句使我们不必再返回一个行记录集,再在客户端或中间层将它转换为XML了。

(2) 简单的HTTP URL请求。

例如,实现此功能需要在“开始”|“程序”|Microsoft SQL Server|“在IIS中配置SQLXML”所打开的“用于SQL Server的IIS虚拟目录管理”对话框中进行配置。

要通过HTTP访问一个SQL Server数据库,首先在上述对话框中设置一个虚拟目录,这个虚拟目录在HTTP和一个特定的数据库之间提供了一个链接。在对话框的虚拟目录设置中指定虚拟目录的名称、物理路径、服务器名称、数据库名称和注册信息。一旦创建了一个虚拟目录,就可通过一个URL将查询发送到数据库了。假如设置了一个叫作Northwind的虚拟目录,并在浏览器中输入了查询“http://localhost/Northwind?sql=SELECT*FROM+Shippers+FOR+XML+AUTO+&root=Shippers”,它就会返回相应的XML数据。与运用ADO或其他任何技术相比,HTTP查询会让我们更容易地访问网站或Web应用程序的数据。对于一个简单的查询语句来说,HTTP查询会很好,但对于一个更复杂的查询来说,这种格式就会变得难以理解并很难管理了。此外,这种方法也不安全,因为查询源代码是暴露给用户的。另一种可选方法是在HTTP上调用一个模板查询。一个模板查询就是一个包含SQL查询的XML文件。模板作为文件保存在服务器上。因此,如果你在一个叫作GetShippers.xml的模板中封装了Shippers SELECT查询,那么URL查询的形式就会是http://localhost/Northwind/templates/GetShippers.xml。模板也可以带有参数,当模板调用一个存储过程时,该功能会很有用。在URL查询和模板查询中,如果想从查询返回一个HTML页面,可以指定一个XSLT样式表,将它用于XML。模板查询是读取数据的一个更安全的方法,它可以被缓存以得到更好的性能。

(3) OPENXML。

OPENXML函数可以让你像操作一个表那样来运用XML数据,可以将它们转换为内存中的一个行记录集。要运用OPENXML,首先要调用sp_xml_ preparedocument存储过程,实际上,它将XML解析成一个数据树,并将那个数据的句柄传递到OPENXML函数,然后就可操作那个数据了。可以进行查询、将它插入表中等操作。OPENXML函数带三个参数: 用于XML文档内部显示的句柄、一个rowpattern参数和一个flags参数。rowpattern参数指定了应该返回原始的XML文档中的哪些节点;  flags参数指定了以属性为中心的映射(结果集中列名符合属性名)或以元素为中心的映射(结果集中列名符合元素名)。在处理完XML数据后,可以调用sp_xml_removedocument将XML数据从内存中删除。

(4) 通过SQLXML得到更多的支持(需要安装XML for SQL Server 2000 Web Release1方可使用)。

通过发布SQLXML,微软在SQL Server中提供了更多的XML支持。SQLXML包含有updategram和XML BulkLoad功能。可以在线下载最新版本的SQLXML。可以通过基于XML的模板,运用updategram来插入、更新或删除表中的数据。updategram提供了一个方法,使我们可以直接从XML更新SQL Server数据,这样就不用从XML文档得到数据,然后用一个记录集或调用一个存储过程来处理了。updategram只是可以简单地插入、更新或删除数据,如果需要查看一个值是否存在或在更新前查看一些商业规则,那么就应该用OPENXML。

虽然可用OPENXML函数和updategram来插入数据,但对于加载大量的XML数据来说,这两种方法都不实用。可用XML BulkLoad将大量的XML数据插入SQL Server表中。实际上可用SQLXML BulkLoad组件来加载数据,可从一个客户端应用程序来调用这个组件。在BulkLoad组件中,可以指定是否执行数据表检查约束(check constraint),当插入数据时是否应该锁定数据表,等等。

默认情况下,SQLXML BulkLoad不进行事务处理,但可指定所有加载的数据都是在一个单独的事务处理过程中,这样就可实现要么提交成功,要么回滚。如果用了事务处理,所有的数据在插入前都会被写进一个临时的文件。这就意味着需要足够的磁盘空间来保存临时文件,而且加载数据可能会很慢。但XML BulkLoad提供了一个很好的方法,使用户可以将大量的数据写到SQL Server中;  否则用户必须提取数据,然后用另外的方法将它加载到数据库中。

根据具体实现情况,可以在Web应用程序中通过HTTP和XSLT的XML查询来替代标准的ASP/ADO数据访问,从而得到HTML输出结果,这种方法可以极大地提高性能。

2.  SQL Server 2005对XML的支持

在SQL Server 2005中,FOR XML功能新增了根元素和元素名称的新选项,使用FOR XML调用以便可以建立拥有复杂层次关系的能力的、使得你可以定义Xpath语法来提取XML结构的Path模式。例如: 



SELECT ProductID AS '@ProductID',

ProductName AS 'ProductName'

FROM Products

FOR XML PATH('Product'), ROOT('Products')




返回结果为: 



<Products>

<Product ProductID="1">

<ProductName>Widget</ProductName>

</Product>

<Product ProductID="2">

<ProductName>Sprocket</ProductName>

</Product>

</Products>




除了增强了SQL Server 2000中现有的XML功能,SQL Server 2005还添加了一种新的本地xml数据类型,此数据类型能够用于为XML数据创建变量和列,例如: 



CREATE TABLE SalesOrders

(OrderID integer PRIMARY KEY,

OrderDate datetime,

CustomerID integer,

OrderNotes xml)





可以使用xml数据类型存储数据库中的标记文档或半结构化数据。列和变量可以用于非类型XML和类型XML,其中,后者是由XML架构定义(XSD)架构验证的。开发人员可以使用CREATE XML SCHEMA COLLECTION语句为数据验证定义架构,例如: 



CREATE XML SCHEMA COLLECTION ProductSchema AS

'<?xml version="1.0" encoding="UTF-16"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<!-- schema declarations go here -->

</xs:schema>




创建架构集合后,可以通过引用该架构集合并使用其包含的架构声明关联XML变量或列。例如: 



CREATE TABLE SalesOrders

(OrderID integer PRIMARY KEY,

OrderDate datetime,

CustomerID integer,

OrderNotes xml(ProductSchema))




在插入或更新值时,相关架构集合中的声明将验证类型XML,出于符合或兼容性原因,有可能强制实施XML数据结构的业务规则。

xml数据类型也提供了一些方法,这些方法可以用于在实例中查询和操纵XML数据。例如,可以在xml数据类型的实例中使用query方法查询XML,如下面的示例所示:



declare @x xml

set @x=

'<Invoices>

<Invoice>



 <Customer>Kim Abercrombie</Customer>

 <Items>

<Item ProductID="2" Price="1.99" Quantity="1" />

<Item ProductID="3" Price="2.99" Quantity="2" />

<Item ProductID="5" Price="1.99" Quantity="1" />

 </Items>

</Invoice>

<Invoice>

 <Customer>Margaret Smith</Customer>

 <Items>

<Item ProductID="2" Price="1.99" Quantity="1"/>

 </Items>

</Invoice>

</Invoices>'

SELECT @x.query(

'<CustomerList>

{

for $invoice in /Invoices/Invoice

return $invoice/Customer

}

</CustomerList>')




这个例子中的查询使用了用于在文档中查找每个Invoice元素的XQuery表达式,并且从每个Invoice元素返回包含Customer元素的XML文档,其返回结果如下所示: 



<CustomerList>

<Customer>Kim Abercrombie</Customer>

<Customer>Margaret Smith</Customer>

</CustomerList>




另一个在SQL Server 2005中引入的与XML相关的显著功能是支持XML索引。为了增强XML的查询功能,可以为类型xml列创建主XML索引和辅助XML索引。主XML索引是XML实例中所有节点的细化表示,查询处理器可以使用它快速查找XML值中的节点。创建主XML索引后,可以创建辅助XML索引改善特定查询类型的性能。下面的例子就是创建主XML索引和类型PATH的辅助XML索引,这可以改善使用XPath表达式识别XML实例中节点的查询性能。



CREATE PRIMARY XML INDEX idx_xml_Notes

ON SalesOrders (OrderNotes)



CREATE XML INDEX idx_xml_Path_Notes

ON SalesOrders (OrderNotes)

USING XML INDEX idx_xml_Notes

FOR PATH





3.  SQL Server 2008对XML的支持

SQL Server 2008 中与XML相关的主要增强功能包括以下几方面。

(1) XML架构验证增强功能。

可以通过强制实施与一个或几个XSD架构符合的方法验证XML数据。架构为特定XML数据结构定义许可的XML元素和属性,并通常用于确保包括所有所需数据元素的XML文档使用正确的结构。

SQL Server 2005通过使用XML架构集合引入了XML数据验证。一般的方法是通过使用CREATE XML SCHEMA COLLECTION语句创建一个包含XML数据架构规则的架构集合,然后在定义xml列或变量时,引用架构集合的名称,这些xml列或变量必须符合架构集合中的架构规则。这样,SQL Server就会验证在架构集合的列或变量中插入或更新的、违反架构声明的任何数据。

SQL Server 2005中的XML架构支持实现完整的XML规范的大子集,并且包含了大多数通用的XML验证场景。SQL Server 2008 扩展了该支持,使其包括以下已经由用户标识的附加架构验证要求: 支持lax验证,即完全支持dateTime、time和date验证,包括时区信息保护; 改进了对union和list类型的支持。

XML架构通过any、anyAttribute和anyType声明支持XML文档中的通配符部分。



<xs:complexType name="Order" mixed="true">

<xs:sequence>

<xs:element name="CustomerName"/>

<xs:element name="OrderTotal"/>

<xs:any namespace="##other" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>

</xs:sequence>

</xs:complexType>




此架构声明定义了一个命名为Order的XML元素,该元素必须包括命名为CustomerName和OrderTotal的子元素。此外,该元素还可以包含不限数量的其他元素,但这些元素应与Order类型属于不同的命名空间。下面的XML显示了一个包含使用此架构声明定义的Order元素实例的XML文档。注意,Order中还包含一个没有在架构中显式定义的shp: Delivery元素。



<Invoice xmlns=http://adventure-works.com/order

xmlns:shp="http://adventure-works.com/shipping">

<Order>

<CustomerName>Graeme Malcolm</CustomerName>

<OrderTotal>299.99</OrderTotal>

<shp:Delivery>Express</shp:Delivery>

</Order>

</Invoice>





验证通配符部分依赖于架构定义中通配符部分的processContents属性。在SQL Server 2005中,架构可以对any和anyAttribute声明使用skip和strict的processContents值。在前面的例子中,通配符元素的processContents属性已经设置为skip,因此没有尝试验证元素的内容。尽管架构集合包括对shp: Delivery元素的声明(例如,定义一个有效传递方法列表),但该元素仍然是未验证的,除非在Order元素的通配符声明中将processContents属性设置为strict。

SQL Server 2008添加了对第三个验证选项的支持。通过将通配符部分的processContents属性设置为lax,可以对任何含有与它们相关架构声明的元素强制实施验证,但是忽略任何在架构中未定义的元素。继续前面的例子,如果将架构中通配符元素声明的declaration属性设置为lax,并为shp: Delivery元素添加一个声明,则在XML文档中的shp: Delivery元素将被验证。然而,如果替换shp: Delivery元素,则文档就包含一个在架构中未定义的元素,此元素将被忽略。

此外,XML架构规范定义了anyType声明,该声明包含anyType内容模式的lax处理。SQL Server 2005不支持lax处理,因此anyType内容会被严格验证。SQL Server 2008支持anyType内容的lax处理,因此该内容会被正确验证。

(2) XQuery增强功能。

SQL Server 2005引入了xml数据类型,提供了用于对存储在列或变量中的XML数据执行操作的大量方法。可执行的大多数操作都使用XQuery语法导航和操纵XML数据。SQL Server 2005支持的XQuery语法包括FLWOR表达式中的for、where、order by和return语句,这些语句可用于循环访问XML文档中的节点,也可用于返回值。

SQL Server 2008添加了对let语句的支持,该语句用于向XQuery表达式中的变量赋值,如下面的示例所示:



declare @x xml

set @x=

'<Invoices>

<Invoice>

 <Customer>Kim Abercrombie</Customer>

 <Items>

<Item ProductID="2" Price="1.99" Quantity="1" />

<Item ProductID="3" Price="2.99" Quantity="2" />

<Item ProductID="5" Price="1.99" Quantity="1" />

 </Items>

</Invoice>

<Invoice>

 <Customer>Margaret Smith</Customer>

 <Items>

<Item ProductID="2" Price="1.99" Quantity="1"/>

 </Items>

</Invoice>

</Invoices>'



SELECT @x.query(

'<Orders>

{

for $invoice in /Invoices/Invoice

let $count :=count($invoice/Items/Item)

order by $count

return

<Order>

{$invoice/Customer}









<ItemCount>{$count}</ItemCount>

</Order>

}

</Orders>')







这个例子返回以下XML: 



<Orders>

 <Order>

<Customer>Margaret Smith</Customer>

<ItemCount>1</ItemCount>

</Order>

<Order>

<Customer>Kim Abercrombie</Customer>

<ItemCount>3</ItemCount>



 </Order>

</Orders>




(3) XML DML增强功能。

与使用XQuery表达式对XML数据执行操作一样,xml数据类型通过其modify方法支持insert、replace value of和delete这些XML DML表达式。可以使用这些XML DML表达式操纵xml列或变量中的XML数据。

SQL Server 2008添加了对使用insert表达式中的xml变量向现有XML结构插入XML数据的支持。例如,假定一个名称为@productList的xml变量包括以下XML: 



<Products>

<Bike>Mountain Bike</Bike>

<Bike>Road Bike</Bike>

</Products>



可以使用以下代码向产品列表中插入一个新自行车: 



DECLARE @newBike xml

SET @newBike= '<Bike>Racing Bike</Bike>'

SET @productList.modify

('insert sql:variable("@newBike") as last into (/Products)[1]')





运行这段代码后,@productList变量中会包括以下XML:



<Products>

<Bike>Mountain Bike</Bike>

<Bike>Road Bike</Bike>

<Bike> Racing Bike</Bike>

</Products>




5.5.2XML与数据库的互操作过程

首先应该明确XML不是数据库,数据库系统有它自己的一套管理模式,而XML仅仅是用来存放结构化数据的文件,在这一点相当于XML文档仅仅代表着数据库中的某一个表。因此,XML不可能取代数据库,但将数据库和XML结合起来,能够完成很多以前无法完成的工作,例如异构数据交换、应用系统集成等。

开发一个访问数据库的XML应用系统需要同时借助XML编程接口和数据库编程接口,前者用于对XML文档的解析、定位和查询,所需技术包括DOM和SAX;  后者则是用于访问数据库,如数据库中数据的更新和检索等,需要利用的技术有ODBC、JDBC、ADO/ADO.NET等。

XML与数据库的互操作过程如图511所示。



图511XML与数据库的互操作过程


对于XML文档,可以通过DOM读取XML文档中的节点。如本章前面所述,DOM是W3C的一种技术标准,实际上是提供一组API来处理XML数据,可以通过JavaScript、JScript、VBScript等脚本程序来调用,也可通过C++、Java等高级语言来实现。

其次,通过DSO(Data Source Object)进行XML的数据绑定可以方便地将XML节点同HTML标记捆绑,从XML文档中读取或写入数据。DSO的工作方式有两种: 一种是同DOM类似,通过对XML节点树进行遍历来搜索节点,每次仅将节点数据同HTML的一个元素(如SPAN元素)相关联;  第二种同第一种的不同之处在于将节点数据同一个HTML多值元素(如TR元素)相关联。

样式单CSS和XSL实际上是通过给XML数据赋予一定的样式信息以使得其能够在浏览器中显示。CSS技术早在HTML 3.2中就得以实现,其关键是将HTML中的元素同预先定义好的一组样式类相关联以达到样式化的目的,而XML同样也支持这种技术。XSL同CSS有些类似,不同之处在于它是通过定义一组样式模板将XML源节点转换为HTML文档或其他XML文档。XSL实际上也同样符合XML规范,它提供了一套完整的类似控制语言的元素和属性,最终可完成丰富多彩的样式描述。




在ASP/ASP.NET页面文档中嵌入ADO/ADO.NET对象,将数据库中的数据写入XML文档或将XML数据写入数据库是微软对数据访问技术的一种扩展。

思考练习题

1. 简述什么是XML及XML与HTML的区别。

2. CSS与XSL有什么区别? 

3. 对本章的所有例子进行上机验证。




第章

6

.NET Web应用程序开发技术




学习要点

(1) 掌握C#语言编程技术。

(2) 掌握ASP.NET常用控件的使用方法。

(3) 熟悉ASP.NET的内置服务器对象。

(4) 学会配置web.config文件。

(5) 掌握ADO.NET数据库访问技术。

(6) 学会使用VS 2019创建Web服务。

(7) 掌握Web开发中的类库构建与访问。