You are on page 1of 322

21 世纪全国应用型本科计算机系列实用规划教材

XML 实用教程

主 编 丁跃潮 张 涛
副主编 叶文来 刘韵华
参 编 丁 潇 张天桥 程旭曼
内 容 简 介
可扩展标记语言 XML 是一种新的 Web 开发辅助语言,利用它可以通过 Internet/Intranet 进行信息的描
述、交换和显示。本书是学习和应用 XML 语言的实用教材,书中阐述了 XML 的基本概念、语法规则、
文档类型定义(DTD)、Schema 结构、层叠样式单(CSS)、数据源对象(DSO)、文件转换(XSLT)、文档对象
模型(DOM),还介绍了在 Java、ASP 和.NET 以及电子商务环境下 XML 的应用。为适应没有任何 Web 编
程知识的读者,还介绍了 HTML 基础知识。本书内容由浅入深,全书 13 章分初、中、高级入门 3 个层次,
适合各类读者。在讲解基本概念和基础知识的同时给出了大量实例。每章还包括了教学提示、教学目标、
小结和习题,便于读者巩固所学的知识。
本书适合具有一定计算机基础知识的读者阅读,可作为计算机及相关专业本科 Web 设计或 XML 课程
的教材,也可作为大专院校非计算机专业学习计算机基础的教学参考书和自学用书,还可供从事 Web 应
用软件设计的科研人员参考。

市版权局著作权合同登记号 图字:01-2003-8586 号

图书在版编目(CIP)数据

XML 实用教程/丁跃潮,张涛主编. —北京:北京大学出版社,2006.1


(21 世纪全国应用型本科计算机系列实用规划教材)

ISBN 7-301-10462-6
Ⅰ.X… Ⅱ.①丁…②张…Ⅲ. 可扩充语言,XML—程序设计—高等学校—教材 Ⅳ. TP312
中国版本图书馆 CIP 数据核字(2005)第 161303 号

书 名:XML 实用教程
著作责任者:丁跃潮 张 涛 主编
责 任 编 辑:周 欢
标 准 书 号:ISBN 7-301-10462-6/TP·0870
出 版 者:北京大学出版社
地 址:北京市海淀区成府路 205 号 100871
网 址:http://cbs.pku.edu.cn http://www.pup6.com
电 话:邮购部 62752015 发行部 62750672 编辑部 62750667 邮购部 62752015
电 子 信 箱:pup_6@163.com
排 版 者:北京东方人华北大彩印中心 电话:62754190
印 刷 者:
发 行 者:北京大学出版社
经 销 者:新华书店
787 毫米×1092 毫米 16 开本 20.25 印张 486 千字
2006 年 1 月第 1 版 2006 年 1 月第 1 次印刷
定 价:26.00 元
本系列教材编写目的和教学服务
《21 世纪全国应用型本科计算机系列实用规划教材》在全国的各位编写老师的共同辛
勤努力下,在编委会主任刘瑞挺教授和其他编审委员会成员的悉心指导下,经过北京大学
出版社第六事业部各位编辑的刻苦努力,终于与师生们见面了。

教材编写目的
目前,我国高等教育正迎来一个前所未有的发展机遇期。高等教育的发展已进入到一
个新的阶段。高等本科院校也逐渐演变成“研究型、学术型”和“应用型、就业型”两类。
作为知识传承载体的教材,在高等院校的发展过程中起着至关重要的作用。但目前教
材建设却远远滞后于应用型人才培养的步伐,许多院校一直沿用偏重于研究型的教材,应用
型教材比较缺乏,这势必影响应用型人才的培养。
为顺应高等教育普及化迅速发展的趋势,配合高等院校的教学改革和教材建设,坚持
“因材施教”的教学原则,注重理论联系实际,全面促进高等院校教材建设,进一步提高
我国高校教材的质量,北京大学出版社大力推出高校“应用型本科”各专业相关教材。本
系列教材不仅讲解基础理论技术,更突出工程实际应用,注重技术与应用的结合。
本套计算机系列教材的编写思想主要如下:
(1) 要符合学校、学科的计算机课程设置要求。以高等教育的培养目标为依据,注重
教材的科学性、实用性、通用性,尽量满足同类专业院校的需求。
(2) 要定位明确。要准确定位教材在人才培养过程中的地位和作用,正确处理系列教
材与系列课程、读者层次的关系,面向就业,突出应用。
(3) 合理选材和编排。教材内容应处理好传统内容与现代内容的关系,大力补充新知
识、新技术、新工艺、新成果。根据教学内容、学时、教学大纲的要求,制定模块化编写
体例,突出重点、难点。
(4) 体现建设“立体化”精品教材的宗旨。提倡为主干课程配套电子教案、学习指导、
习题解答、课程设计、毕业设计等教学配套用书。

教学服务
1.提供教学资源下载。本系列大部分教材中涉及到的实例(习题)的原始图片和其他
素材或者是源代码、原始数据等文件,都可以在相关网站上下载。每本教材都配有 PPT 电
子教案,老师可随时在网络上下载并可修改为适合自己教学的 PPT。
2.提供多媒体课件和教师培训。针对某些重点课程,我们配套有相应的多媒体课件,
对大批量使用本套教材的学校,我们会免费提供多媒体课件。另外,我们还将免费提供教
师培训名额,不定期组织老师进行培训。
3.欢迎互动。欢迎使用本系列教材的老师和同学提出意见和建议,有建设性的将给予
奖励;同时有教材或者专著出版要求的老师,请与我们联系。
北京大学出版社第六事业部(http://www.pup6.com)
《21 世纪全国应用型本科计算机系列实用规划教材》

专家编审委员会
(按姓氏笔画排名)

主 任 刘瑞挺

副主任 胡昌振 段禅伦

崔广才 谢红薇

委 员 叶俊民 杨 璐 陈天煌 范冰冰

陈仲民 胡 明 秦 锋 龚声蓉
《21 世纪全国应用型本科计算机系列实用规划教材》

分系列专家编审委员会名单
(按姓氏笔画排名)

计算机应用技术——
主 任 胡昌振
副主任 杨 璐 龚声蓉
委 员 云 敏 马秀峰 李 明 肖淑芬 周松林
杨长生 钟 声 赵忠孝 高 巍

软件开发与软件工程——
主 任 谢红薇
副主任 叶俊民 陈天煌
委 员 王建国 孙 辉 吕海莲 李福亮 何朝阳
张世明 陈佛敏 贺 华 赵绪辉 徐庆生
徐 辉

硬件与网络技术——
主 任 崔广才
副主任 范冰冰 胡 明
委 员 龙冬云 冯嘉礼 曲朝阳 汤 惟 张有谊
董春游 程小辉

专业基础课——
主 任 段禅伦
副主任 陈仲民 秦 锋
委 员 王昆仑 王 虹 仇 汶 田敬军 刘克成
朴春慧 吴晓光 苏守宝 陈付贵 昝风彪
谭水木 魏仕民
21 世纪全国应用型本科计算机系列实用规划教材
联合编写学校名单(按拼音顺序排名)
1 安徽财经大学 23 杭州师范学院

2 安徽工业大学 24 合肥工业大学

3 安阳师范学院 25 合肥学院

4 北华大学 26 河北经贸大学

5 北京化工大学 27 河南科技学院

6 北京建筑工程学院 28 黑龙江八一农垦大学

7 北京理工大学 29 黑龙江科技学院

8 渤海大学 30 湖南大学

9 长春大学 31 湖北经济学院

10 长春工业大学 32 孝感学院

11 长春理工大学 33 湖州师范学院

12 长春税务学院 34 华北科技学院

13 滁州学院 35 华南师范大学

14 楚雄师范学院 36 华中农业大学

15 东北电力大学 37 华中师范大学

16 福建工程学院 38 华北水利水电学院

17 福建师范大学 39 淮北煤炭师范学院

18 广西财经学院 40 黄石理工学院

19 桂林工学院 41 吉林农业大学

20 哈尔滨理工大学 42 集美大学

21 海南大学 43 江汉大学

22 韩山师范学院 44 江苏科技大学
45 内蒙古大学 64 苏州大学

46 南昌工程学院 65 台州学院

47 南京航空航天大学 66 太原理工大学

48 南开大学 67 太原师范学院

49 南阳理工学院 68 唐山师范学院

50 宁波工程学院 69 同济大学

51 平顶山学院 70 皖西学院

52 青岛理工大学 71 武汉大学

53 青岛科技大学 72 武汉科技学院

54 青海民族学院 73 武汉理工大学

55 曲阜师范大学 74 武夷学院

56 山西大学 75 忻州师范学院

57 山西广播电视大学 76 新疆石油学院

58 陕西理工学院 77 许昌学院

59 上海第二工业大学 78 玉溪师范学院

60 上海海事大学 79 浙江工业大学之江学院

61 沈阳大学 80 衢州广播电视大学

62 沈阳化工学院 81 中国农业大学

63 石家庄铁道学院 82 中国石油大学
前 言

可扩展标记语言(eXtensible Markup Language, XML)作为一种计算机技术出现不到 8


年。虽然它是一种表面上非常简单的技术,但对计算机软件、数据库管理和 B2B 通信世界
的广泛适用性和深远影响令人惊讶。这种基于标记的可扩展语言提供强大的功能,不但可
以为构建数据提供一种高度结构化而且易于处理的方式,而且能够存储、交换关于数据意
义的信息,是跨平台的信息交换的主要途径。人们越来越发现 HTML 这种语言已经远远不
能满足网络潜在应用能力的需要,而 XML 良好的格式、灵活的 Web 应用、便捷的数据处
理、面向对象的特点、开放的标准和数据的选择性更新等优越性受到业界的青睐。
本书系统介绍了设计和使用 XML 文档所必需的基本技术,以及很多非常重要的相关
技术。通过本书学习,使学生对 XML 语言有一个全面的了解,掌握相关的主要知识点,
在软件设计中运用 XML 技术灵活地进行信息的描述、交换和显示。全书共分 13 章。
第 1 章介绍 XML 这一全新的标识语言的引导知识,包括标记语言发展,XML 的特点、
应用前景、数据结构、开发和应用环境,最后建立简单的引例。
第 2 章叙述了网页设计的基本概念及 HTML 的基本知识,包括 HTML 文档的基本结
构、常用 HTML 元素标识功能及使用方法等,适合于没有 HTML 网页设计知识而直接学
习 XML 的学生。
第 3 章讲解了 XML 常用语法、基本规则、XML 的相关技术和 XML 名称空间,并讲
述编辑 XML 文档的步骤。
第 4 章论述 DTD 的作用,详细说明 DTD 元素、属性和实体的语法规则,并讲解了 DTD
的使用方法,给出综合实例。
第 5 章介绍 XML Schema 的基础知识, Schema 中元素、属性和类型等构件,模式定
义基本要求以及命名空间的概念。
第 6 章首先让读者了解 CSS 的作用,介绍了 CSS 语法及常见的 CSS 属性的设置,并
以实例的方式讲述了 XML 中如何使用 CSS。
第 7 章介绍 XML 作为数据源对象的相关技术,数据岛的概念、数据绑定的方法、支
持 DSO 的 HTML 标记、XML 文件的嵌入和 XML 数据源对象的综合运用。
第 8 章讲述了 XSL 的基本概念,着重讲解 XSLT 转换语言,XSLT 文档的编写,模板
的规则及应用模板,XSLT 的转换执行过程,实现 XSLT 的方式。
第 9 章介绍文档对象模型的概念和基础知识,以实例说明客户端和服务器端加载 XML
的方法和出错处理,并介绍了 XML 的结点接口。
第 10 章先介绍 Java 的特点、开发环境,然后讲述在 Java 环境下使用 DOM 加载 XML、
访问 XML 元素与属性、创建 XML 文件、转换 XML 文件为 HTML 的方法。
第 11 章阐述 ASP 的概念、ASP 内建对象、ADO 基本功能和 ASP 环境下 XML 的运用,
使学生掌握如何利用 ASP、ADO 与 XML 结合的方法,对数据库的操作。
第 12 章对 ebXML 进行了简单介绍,包括 ebXML 的概念、设计目标、任务、技术体
·VI· XML 教程

系结构、应用过程以及 ebXML 展望。


第 13 章介绍了 Microsoft .NET Framework 的基本概念,.NET 进行处理 XML 文档的方
式,使用数据集存储和处理 XML 文档,综合应用.NET 技术建设一个网上书店。
前 6 章属于 XML 基础知识,满足一般简单应用;第 7 章~第 9 章属于中级内容,实
现对 XML 的较全面掌握和系统应用;第 10 章~第 13 章属于高级应用的入门,为学生增
添新的视点。书中在脚本语言方面兼顾 VBScript 和 JavaScript,在 Web 应用的体系结构上
兼顾 ASP/ASP.NET 和 J2EE 两大主流。在教学过程中,各学校可以根据课时量多少和专业
方向取舍相关内容。
全书力求使学生能够把 XML 与网页设计技术相结合,特别是与数据库技术结合,灵
活地进行信息的描述、交换和显示。各章节语法介绍简明易懂,避免复杂的理论介绍。选
择通俗的实例进行导学,使学生能够上手。实例的代码作了必要的注解,全部实例代码可
在网上下载,网址 http://cec.jmu.edu.cn/book),并将在该网站上提供“XML 网上教学平台”,
供教师教学使用或参考。
本书集中了国内 6 所高等院校 XML 技术领域教师的智慧,本书主编为丁跃潮、张涛,
副主编为叶文来、刘韵华。其中,第 1、7、9 章由丁跃潮编写,第 2 章由张涛和张天桥编
写,第 3、4 章由丁潇编写,第 5 章由叶文来和张天桥编写,第 6 章由程旭曼和张涛编写,
第 8、13 章由叶文来编写,第 10、12 章由刘韵华编写,第 11 章由张涛和程旭曼编写,全
书由丁跃潮统稿。
由于时间仓促,且作者经验和水平有限,书中难免有遗漏或错误,敬请指正,至此先
表示诚挚的谢意。
编 者
2005 年 10 月 10 日

·VI·
信息技术的应用化教育
(代丛书序)

刘瑞挺/文
北京大学出版社第六事业部组编了一套《21 世纪全国应用型本科计算机系列实用规划
教材》。为了做好这项工作,他们制订了详细的编写目的、丛书特色、内容要求和风格规范。
在内容上强调面向应用、任务驱动、注重实例分析、培养能力;在风格上力求文字精练、
脉络清晰、图表丰富、版式明快。

一、组编过程
2004 年 10 月,该部开始策划教材丛书,派出编辑分别深入各地高校,了解教学第一
线的情况,物色合适的作者。2005 年 4 月 16 日在北京大学召开了“《21 世纪全国应用型
本科计算机系列实用规划教材》研讨会”。来自全国 73 所院校的 102 位教师汇聚一堂,共
同商讨应用型本科计算机系列教材建设的思路,并对规划选题进行了分工。2005 年 7 月 21
日在青岛又召开了“《21 世纪全国应用型本科计算机系列实用规划教材》审纲会”。编审
委员会成员和 46 个选题的主编、参编,共 100 多位教师参加了会议。审稿会分专业基础课、
软件开发与软件工程、硬件与网络技术、计算机应用技术等小组对大纲及部分稿件进行了
审定,力争使这套规划教材成为切合当前教学需要的高质量的精品教材。

二、转变观念
为了搞好这套教材,要转变一些重要的观念。
首先,需要转变的观念就是大学及其培养人才的定位。大学并不都是“研究型”的,每
个大学生不一定都当科学家。事实上,大多数学校应该是“应用型”的,大学生将直接进
入社会基层、生产一线、服务前沿,成为各行各业的实践者和带头人。
其次,应该转变的观念就是教材建设的思路。许多人偏爱于“研究型”的教材,即使
写“应用型”教材,也多半是对前者进行删繁就简、避虚就实,这样还不能产生真正“应
用型”的教材。因此,以“学科”为中心、追求雄厚“理论基础”的传统应该被以“应用”
为导向、追求熟练“实践技能”的思路所取代。
第三,必须转变对计算机技术的认识。20 年前,有人把计算机技术理解为 BASIC 编
程;10 年前,有人把 Windows 95 和 Word 称为计算机文化;今天,中小学陆续开出《信息
技术》课,有人对此怀疑观望,其实它意义深远。以计算机为核心的信息技术,今后 20 年
的发展主题将是在各个领域的应用普及。大学计算机应用型本科的教材建设应该面向信息
技术的深入应用,而不是相反,因为信息时代已经不是遥远的未来。

三、信息技能
以计算机为核心的信息技术,从一开始就与应用紧密结合。例如,ENIAC 用于弹道计
算,ARPANET 用于资源共享以及核战争时的可靠通信。即使是非常抽象的图灵机模型,也
II

与第二次世界大战时图灵博士破译纳粹密码的工作相关。
今天的信息技术有三个重要的特点:
第一,信息技术是计算机与通信技术融合的辉煌成果。长期以来,计算机技术和通信
技术并行不悖地独立发展。20 世纪后半叶,两者相互渗透,产生了程控电话、数据通信、网
络技术、高清晰电视,世界各国构建了全球的、宽带的、网站密布的信息高速公路,出现
了无处不在的手机通信和移动办公系统、随身听、数码摄录相机、家庭影院、智能控制系
统,还有越来越多的嵌入式系统。人们的工作方式和生活方式都发生了质的飞跃。
第二,信息技术与各行各业紧密结合。我国的职业门类有:农林牧渔、交通运输、生
化与制药、地矿与测绘、材料与能源、土建水利、制造、电气信息、环保与安全、轻纺与
食品、财经、医药卫生、旅游、公共事业、文化教育、艺术设计传媒、公安、法律,这些
门类都需要信息技术。
第三,在发展初期,以计算机为核心的信息技术是一项专门技术,只有专家才需要它、
才能掌握它,在专家与平民之间有很深的“信息鸿沟”。今天,信息技术已经不再是只有专
家才需要、才能掌握的专门技能,而是普通人都需要、也都能掌握的基本信息技能。但是,
“信息鸿沟”也迁移到普通人之间。具有信息优势的学生能良性循环,强者更强。
有了这样广阔的应用信息背景,再造计算机应用型本科的课程体系就有了基础。

四、能力结构
关于应用型计算机人才的能力结构,我们不用“宫殿”模型,而用“雄鹰”模型。前
者是建筑学模型,适合描述学科;后者是生物学模型,适合描述人才。“雄鹰”模型包括主
体、两翼、头部、尾部等,它有可成长性。
首先,数据是信息技术的主体,数据技术是基本功。通常,数据包括文字、公式、表
格、图形、图像、动画、声音、视频等等。因此,你不仅要会录入文章、绘制图表,还应
该会采集音乐、编辑视频。大家面对的是多媒体数据,应该能收集它、整理它,数据经过
整理就成为有用的信息。
其次,信息技术的两翼是数据库技术和网络技术。为了管理好、使用好数据,就必然
用到数据库技术,数据库技术是一切信息管理的基石。为了分享数据和信息,就需要网络
技术。有了上述数据主体技术和两个“翅膀”,你应该可以起飞了。
但是能飞多高,能飞多远,还应该有编程技术、智能技术、安全技术的支持。这相当
于头尾各部分的作用。编程将使大家的信息技能游刃有余。人工智能使你飞得更远,安全
技术能使你飞得更稳。
有人可能会责难我们,难道大学本科生还需要学习办公软件的技能吗?他们认为这是
让人“笑掉大牙”的事。其实,办公软件是最重要的提高生产效率的应用软件,很容易使
用,但各人使用效率的高低则十分悬殊。我们设想,今后大学生在入学前先学会计算机的基
本操作,我们再开一门高级办公技术的课,通过严格的行业及个人行为规范,对学生进行
应用化训练,养成正确的职业习惯。将来工作时能提高效率、改善质量、降低成本。这决
不是贻笑大方的事。
III

五、初步规划
应用型本科教材的规划是一个长期的战略任务,不是短期的战术行为。因此,目前的
规划教材不可能一步到位,还会保留一些传统的基础课。例如,数字电路与逻辑设计、微
机原理及接口技术、单片机原理及应用等。即使是纯硬件专业的学生,如何学这些传统硬
件课都值得商榷,更何况公共基础课。
我们将分门别类逐步建设好应用型本科的重点课程和教材:
(1) 基础类教材:信息技术导论,计算机应用基础,高级办公技术,数据与操作,密
码与安全,实用数据结构,实用离散数学……;
(2) 数据库类教材:数据库原理与应用,信息系统集成,数据采掘与知识发现……;
(3) 网络类教材:计算机网络,因特网技术,网络管理与安全,网站与网页设计……;
(4) 编程类教材:面向对象程序设计,C++程序设计,Java 程序设计……;
(5) 提高类教材:软件工程原理及应用,人工智能原理及应用……。
新教材要体现教育观念的转变,系统地研究普通高校教学改革的需求,优先开发其中
教学急需、改革方案明确、适用范围较广的教材。注重规划教材的科学性、实用性、易学
性,尽量满足同类专业院校的需求。教材内容应处理好传统与现代的关系,补充新知识、新
技术、新工艺、新成果。
我相信北京大学出版社在全国各地高校教师的积极支持下,精心设计,严格把关,一
定能够建设一批符合应用型人才培养目标的、适应计算机应用型人才培养模式的系列精品
教材,而且能建设一体化设计、多种媒体有机结合的立体化教材,为各门课程配套电子教
案、学习指导、习题解答、课程设计等辅导资料。让我们共同努力吧!

刘瑞挺教授 曾任中国计算机学会教育培训委员会副主任、教育部理科计算机科学教学指
导委员会委员、全国计算机等级考试委员会委员。目前担任的社会职务有:全国高等院校
计算机基础教育研究会副会长、全国计算机应用技术证书考试委员会副主任、北京市计算
机教育培训中心副理事长。
目 录

第1章 引论....................................................... 1 2.5.1 <table>和</table> ..................... 33


2.5.2 <caption>和</caption> ............. 36
1.1 标记语言的发展 .................................... 1
2.5.3 <tr>和</tr>................................ 36
1.1.1 SGML 的起源 ............................ 1
2.5.4 <th>和</th> .............................. 36
1.1.2 HTML 的出现 ............................ 2
2.5.5 <td>和</td> .............................. 36
1.1.3 XML 的诞生............................... 3
2.6 色彩 ...................................................... 38
1.2 XML 的特点和应用前景....................... 6
2.6.1 色彩的表示............................... 38
1.2.1 XML 的特点............................... 6
2.6.2 文本的色彩............................... 39
1.2.2 XML 的应用前景....................... 9
2.6.3 表格的颜色............................... 39
1.3 XML 文档的数据结构......................... 11
2.6.4 <hr>标记的 bgcolor 属性 ......... 40
1.3.1 层状结构数据模型................... 11
2.7 超文本链接........................................... 40
1.3.2 XML 语法的基本点................. 13
2.7.1 超文本链接的概念................... 40
1.3.3 XML 文档的结构..................... 13
2.7.2 页面链接................................... 41
1.4 XML 的开发和应用环境..................... 15
2.7.3 本地链接................................... 41
1.4.1 XML 编辑工具......................... 15
2.7.4 电子邮件链接........................... 42
1.4.2 XML 验证工具......................... 18
2.8 小结 ...................................................... 43
1.4.3 XML 解析器............................. 18
2.9 习题 ...................................................... 43
1.4.4 XML 浏览工具......................... 19
1.5 小结 ...................................................... 19 第 3 章 XML 基础 ............................................. 44
1.6 习题 ...................................................... 19
3.1 XML 标记语法..................................... 44
第 2 章 HTML 基础 .......................................... 22 3.1.1 标记的命名规则....................... 44
3.1.2 标记的使用规则....................... 44
2.1 HTML 概述 .......................................... 22
3.2 XML 文档的语法和数据结构 ............. 47
2.1.1 HTML 概述 .............................. 22
3.2.1 处理指令................................... 48
2.1.2 如何编写一个 HTML 文件 ..... 22
3.2.2 XML 的属性............................. 50
2.1.3 HTML 文件的调试 .................. 23
3.2.3 特殊字符的使用....................... 51
2.2 HTML 的标记 ...................................... 23
3.2.4 XML 文档中的注释 ................. 52
2.2.1 标记的一般特性....................... 23
3.2.5 程序中的文字 CDATA
2.2.2 常用标记 .................................. 24
标记........................................... 52
2.3 文字修饰 .............................................. 26
3.3 XML 的相关技术................................. 54
2.3.1 字号 .......................................... 26
3.3.1 CSS ........................................... 54
2.3.2 字体样式 .................................. 28
3.3.2 DTD .......................................... 54
2.3.3 特殊标记 .................................. 29
3.3.3 XML Schema ............................ 54
2.4 列表 ...................................................... 30
3.3.4 XSL ........................................... 54
2.5 表格 ...................................................... 33
·VIII· XML 实用教程

3.3.5 XML DOM ............................... 55 5.3.2 element 元素 ............................. 92


3.3.6 XML 的链接语言..................... 55 5.3.3 设置默认值和固定值............... 93
3.4 XML 名称空间..................................... 55 5.3.4 引用元素和替代....................... 94
3.4.1 名称空间的声明....................... 55 5.4 Schema 的属性声明 ............................. 95
3.4.2 名称空间的范畴....................... 56 5.4.1 创建属性................................... 96
3.5 开发工具 XMLSpy 与 XML 实例....... 57 5.4.2 为属性指派类型....................... 96
3.6 小结 ...................................................... 61 5.4.3 属性的默认值和固定值 ........... 97
3.7 习题 ...................................................... 61 5.5 Schema 的数据类型 ............................. 98
5.5.1 简单类型................................... 98
第 4 章 XML 文档类型定义 .......................... 63
5.5.2 复杂类型................................. 102
4.1 DTD 的作用 ......................................... 63 5.6 Schema 的名称空间 ........................... 106
4.2 DTD 元素 ............................................. 64 5.6.1 命名冲突................................. 106
4.2.1 元素的基本类型....................... 64 5.6.2 使用前缀解决命名冲突
4.2.2 元素的声明 .............................. 66 问题......................................... 107
4.3 DTD 属性 ............................................. 71 5.6.3 使用名称空间......................... 108
4.3.1 属性的声明 .............................. 71 5.6.4 URI、URL 和 URN................ 108
4.3.2 属性的类型 .............................. 73 5.6.5 名称空间的作用域................. 109
4.4 DTD 中的实体 ..................................... 76 5.6.6 在 XSDL 中使用的名称
4.4.1 实体的概念 .............................. 76 空间......................................... 109
4.4.2 实体的分类 .............................. 76 5.7 使用 XML Spy 建立 Schema 文档 .... 111
4.5 使用 DTD ............................................. 80 5.7.1 建立根结点............................. 111
4.5.1 内部 DTD ................................. 80 5.7.2 为根结点 book 添加子结点
4.5.2 外部 DTD ................................. 80 title、author、price、resume
4.5.3 混合 DTD ................................. 81 及属性 isbn ............................. 112
4.6 综合实例 .............................................. 82 5.7.3 为 XML 文档指定 Schema .... 113
4.6.1 DTD 片段 ................................. 82 5.8 小结 .................................................... 114
4.6.2 系统 DTD 文档 ........................ 83 5.9 习题 .................................................... 115
4.6.3 XML 文档片段......................... 83
第 6 章 层叠样式表 ..................................... 117
4.6.4 生成完整的 XML 文档............ 84
4.7 小结 ...................................................... 85 6.1 CSS 简介 ............................................ 117
4.8 习题 ...................................................... 86 6.1.1 CSS 的概念............................. 117
6.1.2 CSS 的使用............................. 118
第 5 章 XML Schema 结构 ............................ 87
6.2 设置字体属性..................................... 121
5.1 Schema 概述......................................... 87 6.2.1 font 属性集 ............................. 121
5.2 Schema 的格式和使用......................... 88 6.2.2 实例......................................... 125
5.2.1 简单实例 .................................. 88 6.3 设置色彩和背景图像属性................. 127
5.2.2 Schema 的使用 ......................... 90 6.3.1 定义前景色............................. 127
5.3 Schema 元素的声明............................. 92 6.3.2 定义背景色............................. 128
5.3.1 schema 根元素.......................... 92 6.4 设置边界属性..................................... 130

·VIII·
目 录 ·IX·

6.4.1 设置边框属性..........................130 8.2 XSL 基础 ............................................ 163


6.4.2 设置填充属性..........................132 8.2.1 XSL 的组成 ............................ 163
6.4.3 设置大小属性..........................133 8.2.2 XSLT 简介.............................. 163
6.4.4 设置定位属性..........................133 8.2.3 XPath 简介.............................. 164
6.4.5 设置页面边界属性..................133 8.2.4 XPointer、XLink 和
6.5 CSS2 新增功能 ...................................134 XQuery.................................... 166
6.5.1 @规则......................................134 8.2.5 XSL-FO................................... 167
6.5.2 新增属性 .................................135 8.3 XSLT 转换语言.................................. 168
6.5.3 其他伪类 .................................136 8.3.1 一个简单的 XSLT 示例 ......... 168
6.6 综合实例 .............................................136 8.3.2 示例中的元素分析................. 169
6.7 小结 .....................................................139 8.3.3 XSL 的执行过程 .................... 171
6.8 习题 .....................................................139 8.3.4 应用 XSLT.............................. 173
8.3.5 stylesheet 元素 ........................ 174
第 7 章 XML 数据源对象 ..............................140
8.3.6 XSLT 模板.............................. 174
7.1 数据岛、XML 数据源对象和 8.4 XSLT 模板体...................................... 175
数据绑定 .............................................140 8.4.1 索引与过滤............................. 175
7.1.1 数据岛和 XML 数据源 8.4.2 xsl:for-each.............................. 176
对象 .........................................140 8.4.3 xsl:value-of.............................. 177
7.1.2 数据绑定 .................................141 8.4.4 xsl:choose、xsl:when 和
7.1.3 XML 与 HTML 结合的 xsl:otherwise ........................... 177
优势 .........................................144 8.4.5 xsl:if、xsl:element 和
7.2 支持数据绑定的 HTML 元素 ............144 xsl:attribute.............................. 178
7.3 将 XML 文件数据嵌入 HTML...........145 8.4.6 变量......................................... 179
7.3.1 内部嵌入 XML........................146 8.4.7 执行模板................................. 179
7.3.2 使用外部的 XML 文件...........147 8.4.8 完整的样式表实例................. 181
7.4 结合脚本语言的 XML........................149 8.5 使用 XML Spy 建立 XSLT 文档....... 184
7.4.1 HTML 中的 XML 数据岛 8.6 小结 .................................................... 185
记录编辑与添加......................150 8.7 习题 .................................................... 186
7.4.2 HTML 中的 XML 数据岛
第 9 章 XML 文档对象模型 ........................ 189
记录集页面管理......................154
7.5 综合应用实例 .....................................157 9.1 DOM 基础知识 .................................. 189
7.6 小结 .....................................................159 9.1.1 DOM 的概念和组成............... 189
7.7 习题 .....................................................160 9.1.2 DOM 结构模型 ..................... 189
9.1.3 创建 document 对象 ............... 192
第 8 章 XSL 转换............................................161
9.2 客户端加载 XML............................... 193
8.1 XSL 概述.............................................161 9.2.1 加载外部 XML 文件 .............. 193
8.1.1 XSL 的意义 .............................161 9.2.2 加载 XML 文档字符串 .......... 198
8.1.2 XSLT 和 CSS 的比较..............162 9.2.3 加载 XML 文件及其转换
8.1.3 浏览器对 XSL 的支持 ............162 文件......................................... 200

·IX·
·X· XML 实用教程

9.3 服务器端加载 XML............................201 第 11 章 XML 与 ASP ..................................... 236


9.3.1 服务器端加载 XML 文件
11.1 ASP 简介 .......................................... 236
并显示所有元素......................201
11.1.1 ASP 的功能 .......................... 236
9.3.2 服务器端加载 XML
11.1.2 ASP 内建对象 ...................... 237
文件及其转换文件并
11.2 ADO 的内部对象 ............................. 238
显示所有元素..........................203
11.2.1 Connection 对象 ................... 238
9.4 parseError 对象....................................203
11.2.2 Recordset 对象...................... 241
9.4.1 parseError 属性........................203
11.2.3 Recordset 对象的方法 .......... 243
9.4.2 出现错误时的处理..................204
11.2.4 利用 Connection、Recordset
9.5 DOM 的结点接口 ...............................204
对象存取数据表数据 ........... 244
9.5.1 新增 XML 结点.......................204
11.3 XML 在 ASP 中的应用.................... 245
9.5.2 删除 XML 元素和属性...........208
11.3.1 使用 ASP 创建 XML DOM
9.5.3 访问和修改 XML DOM
对象....................................... 246
结点 .........................................209
11.3.2 使用 ASP 遍历 XMLDOM
9.6 小结 .....................................................211
对象....................................... 246
9.7 习题 .....................................................211
11.3.3 使用 ASP 显示 XML 文件... 249
第 10 章 XML 与 Java....................................213 11.3.4 使用 ASP 创建 XML 文档... 250
11.3.5 使用 ASP 转换 XML
10.1 Java 简介 ...........................................213
文档成 HTML 文档.............. 251
10.1.1 Java 的诞生 ...........................213
11.3.6 数据库记录转换成 XML
10.1.2 Java 的特点 ...........................213
文档....................................... 254
10.1.3 Java 带来的影响....................215
11.4 综合实例........................................... 256
10.2 Java 的开发环境 ...............................216
11.5 小结 .................................................. 265
10.2.1 JDK 的安装 ...........................216
11.6 习题 .................................................. 265
10.2.2 JDK 的配置 ...........................218
10.3 Java 程序加载 XML 文件.................219 第 12 章 ebXML 简介 .................................... 267
10.3.1 JAXP 简介 .............................220
12.1 ebXML.............................................. 267
10.3.2 常用的 DOM 接口 ................220
12.1.1 ebXML 的设计目标 ............. 267
10.3.3 加载 XML 文档文件.............220
12.1.2 ebXML 的概念 ..................... 268
10.3.4 设定加载 XML 文件
12.1.3 ebXML 的任务 ..................... 268
的参数 ...................................223
12.2 ebXML 的技术体系结构 ................. 268
10.4 Java 程序中访问 XML 元素
12.2.1 消息传送............................... 268
和属性................................................226
12.2.2 商务处理流程和信息建模 ... 269
10.4.1 访问 XML 元素和属性.........227
12.2.3 贸易伙伴草案和协定 ........... 270
10.4.2 使用 DOM 创建 XML
12.2.4 注册表................................... 271
文档 .......................................231
12.2.5 核心组件............................... 272
10.5 Java 程序中 XML 文件的转换.........233
12.3 ebXML 的应用过程 ......................... 272
10.6 小结 ...................................................235
12.3.1 实现阶段............................... 272
10.7 习题 ...................................................235
12.3.2 发现和获取阶段................... 272

·X·
目 录 ·XI·

12.3.3 实时运行阶段........................273 13.3 用.NET 处理 XML 文档 .................. 280


12.4 ebXML 展望......................................273 13.3.1 .NET 下与 XML 相关
12.4.1 电子商务全球化解决方案....273 的类简介............................... 281
12.4.2 可用性和互通性....................273 13.3.2 用 XmlTextReader 类
12.4.3 从现有的 EDI 和 XML 读取和解析 XML 文档 ........ 282
方案迁移 ...............................273 13.3.3 用 XmlTextWriter 类书写
12.4.4 安全性保证............................273 XML 文档............................. 286
12.5 小结 ...................................................274 13.3.4 存储和处理 XML 文档 ........ 288
12.6 习题 ...................................................274 13.3.5 XML 与数据库协调工作 ..... 292
13.4 利用 XML 和.NET 构建动态网站 .. 295
第 13 章 XML 与.NET 构建小型 Web
13.4.1 网上书店项目概述............... 295
应用 .................................................275
13.4.2 网站后台数据文件............... 296
13.1 .NET Framework 介绍 ......................275 13.4.3 网站站点架构....................... 298
13.1.1 .NET 构架..............................276 13.4.4 具体实现............................... 298
13.1.2 从 MSXML 到.NET 的 13.5 小结 .................................................. 303
XML ......................................276 13.6 习题 .................................................. 304
13.1.3 XML 分析模式......................277
参考文献 ............................................................ 305
13.2 Visual Studio .NET 集成开发环境 ...277
13.2.1 Visual Studio .NET 主界面 ...278
13.2.2 XML 编辑器..........................278

·XI·
第1章 引 论

教学提示:信息革命和信息技术的发展,改变了人类的生产和生活方式,带来了信息
社会。随着网络技术的发展,网上信息交流已逐渐成为人们交流思想、感情、成果等的主
要渠道,Internet 成为与报纸、广播、电视并驾齐驱且更优越的第四媒体。现有标记语言
HTML 和与其配合的脚本语言都是有限的。可扩展性标记语言 XML 的出现,把网络表达
语言向前推进了一大步,使得标记语言可以由编程人员按需要进行扩展,其扩展能力是无
限的,这就给 Web 编程带来了革命性进展。本章介绍 XML 这一全新的标记语言的引导知
识,包括标记语言的发展,XML 的特点、应用前景、数据结构、开发和应用环境。
教学目标:了解标记语言的发展和现状,掌握 XML 的特点,理解 XML 的应用前景,
掌握 XML 文档的数据结构和基本语法,了解常用的 XML 开发工具,学会使用一种综合性
工具。

1.1 标记语言的发展

XML 是标记语言发展的一个新阶段。为了更好地理解 XML,需要回顾标记语言的发


展过程。标记语言是随着文档处理和信息交换技术的发展而进化的。

1.1.1 SGML 的起源

SGML 的全称是 Standard Generalized Markup Language(通用标记语言标准)。 它是国


际上定义电子文档结构和内容描述的标准。
早在 1969 年,IBM 公司的工作人员 Ed Mosher、Ray Lorie 和 Charles F.Goldfarb 就开
发了一种文档描述语言 GML,用来解决不同系统中文档格式不同的问题。GML 是 IBM 许
多文档系统的基础,是一种自参考的语言,可以描述任何其他语言的语法和词汇,能够标
识出任何数据集合的结构。1974 年,Goldfarb 提出了在 GML 中实现语法合法性分析器的
概念。经过多年的发展,1984 年国际标准化协会(ISO)开始对此提案进行讨论,终于在 1986
年演变成一个国际标准(ISO 8897),并被称为 SGML。
SGML 实际上是一种通用的文档结构描述符号化语言,主要用来定义文档模型的逻辑
和物理类结构。一个 SGML 文件由 3 部分组成,即语法定义、文档类型定义(Document Type
Definition,DTD)和文档实例。语法定义部分定义了文档类型定义和文档实例的语法结构;
文档类型定义部分定义了文档实例的结构和组成结构的元素类型。文档实例是 SGML 文件
·2· XML 实用教程

的主体部分。
SGML 是很多大型组织,比如电信、飞机、汽车公司、化工企业和军队的文档标准,
它是与平台无关的、结构化的、可扩展的语言,这些特点使 SGML 在很多公司受到欢迎,
并被用来创建、处理和发布大量的文本信息。

1.1.2 HTML 的出现

1989 年,在欧洲量子实验室(CERN)的研究人员 Tim Berners Lee 开发了基于 SGML 的


非常简单的超文本版本,被称为 HTML(Hyper Text Markup Language),它是 SGML 的一个
简化子集。HTML 继承了 SGML 许多重要的特点,比如结构化、实现独立和可描述性,但
它同时也存在很多缺陷。如,它只能使用固定的有限的标记,而且只侧重于对内容的显示。
当计算机的应用水平大幅度提高的时候,人们开始对简单的 HTML 不满意。因此,又开始
对 HTML 进行修改、升级,这样就从 HTML 从 1.0 一直升到 4.0 版本,扩展了许多的命令,
使得 HTML 能够解决更多的问题。与此同时,DHTML、VHTML、SHTML 等也快速发展
起来。作为 WWW 的一个组成部分,HTML 以简单精练的语法、极易掌握的通用性和易学
性,使 Web 网页可以吸引广大网民,使互联网得以普及发展以至今日辉煌。
【例 1.1】 简单的 HTML 网页代码,如源程序 code1_1.htm 所示。
<html>
<head>
<title>简单的 HTML</title>
</head>
<body>
<h1 align="center">XML 专题系列讲座</h1>
<table border="1" width="97%" id="table1">
<tr>
<td width="38">序次</td>
<td width="96">内容</td>
<td width="54">主讲人</td>
<td width="106">时间</td>
<td>地点</td>
</tr>
<tr>
<td width="38">1</td>
<td width="96">XML 导引</td>
<td width="54">丁跃潮</td>
<td width="106">2005 年 6 月 4 日</td>
<td>计算机学院教学楼 317 教室</td>
</tr>
<tr>
<td width="38">2</td>
<td width="96">XML 文档验证</td>
<td width="54">叶文来</td>
<td width="106">2005 年 6 月 9 日</td>
<td>理学院教学楼 204 教室</td>
</tr>

·2·
第1章 引论 ·3·

<tr>
<td width="38">3</td>
<td width="96">XML 文档显示</td>
<td width="54">陈杰</td>
<td width="106">2005 年 6 月 13 日</td>
<td>计算机学院教学楼 108 教室</td>
</tr>
<tr>
<td width="38">4</td>
<td width="96">XML 网页制作</td>
<td width="54">叶文来</td>
<td width="106">2005 年 6 月 17 日</td>
<td>信息工程学院教学楼 315 教室</td>
</tr>
<tr>
<td width="38">5</td>
<td width="96">XML 应用实例</td>
<td width="54">陈杰</td>
<td width="106">2005 年 6 月 21 日</td>
<td>信息工程学院教学楼 315 教室</td>
</tr>
</table>
<ul>
<li>信息发布日期:2005 年 5 月 28 日</li>
<li>联系人:张小英、梅玉婷</li>
<li>电子邮件:<a
href="mailto:xyzhang@jmu.edu.cn">xyzhang@jmu.edu.cn</a></li>
<li>网址:<a
href="http://www.jmu.edu.cn/cs">http://www.jmu.edu.cn/cs</a></li>
</ul>
</body>
</html>

然而,因为 HTML 本身有很多缺陷。首先,HTML 是把数据和显示格式一起存放的,


不能只使用数据而不需要格式,而分离这些数据和格式较为困难。其次,HTML 对超文本
链接支持不足,属于单点链接,功能上有一些限制。再次,HTML 缺乏空间立体描述,处
理图形、图像、音频、视频等多媒体能力较弱,图文混排功能简单,不能表示多种媒体的
同步关系等,也影响 HTML 的大规模应用,特别是复杂的多媒体数据处理。最后,HTML
的标记有限,不能由用户扩展自己的标记。

1.1.3 XML 的诞生

随着 Web 上数据的增多,HTML 存在的缺点就变得不可忽略。W3C 提供了 HTML 的几


个扩展用来解决这些问题。最后,W3C 的成员认识到随着 Web 的发展,必须有一种方法能够
把数据和它的显示分离开来,决定开发一个新的 SGML 的简化子集,称为 XML(eXtensible
Markup Language),这样就导致了 XML 的诞生,它的起源和演化过程如图 1.1 所示。XML
保留了很多 SGML 标准的优点,更容易操作,便于在 WWW 环境下实现。它是为文档交换
所设计的,并以一种开放、自我描述方式定义数据结构。在描述数据内容的同时能突出对

·3·
·4· XML 实用教程

结构的描述,从而体现出数据之间的关系。这样所组织的数据对于应用程序和用户都是友
好的、可操作的。应用 XML,人们可以在自己的领域内自由地交换信息。在 1998 年 1 月,
W3C 公布了 XML 1.0 版本,成为 W3C 的标准,这是计算机史上一个重要的里程碑。
后来,W3C 又用 XML 设计出一个与 HTML 4.0 功能等价的语言,称为 XHTML
(eXtensible Hyper Text Markup Language),使之与 HTML 相兼容。
XML 和 HTML 都属于 SGML 的子集,但与 HTML 不同,XML 有 DTD。XML 是一
种元标记语言,即可以像 SGML 那样作为元标记语言来定义其他文档系统,而 HTML 和由
XML 派生的 XHTML 都是实例符号化语言,不能定义其他文档系统。两者的不同点比较如
表 1-1 所示。

GML(1969)

SGML(1985)

HTML(1993)
XML(1998)

XHTML(1999)
XML 各项技术

图 1.1 XML 的起源和演化谱系

表 1-1 HTML 与 XML 的不同点比较

比较内容 HTML XML


可扩展性 不具有扩展性 是元标记语言,可用于定义新的标记语言
侧重点 侧重于如何表现信息 侧重于如何结构化地描述信息
不要求标记的嵌套、配对等,不 严格要求嵌套、配对,并遵循 DTD 的树状
语法要求
要求标记之间具有一定的顺序 结构
可读性及可维护性 难于阅读和维护 结构清晰,便于阅读和维护
数据和显示的关系 内容描述与显示方式整合为一体 内容描述与显示方式相分离
保值性 不具有保值性 具有保值性
编辑及浏览工具 已有大量的编辑、浏览工具 编辑、浏览工具尚不成熟
结构描述 不支持深层的结构描述 文件结构嵌套可以复杂到任何程度
与数据库的关系 没有直接联系 与关系型和层状数据库均可对应和转换
超文本链接 单文件、书签链接 可以定义双向链接、多目标链接、扩展链接
大小写敏感性 不区分大小写 区分大小写

·4·
第1章 引论 ·5·

【例 1.2】 一个典型的网上书店中关于书的 XML 文档,代码如源程序 code1_2.xml 所示。


<?xml version="1.0" encoding="gb2312"?>
<!-- edited with XMLSpy v2005 rel. 3 U (http://www.altova.com) by () -->
<!-- 这个文档包含网上书店中关于书的描述,文件名 code1_2.xml -->
<books>
<book id="001" bookcategory="文艺" amount="100" remain="80"
discount="8.7">
<bookinfo>
<title>三国演义</title>
<author>罗贯中</author>
<publish>
<publisher>文艺出版社</publisher>
<ISBN>0-764-58007-8</ISBN>
<pubdate>1998.10</pubdate>
</publish>
<price>80.00 </price>
</bookinfo>
<resume>
滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白发渔樵江渚上,
惯看秋月春风。一壶浊酒喜相逢。古今多少事,都付笑谈中。</resume>
</resume>
<recommendation>经典好书</recommendation>
<chapter>
<title>宴桃园豪杰三结义 斩黄巾英雄首立功</title>
<para>话说天下大势,分久必合,合久必分。</para>
话说天下大势,分久必合,合久必分。
</para>
</chapter>
<chapter>
<title>张翼德怒鞭督邮 何国舅谋诛宦竖</title>
<para>且说董卓字仲颖,陇西临洮人也,官拜河东太守,自来骄傲。</para>
且说董卓字仲颖,陇西临洮人也,官拜河东太守,自来骄傲。
</para>
</chapter>
</book>
<book id="018" bookcategory="计算机" amount="560" remain="200"
discount="8.2">
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>

·5·
·6· XML 实用教程

</bookinfo>
<resume>本书是学习计算机专业知识的入门教材,体现计算机专业主干课程的经典教学
内容。全书注重在较低计算机知识背景下系统了解和认识计算机科学的全貌,理解基本原理,掌
握关键概念。
</resume>
<recommendation>推广教材</recommendation>
<chapter>
<title>第 1 章 计算机基础知识</title>
<para>计算机是一种能快速而高效地完成信息处理的数字化电子设备。……</para>
</chapter>
<chapter>
<title>第 2 章 计算机硬件基础</title>
<para>硬件就是构成计算机各部件的实体,是计算机中看得见、摸得到的部分。硬
件是计算机工作的前提。……</para>
</chapter>
</book>
</books>

该文件反映了书的基本信息,介绍了两本书。

1.2 XML 的特点和应用前景

XML 有许多特点,其优越性是明显的,因而具有广阔的应用前景。

1.2.1 XML 的特点

1. 具有良好的格式
XML 文档格式属于良好格式的文件。HTML 文件中的标记,有些是不需要结尾标记的,
如<br>,有些网页缺少若干结尾标记,照样能正确显示。而 XML 的标记一定要拥有结尾
标记,例如:
<name>张三</name>

即,XML 标记一定是成双成对的。如果没有结尾标记,那么在结束的“>”前,需要
有“/”,表示开头和结尾是在同一标记内,例如:
<book sales="yes"/>

2. 具有验证机制
XML 的标记是程序员自己定义的,标记的定义和使用是否符合语法,需要验证。XML
有两种验证方法。一种是 DTD,它是一个专门的文件,用来定义和检验 XML 文档中的标
记。另一种是 XML Schema,用 XML 语法描述。它比 DTD 更优越,多个 Schema 可以复
合使用 XML 名称空间,可以详细定义元素的内容及属性值的数据类型。

·6·
第1章 引论 ·7·

3. 灵活的 Web 应用
在 XML 中数据和显示格式是分开设计的,XML 元数据文件就是纯数据的文件,可以
作为数据源,向 HTML 提供显示的内容,显示样式可以随 HTML 的变化而丰富多彩。也
就是说,HTML 描述数据的外观,而 XML 描述数据本身,是文本化的小型数据库表达语
言。HTML 数据和显示格式混在一起,显示出一种样式。XML 采用的标记是自己定义的,
这样数据文件的可读性就能大大提高,也不再局限于 HTML 文件中的那些标准标记了。由
于 XML 是一个开放的基于文本的格式,它可以和 HTML 一样使用 HTTP 进行传送,不需
要对现存的网络进行改变。
数据一旦建立,XML 就能被发送到其他应用软件、对象或者中间层服务器中做进一步
的处理,或者可以被发送到桌面用浏览器浏览。XML 和 HTML、脚本、公共对象模式一起
为灵活的 3 层 Web 应用软件的开发提供了所需的技术。
4. 丰富的显示样式
XML 数据定义打印、显示排版信息主要有 3 种方法:用 CSS(Cascading Style Sheet)
定义打印和显示排版信息,用 XSLT 转换到 HTML 进行显示和打印,用 XSLT 转换成 XSL
(eXtensible Stylesheet Language)的 FO(Formatter Object) 进行显示和打印。这些方法可以显
示出丰富的样式,呈现漂亮的网页。
5. XML 是电子数据交换(EDI)的格式
XML 是为互联网的数据交换而设计的,它不仅仅是 SGML 定义的用于描述的文档,
而且在电子商务等各个领域使数据交换成为可能,如图 1.2 所示。XML 能够应用于各种领
域的原因,就是它具有到目前为止其他方法所不具备的数据描述特点,控制信息不是采用
应用软件的独有形式,而是采用谁都可以看得懂的标记形式来表现,所以 XML 最适合作
为数据交换的标准,这也是 XML 受人关注的原因。

电子商务 编辑出版

XML XML

XML XML
多媒体 网络 电子政务

XML XML

行业文档 数据仓库

图 1.2 各领域电子数据交换示意图

用 XML 可以对数据关系进行定义,形成特有的标准,因此,各行各业都在建立自己
的行业化标准,以应用于网络上处理电子商务,把后台系统通过 Web 站点表现出来。在特

·7·
·8· XML 实用教程

定的企业之间或在业界内归纳出一套标记集合,即约定用一套特定的 XML 应用语言作为交


流工具是很有价值的。
XML 还可以作为数据仓库,一个 XML 文档就是一个小的数据库,通过对数据关系的
定义形成各种关系、属性的数据,实现数据交换、上下文检索、多媒体传输等。

6. 便捷的数据处理

XML 是以文本形式来描述的一种文件格式。使用标记描述数据,可以具体指出开始元
素(开始标记)和结束元素(结束标记),在开始和结束元素之间是要表现的元素数据,这就是
用元素表现数据的方法。标记可以嵌套,因而可以表现层状或树状的数据集合。XML 作为
数据库,既具有关系型数据库(二维表)的特点,也具有层状数据库(分层树状)的特点,能够
更好地反映现实中的数据结构。XML 还可以很方便地与数据库中的表进行相互转换。XML
是不同数据结构体的文本化描述语言。它可以描述线性表、树、图形等数据结构,也能描
述文件化的外部数据结构,因此是一种通用的数据结构。
XML 使计算机能够很简易地存储和读取资料,并确保数据结构精确。由于 XML 是以
文本形式描述的,所以适合于各种平台环境的数据交换。同样由于使用文本来描述内容,
可以越过不同平台的障碍进行正常的数据交换。当然,文本形式也会因为文字代码的不同
造成不能阅读的问题,但在这一点上,XML 有着非常完美的解决方案,避免了一般语言设
计的缺漏,可支持国际化及地区化的格式。

7. 面向对象的特性
XML 的文件是树状结构的,同时也有属性,这非常符合面向对象的编程,而且也体现
出对象方式的存储,Oracle 数据库就使用了这种面向对象的特性。
XML 是信息的对象化语言。DTD 和 Schema 是界面或类(Interface 或 Class),XML 是
对象实例(Object),XSL 是方法和实现(Method 和 Implement)。XML-Data 解决了 XML 类
的 继 承 问 题 , 而 XML 中的资源(URI) 寻址(URL) 、物理实体等又构成了信息的组件
(Component)。XML 的资源描述框架(RDF)是信息导航、浏览、搜索的用户接口(UI)标准。

8. 开放的标准
XML 基于的标准是为 Web 进行过优化的。Microsoft 公司和其他一些公司以及 W3C
中的工作组正致力于确保 XML 的互用性,以及为开发人员、处理人员和不同系统及浏览
器的使用者提供支持,并进一步发展 XML 的标准。
由于 XML 彻底把标记的概念同显示分开,处理者能够在结构化的数据中嵌套程序化
的描述以表明如何显示数据。这是令人难以相信的强大机制,使得客户计算机同使用者间
的交互作用尽可能地减少了,同时减少了服务器的数据交换量和浏览器的响应时间。另外,
XML 使个人数据只能通过更新布告发生变化,减少了服务器的工作量,大大增强了服务器
的升级性能。
XML 是信息的高层封装与运输的标准。因此 XML 也是不同应用系统之间的数据接口
标准,是所有信息的中间层表示,是中间层应用服务器(AS)的通用数据接口,甚至可以用
于数据库技术的数据迁移过程、数据库报告格式中。

·8·
第1章 引论 ·9·

9. 选择性更新
通过 XML,数据可以在选择的局部小范围内更新。每当一部分数据变化后,不需要重
发整个结构化的数据。变化的元素必须从服务器发送给客户,变化的数据不需要刷新整个
使用者的界面就能够显示出来。以往只要一条数据变化了,整个页面都必须重建,这严重
限制了服务器的升级性能。XML 也允许添加新的数据和更改原有的数据。加入的信息能够
流入存在的页面,不需要浏览器发一个新的页面。

10. XML 是一个技术大家族

XML 是一套完整的方案,有一系列相关技术,包括文件数据验证、显示输出、文件转
换、文档对象和链接等。这些将在后续章节中一一阐述。
世界上永远也不会出现完美的语言,XML 也是一样,它也存在一些的缺陷。第一,它
是树状存储的,虽然搜索的效率极高,但是插入和修改比较困难。第二,XML 的文本表现
手法、标记的符号化等会导致 XML 数据以二进制表现方法的数据量增加,尤其当数据量
很大时,效率成为很大的问题。第三,XML 文档作为数据提供者使用,没有数据库系统那
样完善的管理功能。第四,由于 XML 是元置标语言,任何个人、公司和组织都可以利用
它定义新的标准,这些标准间的通信就成了巨大的问题。因此,人们在各个领域形成一些
标准化组织以统一这些标准,但是这些努力并不一定能够实现理想的结果。

1.2.2 XML 的应用前景

XML 是一个新兴的网络信息描述、组织和显示语言,是 Internet 的“世界语”,它的


开放性、严谨性、灵活性和结构性倍受网络开发者的青睐。XML 让软件产业中的许多人激
动不已,许多程序员正在奋发工作,以便将梦想变为现实。Web 的飞速发展给予了 XML
充分展示自我的空间,它提供给使用者更为强大的功能,带给程序员更为便利的开发环境,
21 世纪将是 XML 广泛应用的世纪。在以下领域,XML 将一展风采。

1. 网络服务领域

网络服务被称为“IT 产业下一波浪潮”,为了争夺这一领域的主导权,Sun 公司与


Microsoft 公司正在进行激烈而不失精彩的争夺。然而,无论是 Sun 公司还是 Microsoft 公
司,在为自己的网络服务计划宣传时,都一定会把 XML 作为一项重要内容。Microsoft 公
司总裁比尔•盖茨于 2000 年 5 月演讲时强调“新一代互联网的关键在于把握 XML”
。Microsoft
公司 CEO 史蒂夫•鲍尔默认为:“XML 是地平线上的下一场革命。XML 将成为未来互联
网领域占主导地位的标准通信协议,今后各类手持设备、台式计算机等产品都将安装使用
XML 可扩展标记语言。”
Microsoft 公司基础的网络应用平台.NET 体系完全是构架在 XML 之上的,在该体系中,
所有中间传输的文件都以 XML 的形式传输,XML 成为.NET 体系的血液。.NET 技术的普
及也带动了 XML 技术的应用。
XML 有利于信息的表达和结构化组织,从而使数据搜索更有效。XML 可以使用 URL
别名使 Web 的维护更方便,也使 Web 的应用更稳定,XML 还可以使用数字签名,使 Web

·9·
·10· XML 实用教程

的应用更广阔。而 XML 的广泛使用必然能推动 Web 不断发展,从而开创 Web 应用的新


时代。
信息发布在企业的竞争发展中起着重要的作用。服务器只需发出一份 XML 文档,客
户就可根据自己的需求选择和制作不同的应用程序以处理数据。加上 XSL(eXtensible
Stylesheet Language)的帮助,使广泛的、通用的分布式计算成为可能。

2. EDI(电子数据交换)
传统的 EDI(Electronic Data Interchange)标准缺乏灵活性和可扩展性。使用 XML,程序
能够理解在交换数据中所表示的商务数据及概念,根据明确的商务规则来进行数据处理并
给出适当的回音。现有开发的原型已证明,基于 XML 的数据交换是构造电子商务应用的
有效而可行的途径。而且 XML 能够和现有的 EDI 系统相结合,并扩展现有的 EDI 应用。
基于 XML 的数据交换必将改变 EDI 的现状,并给电子商务带来新的机遇和活力。
随着 XML 技术的发展和普及,可以预见到 XML 数据必定成为将来网络上商业数据交
换的首选。XML 数据接口会成为所有商业软件的标准配置,虽然,一般的用户可能感觉不
到它的存在,但是 XML 数据却无所不在。

3. 电子商务领域
电子商务的下一波发展浪潮必将跨越目前发展中的障碍,从而呈现出一系列变化带来
的发展生机。需要做的第一步就是将企业之间日常交流和交换的信息尽可能地电子化、统
一化,来满足不同商业系统之间的数据交换需求。Microsoft 公司的电子商务框架 BizTalk
和 OASIS 组织提出的 ebXML 电子商务框架正在朝这个方向发展,它们将在未来的电子商
务,尤其是 BToB 的电子商务中得到应用,BToB 电子商务将会全部是基于 XML 的应用。
XML 的丰富置标完全可以描述不同类型的单据,例如信用证、保险单、索赔单以及各
种发票等。结构化的 XML 文档发送至 Web 的数据可以被加密,并且很容易附加上数字签
名。因此,XML 有希望推动 EDI(Electronic Data Interchange)技术在电子商务领域的大规模
应用。

4. 数据库领域
关系型数据库行业的三大世家——IBM 公司、Oracle 公司和 Microsoft 公司都分别在它
们的数据库产品中提供了对 XML 的支持。Microsoft 公司用代号为 Yukon 的 SQL Server 来
冲杀企业级市场,作为 Microsoft 公司.NET 战略重要部分的 Yukon 正是基于 XML 技术的。
Oracle 公司也已经推出与 XML 有关的产品 XDB(XML 数据库支持)。而 IBM 公司引以为豪
的是其 DB2 和 XML Extender 的完美结合。XML 文档可以定义数据结构,代替数据字典,
用程序输出建库脚本。应用“元数据模型”技术,对数据源中不同格式的文档数据,按照
预先定义的 XML 模板,以格式说明文档结构统一描述,并提取数据或做进一步处理,最
后转换为 XML 格式输出。XML—数据库—网页或文档中的表格,这三者可以互相转换。
XML 文档从本质来看就是数据库,它是数据的集合,每个文件都含有某种类型的数据。
在许多方面看起来它和其他文件没什么区别,但作为一种“数据库”格式,XML 有一些优
点,例如,它是自描述的(所用的标记描述了数据的结构和类型,尽管缺乏语义),可交换

·10·
第1章 引论 ·11·

的,能够以树状或图形结构描述数据;同样它也有缺点,例如,它显得有些烦琐,由于要
对它进行解析和文本转换,所以数据访问速度较慢。

5. Agent(智能体)
构造一个 Agent 所面临的挑战是如何理解接收到的数据。好的 Agent 能智能地解释这
些数据,然后做出相应的反应。倘若送到 Agent 的是 XML 结构化的数据,Agent 就能很容
易地理解这些数据的含义及与它已有知识的关系。基于 XML 的数据交换对于解决 Agent
的交互性问题有重要的作用,XML 及相关技术必将促进 Agent 技术的发展。
XML 能够更准确地表达信息的真实内容,其严格的语法降低了应用程序的负担,也使
智能工具的开发更为便捷。来自不同应用程序的数据也能够转化到 XML 这个统一的框架
中,进行交互、转化和进一步的加工。
从技术上讲,XML 语言只是一种简单得不能再简单的信息描述语言,但从应用角度上
说,XML 的价值就远不止是一种信息的表达工具。事实上,借助 XML 语言,可以准确地
表示几乎所有类型的数字化信息,可以清晰地解释信息的内涵和信息之间的关联,可以在
最短的时间内准确定位用户需要的信息资源。

6. 软件设计元素的交换
XML 也可以用来描述软件设计中有关的设计元素,如对象模型,甚至能描述最终设计
出来的软件。这些基于 XML 的设计元素可以借助 Web 在开发组内进行交换,在不同的开
发工具之间交换。由 IBM 公司、Unisys 公司及其他合作伙伴提出的 XMI(XML Metadata
Interchange)正是朝该方向努力的结果,XMI 阐明了一个开放式信息交换模型,使得用对象
技术工作的软件开发者能用标准的方式在 Internet 上交换软件设计元素。另外,XML 及相
关技术使得软件的分发及更新在 Web 上更容易实现。Microsoft 公司及合作伙伴提出的
OSD(Open Software Description)正是 XML 的一个应用,它定义了一个标记集用来描述软件
包及其与各种客户平台的依赖关系。

1.3 XML 文档的数据结构

XML 的特点和优越性是由其特殊的数据结构决定的。只有理解了 XML 文档的结构,


才能更好地应用 XML 技术。

1.3.1 层状结构数据模型

XML 文档的数据结构是树状结构,相当于原来的层次型数据库系统。
层次型数据库系统(Hierarchical Database System,HDBS)是以记录型(Record Type)
为基本的数据结构,在不同记录型之间允许存在联系,层次模型在记录间只能允许单线
联系。
在层次模型中,记录型包含若干个字段,字段描述的是实体的属性。各个记录类型及
其字段必须命名,各个记录类型、同一记录类型中各个字段不能同名。每个记录类型可以

·11·
·12· XML 实用教程

定义一个排序字段,也称为码字段,如果定义该排序字段的值是唯一的,则它能唯一地标
识一个记录值。
在层次模型中,使用结点表示记录,每个结点表示一个记录类型,记录(类型)之间的
联系用结点之间的连线表示,这种联系是父子之间的一对多的联系。其限制条件为
(1) 有且仅有一个结点无双亲,这个结点称为根结点;
(2) 其他结点有且仅有一个双亲结点。
层次模型的结构就像一棵倒栽的树,根结点以外的结点有且仅有一个父结点。这就使
得层次数据库系统只能处理一对多的实体联系。
层次模型在理论上可以包含任意(有限)条记录型和字段,但任何实际的系统都会因为
存储容量或实现复杂而限制层次模型中包含的记录型个数和字段的个数。
在层次模型中,具有相同父结点的子结点称为兄弟结点,没有子结点的结点称为叶
结点。
层次模型中结点都是包含若干字段的记录型,同一结点下不允许有相同的子结点,即
兄弟结点不能相同,这是因为字段不能重复。而在 XML 文档中,有些结点是字段,有些
结点是记录,同一层次中的兄弟可以相同,因为相对于父结点来说,它们代表着记录。图
1.3 所示的是层次模型的一个抽象实例。

A1

B1 B2 Bi Bn

C1 C2 C3 C4 C5 C6 C7 C8

D1 D2 D3 D4 D5 D6

E1 E2 E3

图 1.3 层次模型

如图 1.4 所示的是图 1.3 的一个具体的 XML 实例,实际上就是本章“例 1.2”中 XML


文档“code1_2.xml”的结构图。
层次模型的优点主要是数据模型比较简单,实体间的联系固定,具有良好的完整性支
持,部门或分类性数据的描述直观;层次模型的缺点是插入和删除操作的限制比较多,查
询子结点必须通过父结点、不便于表示实际工作中非层次的数据。

·12·
第1章 引论 ·13·

books

book book book book

Recomen- Recomen-
bookinfo resume chapter bookinfo resume capter
dation dation

title author publish price title para

publisher ISBN pubdate

图 1.4 层次模型的 XML 实例

1.3.2 XML 语法的基本点

XML 要遵循 W3C 推荐规则规定的 XML 语法,这些语法的基本点有:


XML 文档只能包含一个根元素。XML 文档的根元素是包含所有被视为文档本身内容
的单个元素。根元素是在文档的序言码部分后出现的第一个元素。它也称为文档元素。
所有 XML 元素必须包含结束标记。尽管结束标记对于某些 HTML 文档元素为可选标
记,但是 XML 文档中的所有元素都必须具有结束标记。
元素的开始标记和结束标记的名称必须相同。XML 区分大小写,因此结束标记名称必
须与其伴随的开始标记名称完全匹配。
XML 元素不能重叠。如果一个元素的开始标记出现在另一个元素中,则该元素的结束
标记也必须包含在其中。
所有属性值都必须使用引号。属性值必须用单引号或双引号括起来。
在 XML 文档的文本中不能使用“<”、“>”、“&”3 个字符,这些都是对于 XML
分析程序具有特定含义的特殊字符。如果需要在 XML 文档的文本中使用这些字符,则应
使用预定义的字符或实体引用。

1.3.3 XML 文档的结构

XML 文档包含 7 个主要部分:序言码、处理指令、根元素、元素、属性、CDATA 节


和注释。XML 文档也可以不包含注释,有时也可以没有属性。这里仅对 XML 文档的各部
分做简要说明,第 3 章将做详细介绍。
1. 序言码
序言码是 XML 文档的第一部分。序言码包含 XML 声明(表明该文档是 XML 文档)、

·13·
·14· XML 实用教程

处理指令(提供 XML 分析程序用于确定如何处理文档的信息)和架构声明(确定用于验证文


档是否有效的 XML 架构)。以下是 XML 文档中序言码的示例:
<?xml version="1.0" encoding="gb2312"?>

2. 处理指令
处理指令是用来给处理 XML 文档的应用程序提供信息的,XML 分析器把这些信息原
封不动地传给应用程序,由应用程序来解释这个指令,遵照它所提供的信息进行处理。处
理指令应该遵循下面的格式:
<?处理指令名 处理指令信息?>

如:
<?xml-stylesheet type="text/xsl" href="book.xsl"?>

3. 根元素
根元素是 XML 文档的主要部分。根元素包含文档的数据以及描述数据结构的信息。
以下是 XML 文档中根元素部分的示例。
<books xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

</books>

根元素中的信息存储在两种类型的 XML 结构中:元素和属性。XML 文档中使用的所


有元素和属性都嵌套在根元素中。
4. 元素
元素是 XML 文档的基本构成单元,它用于表示 XML 文档的结构和 XML 文档中包含
的数据。元素包含开始标记、内容和结束标记。由于 XML 区分大小写,所以,开始标记
和结束标记必须完全匹配。以下是描述书籍信息的示例,publish 元素下有 3 个有关出版社
的子元素。
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>

元素可以包含文本、其他元素、字符引用或字符数据部分。没有内容的元素称为空元
素。空元素的开始标记和结束标记可以合并为一个标记,例如:
<sale/>

·14·
第1章 引论 ·15·

5. 属性
属性是使用与特定元素关联的对应“名称—值”的 XML 构造。其中包含的有关元素内
容的信息并非总是用于显示,而是用于描述元素的某种属性。使用等号分隔属性名称和属
性值,并且包含在元素的开始标记中。属性值包含在单引号或双引号中。以下是与 book 元
素关联的 bookcategory 等 4 个属性的示例。
<books>
<book id="018" bookcategory="计算机" amount="560" remain="200"
discount="8.2">
</book>
</books>

6. CDATA
在标记 CDATA 下,所有的标识、实体引用都被忽略,而被 XML 处理程序一视同仁
地作为字符数据看待。CDATA 的形式如下。
<![CDATA[ 文本内容 ]] >

CDATA 的文本内容中不能出现字符串“]]>”,另外,CDATA 不能嵌套。


7. 注释
XML 文档可以包含注释,也可以没有这项内容。注释并不由 XML 分析程序进行处理,
但用于在文档的 XML 源代码中提供必要的说明。注释以“<!--”开始,并以“-->”结束。
在这些字符之间的文本会被 XML 分析程序忽略。以下是 XML 文档中注释的示例。
<!-- 这个文件是网上书店中关于书的描述文档 -->
<document>
</books>

</books>
</document>

1.4 XML 的开发和应用环境

XML 的开发应用环境包括 XML 编辑工具、验证工具、解析工具和浏览工具 4 项内容。


目前市面上单项功能的工具和多项功能的工具有很多。现以主要功能划分并介绍如下。

1.4.1 XML 编辑工具

XML 编辑工具是 XML 最基本的工具,负责编辑 XML 文档。由于 XML 文档是文本文


件,所以具有文本编辑功能的编辑器都可以使用,最简单的就是 Windows 记事本。
1. XMLwriter
XMLwriter 的出现比较早,是由 Wattle Software 公司开发的 XML 编辑软件,汉化

·15·
·16· XML 实用教程

的界面如图 1.5 所示。该软件的主界面同 Visual Studio 非常相似,可以对 XML 文档进行编


辑,将不同的元素用不同的颜色区分开来,同时还可以利用外挂式浏览器进行预览。但它
不支持所见即所得,其页面的浏览只能用专用的浏览器。

图 1.5 汉化 XMLwriter 界面

XMLwriter 比较有特色的功能有 Load TagBar、Validate XML File、Convert Using XSL。


第一个功能用于从 DTD 和 Schema 文件中提取标记,并通过树状结构显示在 TagBar 中;
第二个功能用于验证 XML 文档的有效性;最后一个功能根据 XSL 样式单将 XML 文档转
换成相应的 HTML 文档输出。
XMLwriter 的其他功能还有给 XML 文档定义 CSS 样式、支持 SQL 等。另外,它还提
供了集成开发环境 IDE(Integrated Development Environment),面向项目管理。

2. XML Spy
XML Spy 是 Icon Information-Systems 公司的产品,显示界面如图 1.6 所示。
XML Spy 在功能上较 XMLwriter 有所提高。它支持 Unicode、多字符集,支持
Well-formed 和 Validated 两种类型的 XML 文档,并可编辑 XML 文档、DTD、Schema 以
及 XSLT。其最大特点是提供了 4 种视窗:XML 结构视窗、增强表格视窗、源代码视窗及
支持 CSS 和 XSL 的预览视窗。结构视窗以树状结构编辑 XML 文档(包括 XML、XSL 文档,
但对 DTD 文档的显示相对较为简单);增强表格视窗以表格的方式显示出文档中某一项元
素的数据库项;源代码视窗可以查看和修改文档源码,并且以不同的颜色标注不同的元素;
预览视窗采用内嵌 IE 6.0 的方式在软件内对 XML 文档进行浏览,支持 CSS 和 XSL。
XML Spy 可支持 DTD、DCD(Document Content Descriptions)、XDR(XML-Data Reduced)、
BizTalk、XSD(XML Schema Definition)的编辑与有效性检查。XML Spy 也提供集成开发环
境 IDE,但仍不支持所见即所得。

·16·
第1章 引论 ·17·

图 1.6 XML Spy 界面

XML Spy 目前的最高版本是 2005 版,可运行在 Windows 95/98/Me/XP/2000/2003 环境


中。本书主要以 XML Spy 作为编辑和验证工具,并作为基本浏览工具。

3. Stylus Studio
Stylus Studio 6 XML Professional Edition 是 XML 集成开发环境,具有功能强大的 XML
编辑器、XSLT 调试器及其他 XML 工具,从而显著提高了 XML 的开发效率,最大限度地
释放了开发人员的生产力和创造力。
Stylus Studio 提供了一套完全的 XML 工具和特性集,可用于 XML、XSL/XSLT、Xquery、
SQL/XML、Xpath、Web 设计、Web 服务程序、关联数据库、JSP 编辑、XML-Java 调试互
联以及许多其他的 XML 相关技术。Stylus Studio 是一款功能齐全的综合性开发工具。

4. Visual XML
Visual XML 由 Pierre Morel 开发,能够以树状结构显示 XML、DTD 文档。有的版本
支持多种数据库,如 Oracle、Access、SQL Server、Informix、Sybase、DB2,能够实现与
数据库的集成,并可通过 Wizard 方式进行数据库的浏览、SQL 语句和存储过程的创建和执
行,以图形界面实现 XML 元素与数据库对象的绑定,同时创建 XML 文档和 DTD 文档。
但是,Visual XML 创建新文件时的速度比较慢,元素、属性的添加和移位等操作仍不十
分灵活。

5. Microsoft XML Notepad


它是 Microsoft 公司专门为设计 XML 文档而提供的编辑软件,可以借助它验证 XML
文档的有效性。

·17·
·18· XML 实用教程

6. Xray
Xray 一种具有实时错误检查的 XML 编辑器。它根据 DTD 或者 XML Schema,允许用
户创建格式良好的 XML 文档或验证文档的有效性,并且支持多文档编辑,是一款免费软
件,支持 Windows 的各种平台。

7. Editplus
Editplus 是一个功能强大的编辑器,支持各种常见语言的彩色语法显示,能够允许用户
自定义工具。Editplus 经过配置后可以作为 C、C++、Java、BASIC、Masm 等 DOS 版本语
言开发工具的 Windows 集成环境,编译和运行这些语言的程序。

1.4.2 XML 验证工具

为了使得定义的 XML 文档有效,通常必须为它定义一组语法,这种语法规定这类文


档应该包含哪种类型的数据,数据的层次结构又是怎样的,以及各层次标记和数据的数量、
选择性、默认值等。因此,XML 文档需要通过专门的工具来验证其合法性。常用的验证工
具有以下两种:
(1) Microsoft XML Validator。该软件可以检查 XML 文档是否是“格式良好的”以及其
有效性,并对错误发出警告。
(2) Microsoft XSL Debugger。样式单文件的复杂性使开发人员在编写时容易出现错误,
这个软件就是帮助用户调试样式单文件,把复杂枯燥的调试过程用可视化界面显示出来。

1.4.3 XML 解析器

XML 规范不仅描述了 XML 数据的格式和语法,而且为处理 XML 数据指定了一个两


层的用户体系结构。第一层就是 XML 解析器(也被称为 XML 处理程序)。XML 解析器负责
检查 XML 文档,首先它检查 XML 数据是否符合语法规则,确保开始标记有与其匹配的结
束标记,并确保文档是格式正确的。大多数解析器还根据 DTD 或 XML Schema 进行确认,
核实其结构和内容是语法定义文档所指定的。XML 解析器可以减轻应用程序处理 XML 数
据的负担,同时把 XML 数据的内容和结构以规定的方式送到第二层(XML 应用层)。
微软的 XML 核心服务组件是 MSXML。虽然微软在 2005 年 11 月推出了 MSXML 6.0,
但是 2003 年 4 月推出了 MSXML 4.0spr 仍是当前最常用的解析器。和 MSXML 3.0 相比,
MSXML 4.0 提供了大量的新功能和功能改进。其中包括:对 XML 模式语言的支持,更快
的分析器和 XSLT 引擎,对 XML 流更好的处理,更好的一致性支持。MSXML 4.0 并不是
MSXML 3.0 的替代产品,因为在 3.0 版本中的一些过时功能已经在 4.0 版本中彻底去除了。
所以 MSXML 4.0 可以和 MSXML 3.0(甚至更早的版本)同时安装。
MSXML 4.0 不支持 4.0 RTM Beta 测试版升级。因此必须完全卸载此 RTM 版,一般应
删除 system32 目录下的 msxml4*.dll 文件,以确保 MSXML 4.0 安装成功。

·18·
第1章 引论 ·19·

1.4.4 XML 浏览工具

XML 文档除了后台使用外,还需要进行浏览,特别是编辑过程中。一般的 XML 编辑


软件都能浏览 XML。Microsoft XML Tree Viewer 是一个典型的 XML 浏览器,可以把 XML
文档的内容用树状结构形式显示出来。
Internet Explorer(简称 IE)具有很强的 XML 文档浏览功能,也为人们主要所采用。一般
不需要使用别的浏览工具。
大型开发工具.NET 体系、PowerBuilder、JBuilder 等都支持 XML,具有 XML 的编辑、
验证、解析和浏览功能。

1.5 小 结

XML(eXtensible Markup Language)是在克服 HTML 的缺陷和局限性基础上发展起来


的,标记语言的发展导致了 XML 的诞生。而 XML 的出现,把网络表达语言集合推进了一
大步,使得标记语言可以由编程人员按需要无限扩展,这就给 Web 编程带来了革命性的进
展,使人们可以在所涉及的领域内自由地交换信息。
XML 是一个新的 SGML 的简化子集,能够把数据和它的显示分离开来,具有良好的
格式、严格的验证机制、灵活的 Web 应用、丰富的显示样式、便捷的数据处理、开放的标
准、选择性的更新等优点。
XML 在网络服务、电子数据交换、电子商务、数据库、智能体和软件设计等领域有广
泛的应用前景。
XML 文档的数据结构是树状结构,相当于原来的层次型数据库系统,既能表示关系型
数据库的二维表,也能反映出事物的层次性。XML 文档包含 7 个主要部分:序言码、处理
指令(PI)、根元素、元素、属性、CDATA 节和注释。
XML 是一套完整的方案,有一系列相关技术,包括文件数据验证、显示输出、文件转
换、文档对象和链接等,其开发应用环境包括 XML 编辑工具、验证工具、解析工具和浏
览工具。

1.6 习 题

1. HTML 存在哪些缺陷?
2. 请比较 XML 与 HTML 有哪些异同。
3. 为什么说 XML 是元标记语言?
4. 试述 XML 的特点和优越性。
5. XML 的开发和应用需要怎样的环境?
6. 使用XML Spy 或记事本等文本编辑器编辑如下XML 文档,
并保存文件名为code1_3.xml,
然后在 IE 中浏览。

·19·
·20· XML 实用教程

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


<orders>
<order>
<customerID>c0500069</customerID>
<order_date>20050517</order_date>
<order_status>pending</order_status>
<items>
<item>
<bookID>001</bookID>
<quantity>10</quantity>
<item_status>pending</item_status>
</item>
</items>
</order>
<order>
<customerID>c500701</customerID>
<order_date>20050712</order_date>
<order_status>pending</order_status>
<items>
<item>
<bookID>002</bookID>
<quantity>30</quantity>
<item_status>pending</item_status>
</item>
<item>
<bookID>003</bookID>
<quantity>20</quantity>
<item_status>pending</item_status>
</item>
</items>
</order>
</orders>

7. 使用 XML Spy 或记事本等文本编辑器编辑如下 XML 文档,并保存文件名为 code1_4.xml


的文件,然后在 IE 中浏览。
<?xml version="1.0" encoding="gb2312" ?>
<customers>
<customer ID="c0500103" >
<username>cheaperget</username>
<password>12345678</password>
<email>notknown@yahoo.com</email>
<registerdate>200508</registerdate>
<address>
<zipcode>361021</zipcode>
<phone>0592-6888888</phone>
<street>XX 省 XX 市银江路 108 号</street>
</address>
</customer>
<customer ID="c0500208" >
<username>dreamingboy</username>

·20·
第1章 引论 ·21·

<password>22345678</password>
<email>greatman@lycos.com</email>
<registerdate>200505</registerdate>
<address>
<zipcode>215006</zipcode>
<phone>0512-61666666</phone>
<street>XX 省 XX 市人民路 616 号</street>
</address>
</customer>
</customers>

·21·
第 2 章 HTML 基础

教学提示:Web 页面可采用 HTML 创作,它允许将常规的文本与一些用来描述文本的


标记混合使用。这些标记的主要功能是 Web 中文本的显示外观、版面布局和主体的描述。
在制作网页的时候,有经验的程序员经常是分两步走的,首先使用一些常用的网页制作工
具做成网页的原型,然后再修改其 HTML 代码。HTML 代码不区分大小写,只要能编辑文
本的任何编辑器都可以用于编写 HTML 代码。
教学目标:了解网页设计的基本概念及 HTML 的基本知识,掌握 HTML 文档的基本
结构,熟悉常用 HTML 元素标记的功能及使用方法。掌握格式化网页文本的常用方法,熟
悉在网页中链接语句的使用方法。

2.1 HTML 概述

2.1.1 HTML 概述

HTML 是 Hyper Text Markup Language 的缩写,意思是“超文本标示语言”,它实际


上是专门用来编写网页的一种编程语言。大多数网页的构成基础就是 HTML 语句。上网浏
览一个网页时,实际上是把该网页所对应的 HTML 文件下载到本地计算机中,然后由本地
计算机中的浏览器(如 IE)再解释、显示。一个 HTML 程序由文档头部和正文两部分构成,
其基本结构如图 2.1 所示。

<html>
<head>
HTML部分 <title>欢迎进入HTML世界</title>
文档头部 </head>
正文部分 <body>
<p>这会是一种很有趣的体验</p>
</body>
</html>

图 2.1 HTML 文档的基本结构

2.1.2 如何编写一个 HTML 文件

HTML 文件是一个 ASCII 格式的文件。它可以在任何一种可以编辑 ASCII 文件的编辑


器中编辑(如果 HTML 文件中包含汉字,则要在支持汉字的编辑器中编辑)。通常可以用
第2章 HTML 基础 ·23·

Windows 的记事本和写字板、字处理软件 Word 等来编辑 HTML 文件。


除了这些通用的编辑器外,还有一些专门用于编写 HTML 文件的编辑器。这些专用编
辑器可以在 Internet 中找到,使用它们编写 HTML 常常更方便。
保存文件时,注意文件的扩展名应该为.htm 或.html。不要在文件名中使用一些特殊的
符号(如空格符)。
可以建立一个专用文件夹,来存放这些 HTML 文件。

2.1.3 HTML 文件的调试

一个 HTML 文件编写完毕后,其执行效果到底如何,应在浏览器中查看一下。
【例 2.1】 编写如下内容,保存文件名为 code2_1.html。
<html>
<head>
<title>第 2 章 HTML 基础</title>
</head>
<body>
HTML 是 Hyper Text Markup Language 的缩写,意思是“超文本标示语言”。它实
际上是专门用来编写网页的一种编成语言。大多数网页的构成基础就是 HTML 语句。
</body>
</html>

可以在 Windows 的记事本中输入、编辑并保存此文件(保存时文件名要有.html 的扩展


名,并选择“所有文件”格式来保存),然后,双击此文件图标,则系统自动用 IE 打开此
文件,如图 2.2 所示。

图 2.2 简单的 HTML 网页

值得注意的是,同一个文件在不同的浏览器中显示的效果可能不同。因此,应尽可能
多用几种浏览器查看。

2.2 HTML 的标记

2.2.1 标记的一般特性

作为一种标识语言,构成它的要素是标记,用标记符号来描述信息。标记有很多种,

·23·
·24· XML 实用教程

每一种有自己的含义和作用。浏览时浏览器会根据标记的意义,自动显示效果。概括地说,
一个 HTML 文件中由两大类元素组成:其一是标记,其二是标记的作用对象(如文字、图
形等)。
标记往往是具有特殊含义的英语词组或字母组合(如 title、html 等),其形式不会变化。
标记通常放在“<>”中,可以不区分大小写,也就是说,大写字母与小写字母的意义一样。
对于大多数标记而言,标记是成对的,一个表示开始,一个表示结束。如例 2.1 中的
<title>与</title>就是一对。标记常常使用的格式如下:
<标记符>内容</标记符>
应该注意的是,表示结束的标记符前面有一个斜杠“/”。

2.2.2 常用标记

尽管 HTML 所使用的标记很多,但以下讲述的是最常用的几种。
1. <html>和</html>
这是 HTML 文件所必需的一对标记。<html>居于文件最前面,在文件的开始处;</html>
居于文件最后面,在文件的结尾处。类似于 C 语言中的“{”和“}”。HTML 文件的其他
内容都镶嵌在这对标记中,如例 2.1 中所示。
2. <head>和</head>
这对标记用来指定网页的头部,指明文件信息。文件信息和文本信息共同构成了一个
HTML 文件,或者说,一个 HTML 文件主要由文件信息和文本信息两部分组成。
使用格式如下:
<head>
文字说明
</head>

一般而言,“文字说明”部分的信息要简明扼要。
此对标记可以与<title>及</title>配合使用,也可单独使用。单独使用时,则作为正文的
头部,显示在全部文本信息之前。
3. <title>和</title>
这对标记用来指定网页的标题。它们要包含在<head>和</head>标记之间。使用格式
如下:
<head>
<title>文字说明</title>
</head>

这样一来,“文字说明”就会作为网页的标题,显示在屏幕顶端。图 2.1 中就是在屏


幕的最上面显示“第 2 章 HTML 基础”的提示信息。“文字说明”部分的内容不宜太多,
通常是网页标题信息,或者是如“欢迎光临软件网站!”等欢迎信息。
如果一个网页没有标题,则 IE 会把该网页的路径作为该网页的标题。
4. <body>和</body>
这对标记用来包含网页的文本内容,这是一个网页中最丰富的部分。

·24·
第2章 HTML 基础 ·25·

5. <hn>和</hn>
这对标记用来指定网页的子标题。它按字体大小分为 6 级,n 分别用 1,2,3,4,5,
6 来表示,也就是说,可以采用以下 6 种格式。
<h1>子标题内容</h1>
<h2>子标题内容</h2>
<h3>子标题内容</h3>
<h4>子标题内容</h4>
<h5>子标题内容</h5>
<h6>子标题内容</h6>

这里,n 的值越大,浏览器显示的字体越小。子标题会以不同于正文的方式显示,会
以加黑、下画线等形式突出显示。子标题长度不限,可以多行。
【例 2.2】 以不同于正文的方式显示各级子标题,代码如源程序 code2_2.html 所示。
<html>
<head>
<title>网页子标题标题字体大小</title>
</head>
<body>
<h1>h1 级子标题内容</h1>
<h2>h2 级子标题内容</h2>
<h3>h3 级子标题内容</h3>
<h4>h4 级子标题内容</h4>
<h5>h5 级子标题内容</h5>
<h6>h6 级子标题内容</h6>
这是正文
</body>
</html>

其执行结果如图 2.3 所示。

图 2.3 子标题的分级

6. <br>
这是单个的标记,其作用是换行显示,相当于 Word 中的段落标识符。如果在 HTML

·25·
·26· XML 实用教程

文件中没有使用<br>,那么显示到窗口的边界,则会自动换行。

7. <hr>
此标记会显示一条水平线。这样可以分隔文件中的不同部分,使内容更清晰。
【例 2.3】 换行显示和显示一条水平线,代码如源程序 code2_3.html 所示。
<html>
<head>
<title>这是网页标题</title>
</head>
<body>
望庐山瀑布<br>
唐.李白
<hr>
日照香炉升紫烟,<br>
遥看瀑布挂前川。<br>
飞流直下三千尺,<br>
疑是银河落九天。<br>
</body>
</html>

其执行结果如图 2.4 所示。

图 2.4 水平线的使用

2.3 文 字 修 饰

一个网页大多由以下要素构成:文字、图片、表格、动画及声音。在这些元素中,文
字是十分重要的。下面逐一讲述涉及文字的标记。

2.3.1 字号

可以采用多种方式设置文字的大小。不过设置文字的大小后,其效果会受到 IE 中选项
的影响。如图 2.4 所示是【文字大小】设置为【中】时显示的效果。
当把【文字大小】设置为【最大】时,显示效果如图 2.5 所示。
对比图 2.4 和图 2.5 的文字发现,图 2.5 中的文字比图 2.4 中的大。这就说明了 IE 设置
的影响。因此,文字大小设置标记的作用都是相对的。

·26·
第2章 HTML 基础 ·27·

图 2.5 在 IE 中设置文字大小

下面讲述关于字号的标记。
1. <small>和</small>
把文字以小一些的字号显示(默认的字号为“中”),具体效果参看例 2.4。
2. <big>和</big>
把文字以大一些的字号显示,具体效果参看例 2.4。

3. <font size=n>
本标记也用来设置文字的大小。这里 n 是数字,可以为 1,2,3,4,5,6,7。数字
越大,显示的文字也越大。n 的默认值是 3。
此标记一直有效,直到遇到一个新的 n 值或</font>时为止。
如果给出的 n 值有正负号,则表示在当前字号的基础上增大或缩小字号。如“+1”表
示大 1 号。

4. <basefont size=n>
本标记用来设置文字的默认大小。这里 n 的意思与<font size>标记中的相同。
【例 2.4】 设置文字的默认大小,代码如源程序 code2_4.html 所示。
<html>
<head>
<title>设置文字的默认大小</title>
</head>
<body>
显示效果正常字号
<small>小号字</small>
<big>大号字</big><br>
<font size=1>1 号字<br>
<font size=2>2 号字<br>
<font size=3>3 号字<br>
<font size=4>4 号字<br>

·27·
·28· XML 实用教程

<font size=5>5 号字<br>


<font size=6>6 号字<br>
<font size=7>7 号字<br>
<font size=-5>相对小 5 号<br>
<font size=+2>相对大 2 号
</body>
</html>

其执行结果如图 2.6 所示。

图 2.6 设置文字大小的效果

2.3.2 字体样式

除了可以设置文字的大小之外,还可以设置字体的样式(包括颜色)。

1. <b>和</b>

这一对标记配合使用,使放在它们中间的文字以粗体显示,使用格式如下:
<b>要粗体显示的文字</b>

通常用粗体表示强调,它是一种突出显示的效果。
如果只有<b>标记而忘记了</b>标记,则从<b>开始一直都是粗体。

2. <i>和</i>

这一对标记配合使用,使放在它们中间的文字以斜体显示,使用格式如下:
<I>要斜体显示的文字</I>

注意事项与<b>相同。

3. <u>和</u>

这一对标记配合使用,使放在它们中间的文字以下划线显示,使用格式如下:
<u>要下划线显示的文字</u>

·28·
第2章 HTML 基础 ·29·

注意事项与<b>相同。

4. <strike>和</strike>

这一对标记配合使用,使放在它们中间的文字以加上删除线显示,使用格式如下:
<strike>要加上删除线显示的文字</strike>

注意事项与<b>相同。

5. <sub>和</sub>

这一对标记配合使用,使放在它们中间的文字以下标形式显示,使用格式如下:
<sub>要以下标形式显示的文字</sub>

注意事项与<b>相同,下标会比正常字号小。

6. <sup>和</sup>

这一对标记配合使用,使放在它们中间的文字以上标形式显示,使用格式如下:
<sup>要以上标形式显示的文字</sup>

注意事项与<b>相同,上标会比正常字号小。

2.3.3 特殊标记

因为“<”和“>”作为标记的边界符使用了,所以要显示这两个符号,必须转义。具
体情况如下:“<”用“&lt”,“>”用“&gt”,“&”用“&amp”,“"”用“&quot”。
【例 2.5】 使用字体样式和特殊标记,代码如源程序 code2_5.html 所示。
<html>
<head>
<title>使用字体样式和特殊标记</title>
</head>
<body>
<b>要粗体显示的文字</b>
<i>要斜体显示的文字</i>
<u>要下划线显示的文字</u>
<strike>要加上删除线显示的文字</strike><br>
正常文字<sub>下标形式显示的文字</sub><br>
正常文字<sup>上标形式显示的文字</sup><br>
小于号&lt<br>
大于号&gt<br>
</body>
</html>

其执行结果如图 2.7 所示。

·29·
·30· XML 实用教程

图 2.7 使用字体样式和特殊标记的效果

2.4 列 表

列表是一种条理化地排列信息的方法。它把内容一条条地水平排列显示,直观、清晰。
而它也不同于表格,一般列表没有表格复杂。列表标记使用的通用格式:
<标记>
<条目标记 1>条目内容 1
<条目标记 2>条目内容 2
<条目标记 3>条目内容 3
……
</标记>

值得注意的是,在“条目内容”后不用加换行标记<br>。
1. <dir>和</dir>
把其间包含的内容以列表方式显示,并在每个条目前加上一个标记符号。
2. <menu>和</menu>
与<dir>作用相同,这两个标记比较简单,不能实现复杂的变化。
3. <ul>和</ul>
其效果与上述两个命令的列表效果相似。不过,此命令可以带属性,变成<ul type=f>
的形式。此处 f 为单词,具体情况有如下几种。
f 为 disk:条目以符号“●”引导。
f 为 circle:条目以符号“○”引导。
f 为 square:条目以符号“■”引导。
4. <ol>与</ol>
使用此对标记,也可实现与以上命令相似的列表。不同之处在于,本标记会自动给条
目排序并加上序号。
此标记也可带有属性,有如下两种。
1) < ol type=f>
此处,f 是一个字符,不同的字符表示不同的编号方式,主要有以下几种情况。

·30·
第2章 HTML 基础 ·31·

f 为 A:以大写字母排序。如 A,B,C,D 等。
f 为 a:以小写字母排序。如 a,b,c,d 等。
f 为 I:以大写罗马数字排序。如 I,II,III,IV 等。
f 为 i:以小写罗马数字排序。如 i,ii,iii,iv 等。
f 为 1:以阿拉伯数字排序。如 1,2,3,4 等。
2) <ol start=n>
n 是一个数字,此标记符表示重新定义的起始号。这样一来,可以指定序号的起始号。
【例 2.6】 列表序号的使用,代码如源程序 code2_6.html 所示。
<html>
<head><title>列表序号</title></head>
<body>
<dir>
<LI>李白
<LI>杜甫
<LI>杜牧
</dir>
<menu>
<li>李白----赠孟浩然
<li>杜甫----望岳
<li>杜牧----泊秦淮
</menu>
<ol type=A>
<li>李白----赠孟浩然
<li>杜甫----望岳
<li>杜牧----泊秦淮
</ol>
<ol type=i>
<li>李白----赠孟浩然
<li>杜甫----望岳
<li>杜牧----泊秦淮
</ol>
</body>
</html>

其执行结果如图 2.8 所示。

图 2.8 列表序号的效果

·31·
·32· XML 实用教程

5. 列表的嵌套
列表也可以层嵌套,嵌套后的效果参见例 2.7。
【例 2.7】 列表嵌套的使用,代码如源程序 code2_7.html 所示。
<html>
<head>
<title>列表嵌套</title>
</head>
<body>
<h3>唐诗选读</h3>
<ol>
<li>李白
<ul>
<li>春思
<li>月下独酌
<li>赠孟浩然
</ul>
<li>杜甫
<ul>
<li>望岳
<li>佳人
<li>梦李白
</ul>
<li>杜牧
<UL>
<LI>赤壁
<LI>泊秦淮
<LI>秋夕
</UL>
</OL>
</body>
</html>

其执行结果如图 2.9 所示。

图 2.9 列表嵌套的效果

·32·
第2章 HTML 基础 ·33·

2.5 表 格

HTML 对页面元素的排版基本就是按照元素在文档中出现的先后顺序,从头至尾依次
排下来的,唯一能控制页面元素位置的只有 align 属性,而它所能控制的情况只有 3 种:左、
中、右。要编制复杂的页面布局仅仅依靠基本的 HTML 几乎是不可能实现的。
表格就解决了这个问题,使用表格基本能实现对页面元素在浏览器中随心所欲的排版
定位。表格通常用来显示大量的、分类化的信息,具有表示清晰、明了的特点,使用十分
广泛。
表格一般由以下几部分组成:表格名称、表格栏及表中数据。这与其他软件(如 Word)
中所说的表格十分相同。
以下讲述建立、修改表格所涉及的标记。

2.5.1 <table>和</table>

这是一对用来指明表格范围的标记。通常使用的格式:
<table>
表格全部内容
</table>

1. border 属性
使用表格的这一属性可以给表格加上框线。如<table border>表示表格是有表格线的,
border 的线宽默认为 1。没有写 border 则表示表格是没有表格线的。
一般用<table border=n>来设置有线表格和边框宽度。n 是一个具体的数字,用来指定宽
度的大小,单位是像素,默认为没有边框。当 n 为 0 时,也没有边框,具体效果参见例 2.8。
【例 2.8】 设置表格和表格边框,代码如源程序 code2_8.html 所示。
<html>
<head>
<title>这是表格和表格边框的例子</title>
</head>
<body>
<table border="2">
<caption>表格标题</caption>
<tr>
<th>栏目名称 1</th>
<th>栏目名称 2</th>
<th>栏目名称 3</th>
</tr>
<tr>
<td>数据 1-1</td>
<td>数据 2-1</td>
<td>数据 3-1</td>
</tr>

·33·
·34· XML 实用教程

<tr>
<td>数据 1-2</td>
<td>数据 2-2</td>
<td>数据 3-2</td>
</tr>
</table>
</body>
</html>

其执行结果如图 2.10 所示。

图 2.10 表格和表格边框实例

2. width 属性
这一属性可以用来设置有线表格占整个页面的相对宽度,用法为<table width=n>。n 是
一个具体的数字,可以是一个百分数(如 100%),也可以是一个具体的数值,单位是像素(如
80,表示表格占 80 个像素单位的宽度)。
3. height 属性
这一属性可以用来设置有线表格占整个页面的相对高度。其用法与<table width=n>
相似。
使用相对方式来设置表格大小时,浏览器窗口大小的变化会影响到表格大小的变化。
表格宽度、高度设置要合理,在视觉上要有美感。
【例 2.9】 使用相对方式来设置表格大小,代码如源程序 code2_9.html 所示。
<html>
<head>
<title>这是表格占页面相对大小的例子</title>
</head>
<body>
<table border="5" width=80%, height=50%>
<caption>表格占页面的 80%</caption>
<tr>
<th>栏目名称 1</th>
<th>栏目名称 2</th>
<th>栏目名称 3</th>
</tr>
<tr>
<td>数据 1-1</td>
<td>数据 2-1</td>

·34·
第2章 HTML 基础 ·35·

<td>数据 3-1</td>
</tr>
<tr>
<td>数据 1-2</td>
<td>数据 2-2</td>
<td>数据 3-2</td>
</tr>
</table>
<table border="5" width=70%, height=40%>
<caption>表格占页面的 70%</caption>
<tr>
<th>栏目名称 1</th>
<th>栏目名称 2</th>
<th>栏目名称 3</th>
</tr>
<tr>
<td>数据 1-1</td>
<td>数据 2-1</td>
<td>数据 3-1</td>
</tr>
<tr>
<td>数据 1-2</td>
<td>数据 2-2</td>
<td>数据 3-2</td>
</tr>
</table>
</body>
</html>

其执行结果如图 2.11 所示。

图 2.11 设置表格在页面中的相对大小

4. cellspacing 属性
这一属性可以用来设置有线表格的单元格线的宽度,用法为<table cellspacing=n>。n
是一个具体的数值,单位是像素。

·35·
·36· XML 实用教程

5. cellpddeing 属性
这一属性可以用来设置单元格线与数据之间的距离,用法为<table cellpddeing=n>。n
是一个具体的数值,单位是像素,默认值为 1。

2.5.2 <caption>和</caption>

这是一对用来指明表格标题的标记。通常使用的格式:
<caption>
表格标题内容
</caption>

默认的情况下,标题以居中的形式显示,而且显示在表格的上面。标题也可以显示在
表格的下面,这要使用 align 属性,使用格式如下:
<caption align=f>
此处,f 为以下两个单词:top,标题显示在表格之上;bottom,标题显示在表格之下。

2.5.3 <tr>和</tr>

这对标记用来指明表格一行的内容。这一行可以是表格的栏目,也可以是数据。

2.5.4 <th>和</th>

这对标记用来指明表格栏目行中的一项。一行可以由多项组成,必须嵌套在<tr>与</tr>
之中使用。由此标记指定的栏目,文字会突出显示。

2.5.5 <td>和</td>

这对标记用来指明表格数据行中的一项。一行可以由多项组成,它也必须嵌套在<tr>
与</tr>之中使用。由此标记指定的栏目,文字不会突出显示。
本标记的用法参见例 2.8 和例 2.9。
1. align 属性
以上<tr>、<th>及<td>也可以带 align 属性。
align=left:表示居左,如<th align=left>。
align=center:表示居中,如<th align=center>。
align=right:表示居右,如<th align=right>。
特别值得注意的是,这种调整可以针对每一表格单元,因此可以十分灵活地使用。
2. nowrap 属性
在执行<th>及<td>时,当数据较多,一行显示不下时,浏览器会自动换行显示。如果
不要自动换行,可以使用 nowrap 属性。
3. width 属性
在执行<th>及<td>时,使用此属性可以指定宽度。具体用法与在<table>中一样。

·36·
第2章 HTML 基础 ·37·

4. valign 属性
在执行<th>及<td>时,使用此属性可以指定文字显示在本行的上、中、下位置,使用
格式如下:
<valign=f>

此处,f 为以下单词:top,文字显示在本行偏上位置;middle,文字显示在本行中间位
置;bottom,文字显示在本行偏下位置。
5. colspan 属性
在执行<th>及<td>时,使用此属性可以实现单元格的横向合并,使用格式如下:
<colspan=n>

这里,n 是数值,默认为 1(此时可以省略该参数)。若要实现两栏合并,则让 n 的值


为 2 即可。
6. rowspan 属性
在执行<th>及<td>时,使用此属性可以实现单元格的纵向合并,使用格式如下:
<rowspan=n>

这里,n 是数值,默认为 1(此时可以省略该参数)。若要实现两栏合并,则让 n 的值


为 2 即可。
【例 2.10】 实现栏目合并,代码如源程序 code2_10.html 所示。
<html>
<head>
<title>这是表格栏目合并的例子</title>
</head>
<body>
<table border="2">
<caption>表格标题</caption>
<tr>
<th>栏目名称 1</th>
<th colspan=2>栏目名称 2 和 3</th>
<tr>
<th rowspan=2>数据 1-1</th>
<td>数据 2-1</td>
<td>数据 3-1</td>
<tr>
<td>数据 2-2</td>
<td>数据 3-2</td>
</table>
</body>
</html>

其执行结果如图 2.12 所示。

·37·
·38· XML 实用教程

图 2.12 表格栏目合并的效果

2.6 色 彩

2.6.1 色彩的表示

在计算机显示器中,使用红(red)、绿(green)、蓝(blue)3 种颜色来构成各种各样的颜色。
颜色的种类有 16,256 及 65,536 等多种。把这 3 种颜色从 0 到 255 分别编号,再表示为
十六进制数,则红色(rr)就从 00 到 ff,绿色(gg)和蓝色(bb)两种颜色也如此。3 种颜色的表
示合起来就是 rrggbb。这样一来,可以用一种颜色中所含红、绿、蓝成分的程度,数值化
地表示颜色。如黑色为 000000、白色为 ffffff、墨绿色为 008040、深灰色为 808080 等。在
HTML 中,可用这种方式指定颜色。
但是,这种方式指定的颜色多达 256×256×256 种。并非所有的显示器都可显示这么多
种的颜色。当指定了显示器不能显示的颜色时,显示器会以自己可以显示的、最接近的颜
色显示。但这个“最接近的颜色”,也可能偏离设计者原来所想的颜色,这就出现了“变
色”。要解决这一问题,其一可以在其他颜色模式下调试(如把当前颜色改为 16 色,浏览
一下,若不满意可以改);其二也可只使用最常见的 256 种颜色(甚至只 16 色),这是一种保
守的方法。
如果不想使用这种用数值指定颜色的方法,也可以用英文的颜色名称来指定。常见的
颜色见表 2-1。

表 2-1 常见颜色列表

颜 色 名 称 颜 色 名 称

black 黑 red 红
white 白 fuchsia 紫红
navy 深蓝 maroon 棕
blue 蓝 purple 紫
aqua 浅绿 green 绿
teal 靛 olive 橄榄色
silver 银灰(浅灰) lime 柠檬绿
gray 灰 yellow 黄

·38·
第2章 HTML 基础 ·39·

2.6.2 文本的色彩

在 body 的属性中,可以使用以下几种属性改变文本的颜色。
1. text 属性
该属性用来设置文本的颜色。这里所说的“文本”可以是标题、正文及表中的文字,
但不能用于超链接的文字。使用格式为
<text=#rrggbb>

这里的 rrggbb 取值为表示颜色的数据,如 2.6.1 节所述。


2. link 属性
该属性用来设置超链接文字的颜色,默认为蓝色,使用格式为
<link=#rrggbb>

rrggbb 的意义与<text>中的相同。
3. vlink 属性
该属性用来设置鼠标指向的超链接文字时,链接文字的颜色,默认为红色,使用格式为
<vlink=#rrggbb>

rrggbb 的意义与<text>中的相同。
通常情况下,不使用<text>、<link>及<vlink>进行设置,一般都使用默认设置。
4. <font>标记的 color 属性
以上几种属性所指定的都是整个网页中某一类文字的色彩,使用<font>标记的 color 属
性可指定任意一段文字的色彩。这里所说的一段文字,可以为几行、一行甚至只有一个字。
使用格式为
<font color=#rrggbb>

此处,rrggbb 的意义如 2.6.1 节所述(下同)。

2.6.3 表格的颜色

1. <table>标记的 bgcolor 属性
用来指定整个表格的背景颜色,使用格式为
<table bgcolor=#rrggbb>
2. <td>标记的 bgcolor 属性
用来指定表格中一行的背景颜色,使用格式为
<td bgcolor=#rrggbb>

3. <th>标记的 bgcolor 属性
用来指定表格中栏目行的背景颜色,使用格式为
<th bgcolor=#rrggbb>

·39·
·40· XML 实用教程

2.6.4 <hr>标记的 bgcolor 属性

用来指定分隔线的颜色,使用格式为
<hr color=#rrggbb>
【例 2.11】 颜色的设置,代码如源程序 code2_11.html 所示。
<html>
<head>
<title>这是颜色设置的例子</title>
</head>
<body>
颜色显示效果<br>
<font color=red>
<hl>问题与答案(红色)<hl>
<hr color=#808080>
<font color=blue>
如何改变表格的背景颜色?(蓝色)<br>
<font color=olive>
这还不简单(橄榄色)。
</body>
</html>

其执行结果如图 2.13 所示。

图 2.13 颜色的设置

2.7 超文本链接

超文本链接是网页中一种非常重要的功能,是网页中最重要、最根本的元素之一。通
过链接可以从一个网页转到另一个网页,也可以从一个网站转到另一个网站,这符合人类
的跳跃思维方式。链接的标志有文字和图片两种。可以制作一些精美的图片作为链接按钮,
使它和整个网页融为一体。

2.7.1 超文本链接的概念

所谓的超文本链接是指从一个网页指向一个目标的连接关系,这个目标可以是另一个
网页,也可以是相同网页上的不同位置,还可以是一个图片、一个电子邮件地址、一个文
件,甚至是一个应用程序。而在一个网页中用来超文本链接的对象,可以是一段文本或者

·40·
第2章 HTML 基础 ·41·

是一个图片。当浏览者单击已经链接的文字或图片后,链接目标将显示在浏览器上,并且
根据目标的类型来打开或运行。按照链接路径的不同,网页中的超文本链接一般分为以下
3 种类型:内部链接、锚点链接和外部链接。如果按照使用对象的不同,网页中的链接又
可以分为:文本超链接、图像超链接、E-mail 链接、锚点链接、多媒体文件链接、空链接等。
2.7.2 页面链接

用 HTML 创建超文本链接需要使用<a>标记符(结束标记符</a>不能省略),它的最基本
属性是 href,用于指定超文本链接的目标。通过为 href 指定不同的值,可以创建出不同类
型的超文本链接。
在 HTML 文件中用链接指针指向一个目标,使用格式为
<a href = "…">标记超文本链接信息</a>

其中,标记超文本链接信息可以是文字或图片并显示在网页中,当用户单击它时,浏
览器就会显示由 href 属性中的统一资源定位器(URL)所指向的目标,实际上这个标记超文
本链接信息在 HTML 文件中充当指针的角色,它一般显示为蓝色。href 中的 h 表示超文本,
而 ref 表示“访问”或“引用”的意思。在<a>和</a>之间可以用任何可单击的对象作为超
文本链接的源,例如文字或图像。
例如:
<a href ="http://www.hunu.edu.cn/">湖南大学</a>

用户单击“湖南大学”,即可看到湖南大学的主页内容。在这个例子中,充当指针的
是“湖南大学”。
2.7.3 本地链接

超文本链接可以指向本地计算机中的某一个文件,这种链接方式叫做本地链接。在文
件中需要创建一个标签(即做一个记号),为页面中需要跳转到的位置命名。命名时应使用
<a>标记符的 name 属性。使用格式如下:
<a name=标签名>此处创建了一个标签</a>

name 属性是不可缺少的,它的值也即是标签名。href 属性赋的值若是标签的名字,必


须在标签名前边加一个“#”。
【例 2.12】 在一个文件中建立本地链接,代码如源程序 code2_12.html 所示。
<html>
<head><title>使用链接</title></head>
<body>
<a href = #Internet>互联网</a><br><br>
<a href = #HTML>HTML 简介</a><br><br>
<a href = #Consistency>多样化和统一性</a><br><br>
<a name = Internet>互联网</a><br>
<p>互联网是网络的网络。也就是说,计算机网络可以跨越国家甚至全球的范围连接到其
他网络。世界上所有的计算机都可以通过 TCP/IP 协议簇绑定在一起。</p>
<a name = HTML>HTML 简介</a><br>
<p>超文本标记语言是 Web 用来创建和识别文档的标准语言。虽然它不是标准通用标记语
言(SGML)的子集,但与它有着某种程度上的关联。SGML 是一种文档格式语言表示方法。
</p>

·41·
·42· XML 实用教程

<a name = Consistency>多样性和统一性</a><br>


<p>万事万物都离不开多样性和统一性这样一条基本准则。也就是说,所有的事物都可以
融合成一个整体,同时,又保持自己独特的与众不同的一面。站点的独特性恰恰来源于它
的一致性。颜色、字体、分栏布局以及其他设计元素应在站点的每个部分都保持一致。</p>
<br>
</body>
</html>

其执行结果如图 2.14 所示。

图 2.14 使用本地链接

这样设置之后,当用户在浏览器中单击文字“互联网”时,将把“互联网”文字开头
的部分显示在页面的开头。其执行结果如图 2.15 所示。

图 2.15 执行结果

2.7.4 电子邮件链接

若希望用户在网页上通过链接直接打开客户端发送邮件的工具发送电子邮件,则可以
在网页内包含发送电子邮件的功能。实现此功能所需的全部工作就是在链接标记中插入
mailto 值,如:

·42·
第2章 HTML 基础 ·43·

<a href="mailto:webmaster@hnu.cn">管理员信箱</a>

这就创建了一个自动发送电子邮件的链接,“mailto:”后边紧跟想要自动发送的电子
邮件的地址(即 E-mail 地址),当浏览网页的用户单击了指向电子邮件的超文本链接后,系
统将自动启动邮件客户程序(对于安装了 Windows 98/2000 操作系统的计算机,默认时启动
Outlook Express),并将指定的邮件地址填写到【收件人】栏中,用户可以编辑并发送邮件。

2.8 小 结

HTML 是构成网页的最基本的元素,虽然随着技术的发展,又有各种新技术产生,如
PHP、ASP、ASP.NET、JSP 和 J2EE,它们依然是建构在 HTML 之上的,并没有舍弃现有
的 HTML,因为我们还是必须学习 HTML 语法。
HTML 文件是普通的文本文件,再加上一些标记,用以告知 WWW 浏览器有关字形的
变化、表格设置或是一些超文本链接。当用户浏览 WWW 上的信息时,浏览器会自动解释
这些标记的含义,并按照一定的格式在屏幕上显示这些被标记的文件。HTML 的优点是跨
平台性,即任何可以运行浏览器的计算机都能阅读并显示 HTML 文件,不管其操作系统是
什么,并且显示结果相同,呈现出生动、活泼的 WWW 世界。

2.9 习 题

1. HTML 是什么意思?它是一种什么样的语言?
2. HTML 最常用的标记有哪些?
3. 网页主要由哪些要素组成?
4. 用于文字修饰的标记主要有哪些?
5. 用于表格的主要标记有哪些?用表格设计班级通讯录网页。
6. 制作一个网页,网页用表格划分成几个区域。
7. 在<body>的属性中,可以使用哪些属性改变文本的颜色?
8. 用来指定分隔线颜色的具体格式是什么?
9. 制作一个自己的个人主页,网页中有文字链接,并将自己的电子邮箱制作成链接。

·43·
第 3 章 XML 基础

教学提示:XML 扩展了 HTML 的标记和功能,使编程人员可以根据需要定义标记。


XML 还具有信息描述、交换等多项功能。掌握 XML 的语法知识是进一步学习和运用 XML
技术的前提。本章讲述编制 XML 文档的常用语法和基本规则,主要包括 XML 的基本语法、
XML 文档的基本组成等,这些内容是学习整个 XML 的基础。
教学目标:理解结构良好的 XML 文档的概念,掌握 XML 的基本语法,熟悉属性、特
殊字符、注释、CDATA、名称空间的使用方法,了解 XML 的相关技术,能够使用 XML Spy
建立简单的 XML 文档。

3.1 XML 标记语法

3.1.1 标记的命名规则

作为元标记语言,XML 可以在文档中创建、使用新的标记和文法结构。正是这种优点
使得用户能够根据自己的特殊需要制定出适用于自身的一套标记和文法结构,以便于结构
化地描述自己领域的信息,从而提供一种处理数据的最佳方式。
XML 的可扩展性为开发者进行程序开发提供了自由广阔的空间,但并非所有名字都可
以作为标记名。作为标记名字的字符串必须满足以下要求。
(1) 名称的开头必须是字母或“_”;
(2) 标记名称中不能有空格;
(3) 名称的字符串只能包含英文字母、数字、“_”、“-”、“.”等字符。
例如下面的标记就是合法标记:
<Name>、<name>、<_name>、<lisongtao_name>、<li.name>。
而下面是非法的标记:
<.name>、<li%name>、<li*name>、<li/name>
以上标记的命名规则同时也是后面要讲到的属性的命名规则,以及 XML 文档中其他
实体的命名规则。

3.1.2 标记的使用规则

1. 必须具有根标记且根标记必须唯一
结构良好的 XML 应用程序的根标记必须要唯一。
【例 3.1】 根标记不唯一的 XML 文档,代码如源程序 code3_1.xml 所示。
第3章 XML 基础 ·45·

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


<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>

其显示结果如图 3.1 所示。

图 3.1 根标记不唯一的 XML 文档的显示结果

该程序出错的地方是根标记不唯一。只要在两个标记的外面统一套一个标记<book>
</book>,程序就成为运行正常的 XML 文档了。
2. 开始标记和结束标记需配对使用
在 HTML 中,只有开始标记而没有结束标记的程序往往还能得到正确的显示结果,但
在 XML 文档中这种情况是不允许存在的。
【例 3.2】 开始标记和结束标记不配对的 XML 文档,代码如源程序 code3_2.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<bookinfo>
<title>计算机导论</title>

·45·
·46· XML 实用教程

<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publisher>
<price>19.7</price>
</bookinfo>

其显示结果如图 3.2 所示。

图 3.2 开始标记和结束标记不配对的 XML 文档的显示结果

该程序的问题就在于<publish>标记和</publisher>标记不是一对开始和结束标记,这里
只要将<publish>改为<publisher>或将</publisher>改为</publish>问题就解决了。
3. 标记不能交错使用
所谓标记的交错使用就是指如下情形的标记使用。
<publisher><ISBN>7-04-014768-8</publisher></ISBN>

上面例子中,标记</publisher>和标记</ISBN>就是交错使用。在 XML 中这种标记的交


错使用是非法的。应改成:
<publisher><ISBN>7-04-014768-8</ISBN></publisher>

4. 空标记的使用
所谓空标记指的是标记只有开始没有结束,又叫孤立标记。这种标记有的表示一种格
式信息,例如<hr>在 HTML 中代表了一条水平线,有的则保存一些数据信息。空标记可写
成“<标记名/>”的形式。具体使用如例 3.3。
【例 3.3】 空标记的使用,代码如源程序 code3_3.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<!-- 这个文档包含网上书店中关于书的描述,文件名 code3_3.xml -->
<!DOCTYPE bookinfo SYSTEM "code3_1.dtd">
<bookinfo>

·46·
第3章 XML 基础 ·47·

<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<bk/>
<price>19.7</price>
</bookinfo>

5. 标记对大小写敏感
HTML 中并不存在大小写敏感问题,但在 XML 中相配对的标记大小写必须相同。
【例 3.4】 标记大小写不匹配的 XML 文档,代码如源程序 code3_4.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</BOOKINFO>

上面程序中</bookinfo>标记和</BOOKINFO>标记被认为是两个不同的标记,因此<bookinfo>
</BOOKINFO>被认为是两个不配对的标记。程序将显示错误信息,如图 3.3 所示。

图 3.3 标记大小写不匹配的 XML 文档的显示结果

3.2 XML 文档的语法和数据结构

结构良好的 XML 文档,通常是指没有语法错误的 XML 程序。XML 是一种语法要求

·47·
·48· XML 实用教程

十分严格的标记语言,因此语法有严格的限制。这里所说的结构良好的 XML 文档就是指


满足所有语法限制的 XML 文档。有关 XML 的基本语法一共有 4 条:
(1) 文件的第一条语句必须是有关版本的声明;
(2) 标记的使用必须遵循 3.1 节中的各规则;
(3) 属性的值必须用双引号括起来;
(4) 特殊字符必须使用 XML 中特定的编码来表示。
通常情况下满足以上 4 条的 XML 文档就能被 IE 检查通过,就是结构良好的 XML
文档了。

3.2.1 处理指令

处理指令是包含在 XML 文档中的一些命令性语句,目的是告诉 XML 处理一些信息或


执行一定的动作。例如想要通知 XML 解析器某篇 XML 文档所使用的编码字符集,或是要
通知 XML 解析器有关 XML 的版本信息等,都必须通过处理指令来实现。处理指令的格
式为
<?…?>
例如有关版本信息的声明指令:
<?xml version="1.0"?>

其中,“<?”和“?>”是开始和结束的界定符号,xml 是处理指令的命令名字;version
是命令中的属性,通常描述处理指令一个特定的细节;1.0 是属性的值,代表了对属性进行
的某一方面的设定。总而言之以上指令就是告诉 XML 解析器,该文档遵守 XML 1.0 规范,
应按照 XML 1.0 的要求来检查。一个结构良好的 XML 文档必须要包含有关版本的声明,
而且有关版本声明的信息必须放在整个 XML 文档的第一行。
【例 3.5】 没有版本声明的 XML 文档,代码如源程序 code3_5.xml 所示。
<?xml encoding="gb2312" ?>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>

其显示结果如图 3.4 所示。


该程序的错误在于没有关于版本信息的声明,只要在版本声明的程序语句中添加版本
信息 version=“1.0”,该程序的语法错误就能消除。在 XML 浏览器中有关版本声明的信
息在程序中只有使用英文代码的情况下可以省略,但这里不建议这样做,希望读者尽量写
出结构完整的 XML 程序。

·48·
第3章 XML 基础 ·49·

图 3.4 没有版本声明的 XML 文档的显示结果

【例 3.6】 有关版本声明的信息没有放在第一行的 XML 文档,代码如源程序 code3_6.xml


所示。
<!-- 这个文档包含网上书店中关于书的描述,文件名 code3_6.xml -->
<?xml version="1.0" encoding="gb2312" ?>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>

其显示结果如图 3.5 所示。

图 3.5 版本声明的信息没有放在第一行的 XML 文档的显示结果

该程序的错误在于有关版本声明的信息没有放在第一行,只要将其放在第一行,程序
就是一个结构良好的程序了。之所以要这样做的要求是因为 IE 开始显示一个扩展名为.xml
的文件时,就要立即检测它的版本信息,随后才能进行进一步的程序处理。

·49·
·50· XML 实用教程

还有其他方面的处理指令,在后面章节会进一步说明。

3.2.2 XML 的属性

XML 允许为元素设置属性,用来为元素附加一些额外信息,这些信息与元素本身的信
息内容有所不同。一个 XML 可以包含多个属性,从而存储一个或多个关于该元素的数据。
对于非空元素,属性的基本使用格式如下:
<开始标记属性名称 1=“属性值”属性名称 2=“属性值”…></结束标记>

<开始标记属性名称 1=“属性值”属性名称 2=“属性值”…></结束标记>
对于空元素,属性的基本使用格式如下:
<空标记属性名称 1=“属性值”属性名称 2=“属性值”…/>

<空标记属性名称 1=“属性值”属性名称 2=“属性值”…/>

【例 3.7】 属性的使用,代码如源程序 code3_7.xml 所示。


<?xml version="1.0" encoding="gb2312" ?>
<bookinfo id="001" bookcategory="文艺" amount="100" remain="80"
discount="8.7">
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>

其结果如图 3.6 所示。

图 3.6 属性使用效果图

在 XML 中设置属性时应注意:
(1) 要符合 XML 的语法格式,属性值要用引号(单引号或双引号)括起来。如下属性设
置是不合法的。
<book id=001 bookcategory=文艺 amount=100 remain=80 discount=8.7>

·50·
第3章 XML 基础 ·51·

(2) 当属性值本身含有单引号时,则用双引号作为属性的定界符,当属性值本身含有
双引号,则用单引号作为属性的定界符,当属性中既包含单引号,又包含双引号的时候,
属性值中的引号必须用实体引用方式来表示。
(3) 一个元素不可以拥有相同名称的两个属性,不同的元素可以拥有两个相同名称的
属性。如下属性设置中拥有两个名称为 anount 的属性,因此是不合法的。
<book id="001" bookcategory="文艺" amount="100" amount="80"
discount="8.7">

(4) 不但自定义标记中可以有属性,XML 文档的处理指令中也可以有属性,例如 XML


声明版本信息的 version 属性。
<?xml version="1.0" encoding="gb2312" ?>

3.2.3 特殊字符的使用

在 XML 文档中有些字符是特殊字符,这些字符的特殊之处就在于这些字符在 XML 标


记语言中已经被赋予了特殊的意义。例如“<”在 XML 标记语言中就表示所有标记的开始
记号,因而是 XML 语言的保留字符。如果现在要求将字符“<”显示在页面上该如何处理
呢?处理方法是给这些特殊字符定义一个特殊的编码。所有特殊字符所对应的编码,见
表 3-1。

表 3-1 XML 中的特殊字符表

特殊字符 代替符号 特殊的原因

& &amp; 每一个代表符号的开头字符

> &gt; 标记的结束字符

< &lt; 标记的开始字符

" &quot; 设定属性的值

' &apos; 设定属性的值

例如要在文档中显示字符“<”和“>”时,必须使用“&lt;”和“&gt;”代替。例 3.8 中
在“文艺”二字的左右边分别加上“<”和“>”符号。
【例 3.8】 特殊字符的使用,代码如源程序 code3_8.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<book bookcategory="&lt;文艺&gt; ">
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>

·51·
·52· XML 实用教程

<price>19.7</price>
</bookinfo >
</book>

其显示结果如图 3.7 所示。这里需注意特殊字符都以“&”开始,以“;”结束。

图 3.7 特殊字符的使用效果

3.2.4 XML 文档中的注释

任何成熟的计算机程序语言都必须有注释语句,对文档中其他形式的语句进行提示或
说明。这是进行大型程序设计至关重要的一项要求,XML 文档也不例外。XML 文档中的
注释和 HTML 文档中的注释是一样的,都是以下列开始符号和结束符号界定的一行或多
行代码。
<!--

-->

程序 code3_3.xml 的代码是一个带有注释的完整的 XML 文档,注释以灰色显示,表示


是一些帮助信息,而不是程序的正式语句。语法解析器将完全忽略注释中的内容。此外,
注释不能出现在文档的第一行,文档的第一行必须是有关版本信息的处理指令。由于注释
对文档起到了说明的作用,为了方便以后的阅读,希望读者能养成一个及时在程序中添加
注释的习惯。

3.2.5 程序中的文字 CDATA 标记

HTML 标记语言中有一个<pre>标记,叫做预定义格式标记,该标记当中的内容将按原
有格式被显示出来。和 HTML 中的<pre></pre>标记有点相似,XML 标记语言中也有一个
对应的标记,即 CDATA 标记。但这里注意,它们只是相似,本质上还有很大的不同。CDATA
标记的作用是通知 XML 语法解析器,该标记中的代码包括文字和标记都要当成纯文本来解
析,并原封不动的将这段代码传给下一个 XML 应用程序。界定该段代码的开始和结束标记为
<![CDATA[
… ]]>

【例 3.9】 CDATA 标记的使用,代码如源程序 code3_9.xml 所示。

·52·
第3章 XML 基础 ·53·

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


<!-- 这个文档包含网上书店中关于书的描述,文件名 code3_9.xml -->
<bookinfo><![CDATA[
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<bk/>
<price>19.7</price>
</bookinfo>
]]><title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<bk/>
<price>19.7</price>
</bookinfo>

其显示结果如图 3.8 所示。

图 3.8 CDATA 的使用

·53·
·54· XML 实用教程

3.3 XML 的相关技术

单纯的 XML 是用来描述数据的,如果没有搭配适当的样式表,在 Web 浏览器中浏览


XML 文件时,只能看到 XML 文件的树状结构,这本身意义不大。此外,要验证 XML 文
件是否正确合法,还需要有 DTD 或 XML Schema。在 XML 文件中要链接到其他的资源,
就需要 XLink、XPath 和 XPointer 等。

3.3.1 CSS

级联样式单(Cascading Style Sheet,CSS),其目的是提供一种技术手段将 Web 页面在


浏览器中的显示更加引人入胜,同时又不必像常见到的 HTML 文档那样频繁地添加控制显
示的标准标记,从而提高 XML 文档的编写效率。编写 XML 文档的过程中,通过 CSS,能
够将文档的格式化信息与文档的正文分离开来。CSS 的功能在不断被扩充,但到目前为止,
CSS 有两个官方标准:CSS1 和 CSS2。CSS1 能够实现的功能在 CSS2 中可以完成的更好。
目前,CSS1 的功能在大多数高版本的浏览器中都得到了广泛的支持。

3.3.2 DTD

文档类型定义(Document Type Definitions,DTD),就是定义一种标记语言。主要包括


一门标记语言由几部分构成,该语言都是由哪些标记构成的,这些标记的嵌套关系如何,
该语言中是否存在实体(所谓实体,就是一些特殊字符或字符串的别名,例如 HTML 的
“&nbsp;”),标记中是否可用属性,属性的取值该如何指定。简言之就是合法的 XML 文
档的“法”之所在。这在 XML 文档中不是必需的部分,但这里建议尽量写出合法的 XML
文档,一来结构严谨,二来便于以后使用程序处理该文档。

3.3.3 XML Schema

虽然 DTD 在校验 XML 文档的有效性方面非常有用,但它仍然存在许多缺陷,例如,


采用了非 XML 的语法规则、不支持多种多样的数据类型、扩展性较差等,这些缺陷使 DTD
的应用受到了很大的限制。为了解决上述问题,以 Microsoft 公司为首的众多公司提出了
XML Schema(大纲)。XML Schema 建立在 XML 之上,它的样子和一般的 XML 文档完全相
同,使得 XML 文档达到从内到外的完美统一。

3.3.4 XSL

可扩展样式语言(eXtensible Style Language,XSL),是为了格式化 XML 页面而发展起


来的一种标记语言,较 CSS 技术有许多优点。XSL 包括变换语言(Transformation Language)
和格式语言(Formatting Language)。变换语言的主要功能是将数据从一种 XML 表示转换成
另一种符合某一规范的表示,以满足某一特定需要,这种功能使它成为了基于 XML 的电
子商务、电子数据交换和无数据交换的有利工具;而格式语言的功能是描述如何显示文档
中的内容。

·54·
第3章 XML 基础 ·55·

3.3.5 XML DOM

DOM 即 Document Object Model,与 HTML 技术中的 DOM 概念相同,它把 XML 文


档的内容实现为一个对象模型,简单的说就是应用程序如何访问 XML 文档,W3C 的 DOM
Level 1 定义了如何实现属性、方法、事件等。DOM 定义了一组标准指令集,通过程序存
取 HTML 或 XML 的内容,然后通过程序中的对象集合将其显示出来。

3.3.6 XML 的链接语言

超文本链接是描述 HTML 文档中不同部分之间关系的一种技术。在 HTML 标记语言


中只是简单的一条语句,但在 XML 语言中,这种语句被扩充得十分丰富。严格来讲,超
文本链接已经不是 XML 标记语言的一部分,而是一种独立的链接语言。XML 的链接语言
目前主要由 3 部分构成,分别为 XLink 、XPath 和 XPointer。
XLink 支持一般的链接,就像在 HTML 中链接一样,也支持更为复杂的链接。XLink
不仅可以在 XML 文件之间建立链接,而且可以建立其他类型数据之间的链接。不仅如此,
还可描述与非 XML 文件之间的链接关系。
XPath 主要是描述一个路径位置,而位置可以分成相对位置路径和绝对位置路径。一
个相对位置路径事实上包含一连串的寻址步骤,每个寻址步骤是以斜杠“/”进行分隔的。
整个相对位置路径就是这些寻址步骤从左到右结合在一起的。至于绝对路径本身就包含斜
杠“/”,此处所使用的斜杠代表的是根节点,它包括目前的节点。
XML 是结构化的文件,这使得借助文件结构进行内部定位成为可能,此时无需对文件
本身进行修改,这就是 XPointer。XPointer 用于在资源内定位,它支持在 XML 文件中定位
元素、属性、字符串等内部结构。

3.4 XML 名称空间

XML 是一种元标记语言,允许用户定义自己的标记,因此,很可能出现名称重复的情
况。为了解决这个问题,W3C 在 1999 年 1 月颁布了名称空间(Name Space)标准。该标准对
名称空间的定义是:XML 名称空间提供了一套简单的方法,将 XML 文档和 URI 引用标记
的名称相结合,来限定其中的元素和属性名。由此可知它通过使用 URI,解决了 XML 文
档中标记重名的问题,从而确保任何一篇 XML 文档中使用的名字都是全球范围内独一无
二的。原则上一个不使用名称空间的 XML 文档是一个实用意义不大的文档,因为在全球
范围内很可能有和它同名的标记存在。

3.4.1 名称空间的声明

在使用名称空间之前,必须首先进行声明,名称空间的声明类似于前面元素的声明,
将一个唯一的标识符号指定到一个 URI 或其他合法字符串上,使用前面定义的标识符号作
为标记的前缀,表示一类标记的出处。

·55·
·56· XML 实用教程

【例 3.10】 名称空间的声明,文件名 code3_10.xml。


<?xml version="1.0" encoding="gb2312" ?>
<book:bookinfo xmlns:book="http://bestbook.jmu.edu.cn/cs/textbook">
<book:title>计算机导论</book:title>
<book:author>丁跃潮等</book:author>
<book:price>19.7</book:price>
</book:bookinfo>

其中,xmlns 是一个专门用来指定名称空间的关键字,book 是为了 XML 文档中使用


方便而随便起的一个名字,它被用来标识字符串“http://bestbook.jmu.edu.cn/cs/textbook”。
因为通常情况之下,后面的 URI 很长,使用起来和读起来都很不方便,而“book”就是给
该长字符串临时起的一个简短好用的名字,它可以是任意合法的字符串。
这里需要指出的是,字符串“http://bestbook.jmu.edu.cn/cs/textbook”并不是实际存在的
网页,它可以是其他任何合法的字符串。只是采用 URI 的形式便于确保唯一性,一般采用
编程人员所在单位的网址变形而成。如果不采用网址而是用随意的字符串,那么其他人员
随意采用的字符串就可能与其相同而发生冲突。
名称空间声明好以后,就可以使用它了,使用方法:
<book:title>计算机导论</book:title>

注意在声明名称空间时可以将多个声明结合在一起,例如下面语句:
<book:bookinfo xmlns:book1="http://bestbook.jmu.edu.cn/cs/textbook"
xmlns:book2="http://cheapbook.jmu.edu.cn/ee/textbook">

名称空间具有继承性,也就是说,如果不明确声明子元素的名称空间,子元素将继承
父元素的名称空间声明。但要注意的是,在默认声明的名称空间范围内,所有的元素及其
子元素不加前缀,而在显示声明的名称空间范围内,所有的元素及其子元素必须加前缀。
【例 3.11】默认声明与显示声明名称空间的 XML 文档,代码如源程序 code3_11.xml 所示。
<?xml version="1.0" encoding="gb2312"?>
<book xmlns="http://bestbook.jmu.edu.cn/cs/textbook" xmlns:bo="
http://cheapbook.jmu.edu.cn/ee/textbook">
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<price>19.7</price>
</bookinfo>
<bo:publish>
<bo:publisher>高等教育出版社</bo:publisher>
<bo:ISBN>7-04-014768-8</bo:ISBN>
<bo:pubdate>2004.6</bo:pubdate>
</bo:publish>
</book>

3.4.2 名称空间的范畴

名称空间的范畴就是名称空间起作用的范围。而范围就是声明该名称空间的元素及该
元素中所有的子元素,除非是在该元素的某一个子元素上又声明了相同的名称空间。

·56·
第3章 XML 基础 ·57·

【例 3.12】 声明名称空间的范围,文件名 code3_12.xml。


<book:bookinfo xmlns:book="http://book.jmu.edu.cn/it/textbook">
<title>计算机导论</title>
<author>丁跃潮等</author>
<book:publish xmlns:book="http://bestbook.jmu.edu.cn/cs/textbook">
<book:publisher>高等教育出版社</book:publisher>
<book:ISBN>7-04-014768-8</book:ISBN>
<book:pubdate>2004.6</book:pubdate>
</book:publish>
<book:price>19.7</book:price>
</book:bookinfo>

上面的程序当中,用了同名的两个名称空间。第一个名称空间的作用范围是除了
<publish>标记块的整个文档内容,属于 http://book.jmu.edu.cn/it/textbook 名称空间。因为
<publish>标记块的内容中使用的名称空间为 http://bestbook.jmu.edu.cn/cs/textbook,它是一
个独立的区域,第一个名称空间的作用范围要去除该区域。

3.5 开发工具 XMLSpy 与 XML 实例

XML Spy 是 Icon Information-Systems 公司的产品,它的显示界面在第 1 章中已做了介


绍。这里介绍使用 XML Spy 编辑 XML 文档的方法。
XML Spy 支持 Unicode、多字符集,支持 Well-formed 和 Validated 两种类型的 XML
文档,并可编辑 XML 文档、DTD、Schema 以及 XSLT。它的最大特点是提供了 4 种视窗:
XML 结构视窗、增强表格视窗、源代码视窗及支持 CSS 和 XSL 的预览视窗。结构视窗以
树状结构编辑 XML 文档(包括 XML、XSL 文档,但对 DTD 文档的显示相对较为简单);增
强表格视窗以表格的方式显示出文档中的某一项元素的数据库项;源代码视窗可以查看和
修改文档源码,并且以不同的颜色标注不同的元素;预览视窗采用内嵌 IE 6.0 的方式在软
件内对 XML 文档进行浏览,支持 CSS 和 XSL。
XML Spy 可支持 DTD、DCD、XDR、BizTalk、XSD 的编辑与有效性检查。XML Spy
也提供集成开发环境 IDE,但仍不支持所见即所得。
XML Spy 目前的最高版本是 2005 版,可运行在 Windows 95/98/Me/XP/2000/2003 环境
中。本教程主要以 XML Spy 作为编辑和验证工具,并作为浏览工具。
这里以程序 code 3_13.xml 为例使用 XMP Spy 建立一个简单的 XML 文档。
【例 3.13】 XML 文档编辑实例,代码如源程序 code3_13.xml 所示。
<?xml version="1.0" encoding="gb2312"?>
<!-- 这个文档包含网上书店中关于书的描述,文件名 code3_13.xml -->
<books>
<book id="018" category="计算机" amount="560" remain="200" iscount="8.2">
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>

·57·
·58· XML 实用教程

<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>
</book>
<book id="001" category="文艺" amount="100" remain="80" discount="8.7">
<bookinfo>
<title>三国演义</title>
<author>罗贯中</author>
<publish>
<publisher>文艺出版社</publisher>
<ISBN>0-764-58007-8</ISBN>
<pubdate>1998.10</pubdate>
</publish>
<price>80.00 </price>
</bookinfo>
</book>
</books>

XML Spy 的安装比较简单,这里省略。安装后按以下步骤操作。

1. 建立根结点

选择菜单 File | New,弹出 Create new document 对话框,选择里面的 XML(XML


Document)。弹出的 New File 对话框中要求选择 DTD 或 Schema,这是指所建立的 XML 文
档采用何种验证机制,可以先都不选,即单击 Cancel 按钮。
若使用的是 XML Spy 2004,一个空的 XML 文档就会被建立在 Grid 视图区中,界面主
要部分如图 3.9 所示。编码方式项 encoding 默认值为 UTF-8,这里将其改为 gb2312。鼠标
置于 XML 灰绿色拐形区域,单击鼠标右键,在弹出的快捷菜单中选择 Insert | Element,或
选择 Append | Element(因为此时是空文档,插入和追加是一样的),这时增加了一行。在“<>”
符号后面双击并输入 books 字样,即建立了根元素。可以为这个 XML 文档加入注释,选中
books 后,单击鼠标右键在弹出的快捷菜单上选择 Append | Comment,在出现的“<!..”符
后边输入“这个文档包含网上书店中关于书的描述,文件名 code3_13.xml”字样,也可以
不加这条注释。bookinfo 根元素建立后的主要部分如图 3.10 所示。

图 3.9 空 XML 文档的主要界面 图 3.10 建立了根元素 books 后的界面

如果使用的是 XML Spy 2005,情况有所改变。进入 XSL Spy 界面后,出现的是 Text


视图区,并且因为出错而不能直接转换到 Grid 视图区。Text 视图区的第一行为<?xml

·58·
第3章 XML 基础 ·59·

version=“1.0”encoding=“UTF-8”?>,将其中的 UTF-8 改称 gb2312,然后增加一行<books>


</books>,在单击界面下方的 Grid 即可转换到上述正常编辑状态。
2. 增加子元素

选中(单击)books 这一行的区域,单击鼠标右键,在弹出的快捷菜单中选择 Add child |


Element,在 books 区域的子区域内出现“<>”符,选中后并输入 book 字样,即增加了子
元素 book。建立好 book 子元素后的主要部分如图 3.11 所示。

图 3.11 建立了子元素 book 后的界面

再按如上方法建立 book 的子元素 bookinfo 以及 bookinfo 的子元素 title、author、publish、


price,和 publish 的子元素 publisher、ISBN、pubdate。
其中添加多个子元素的方法有两种,这里以元素 bookinfo 为例进行说明。第一种是选
中 bookinfo 区域中 title 子区域以外的拐形区域,即处于 bookinfo 角度上,同样单击鼠标右
键选择 Add child | Element,接着输入子元素名 author。第二种方法是选中 title 子区域,即
处在 title 的角度上,单击鼠标右键选择 Append | Element,接着输入子元素名 author。请读
者撤销上述步骤,重新试验,体会不同角度 Add child 和 Append 的区别。

3. 给子元素输入内容

给子元素输入内容,只需在相应子元素的右侧空格内输入所需内容即可。如给 title 输
入内容,界面的主要部分如图 3.12 所示。

图 3.12 给 title 元素输入内容后的主要部分界面

4. 给子元素增加属性

<book id="001" category="文艺" amount="100" remain="80" discount="8.7">

上述语句行中的 id、category、amount、remain、discount 都是 book 元素的属性。一个


元素的属性和子元素是等价的,都是描述这个元素的性质和状态的,这一点后续部分还将
说明。但是,属性与元素的写法和表现形式是不一样的。

·59·
·60· XML 实用教程

选中 book 区域,单击鼠标右键选择 Add child | Attribute 即出现“=”标记的属性区域,


输入属性名 id,这样就增加了 book 元素的属性 id。在其右侧的格子内输入 id 的值 001。
接下来输入 book 的其他 4 个属性,仍然是两种办法,处在 book 的角度上要选择 Add
child | Attribute,处在属性 id 的角度上要选择 Append | Attribute。属性排列有顺序,如果要
在一个属性之前插入属性,要选择 Insert | Attribute。完成 category、amount、remain、discount
这 4 个属性的输入,并且都在右侧格子中输入属性的对应值。完成后,主要界面如图 3.13
所示。

图 3.13 book 的属性输入后的效果

现在可以体会界面中项目折叠和打开的效果了,请单击 XML 和 document 左侧的黑三


角符进行体会。

5. 添加第二个 book 元素

这是和前一个 book 并行的,只要处在 books 的非子区域的角度,单击鼠标右键选择


Add chills | Element 即可,或者处在 book 的角度上选择 Append | Element。重复上述操作即
可完成,不过这种重复很烦琐。
最简单的办法是选中 book 区域(展开或非展开状态均可),单击鼠标右键选择 Copy | Paste,
这样两个完全相同的 book 元素就并行存在了,而且排列形式也有所变化,更合理。只需要
将第二个 book 元素的各属性值及其子元素的值进行修改,就形成一个区别于前一个 book
的元素了。添加第二个 book 元素后的结果如图 3.14 所示。
经过上述操作,就形成程序 code3_13.xml 文件的内容。前面的操作都是在界面的 Grid
视图中进行的。可以在界面下部单击 Text 视图,查看 XML 文本,也可单击 Browser 视图,
浏览 XML 文件,浏览时单击行前面的“+”或“-”可以打开或折叠相应级别的元素。
在 Grid 或 Text 视图界面下,可以检查当前编辑的 XML 文档的语法和格式是否良好。
按 F7 键、选择 XML 菜单中的 check well-formedness 命令或在工具栏上单击相应的按钮即
可进行该项检查。如果格式存在问题,进行修改后再作检查。这里指检查各层次标记是否
匹配和合理闭合,并非做后续部分要学习的 DTD 和 Schema 意义上的严格检查。

·60·
第3章 XML 基础 ·61·

图 3.14 文件 code3_13.xml 完成编辑后界面的主要部分

3.6 小 结

HTML 是 XML 的基础,用于显示信息,是网上展示信息的基本工具。XML 扩展了


HTML 的标记和功能。作为元标记语言,XML 可以在文档中创建、使用新的标记和文法
结构。
作为标记名字的字符串必须以字母或下划线开头,中间不能有空格,并且只能包含英
文字母、数字和“_”、“-”、“.”等字符。
XML 声明是一个 XML 文档的开始,它必须以“<?xml”开始,以“?>”结束。XML
的非空标记由开始标记与结束标记组成,其中,开始标记的一般形式为<标记名>,结束标
记的一般形式为</标记名>。空标记的一般形式为<标记名/>。在声明 XML 标记时,必须遵
循标记的命名规则。元素是文档的主题,可以为元素定义属性。在编辑 XML 文档时,如
果需要用到特殊符号的话需要用实体引用,如果要为文档进行说明的话可以添加注释。
XML 的相关技术主要有 CSS、DTD、XML Schema、XML DOM、XSLT、XLink、XPath
和 XPointer。
名称空间的使用是为了解决 XML 文档中命名冲突的问题。

3.7 习 题

1. XML 文档中标记的使用有哪些需注意的方面?
2. 如何为一个 XML 文档添加注释?
3. 举例说明为什么要引入名称空间,如何声明名称空间。
4. 在 XML 文档中,若元素 teacher 的内容为:dingxiao asked“Can I help you?”,则

·61·
·62· XML 实用教程

该元素应该如何编写?
5. 使用 XML Spy 2005 编辑下列 XML 文档。
<?xml version="1.0" encoding="gb2312" ?>
<document>
<title>
user order list of E-shop
</title>
<order>
<customerID>XXXXXXXX</customerID>
<order_date>20040517</order_date>
<order_status>pending</order_status>
<item>
<bookID>001</bookID>
<quantity>1</quantity>
<order_item_status>pending</order_item_status>
</item>
</order>
</document>

6. 下面是一个网上购物订单,将它写成 XML 格式。


顾客编号:X00349827,订单号:DD934809,订货时间:2004-05-17;
付款方式:邮局汇款,通讯地址:xxx 市 xxx 路 xxx 号,邮编:123456;
汇款地址:yyy 市 yyy 路 yyy 号,收款人 xxxx 书店;
定书号:001,书名:AAA,数量:1,价格:34.00;
定书号:002,书名:BBB,数量:1,价格:29.00;
定书号:003,书名:CCC,数量:1,价格:41.00。

·62·
第 4 章 XML 文档类型定义

教学提示:XML 的可扩展性表现在用户可以自己定义标记和标记之间的嵌套关系,而
DTD 就是进行这种定义的语言。它定义了文档的逻辑结构,规定了文档中所使用的元素、
实体、元素的属性、元素与实体之间的关系。根据 DTD 可检查 XML 文档中的数据,以验
证其是否符合规定和要求,这可以保证 XML 文档数据的正确性和有效性。本章介绍 DTD
的语法,包括元素、属性和实体的语法,结合例子给出 DTD 的使用方法并给出综合实例。
教学目标:了解 DTD 的作用,熟悉元素、属性及实体的运用,掌握引用 DTD 的方法,
能够为特定的系统设计标记语言。

4.1 DTD 的作用

XML 文档是一种元标记语言,即一种定义标记语言的语言。在 XML 中可以创建新的


标记语言,这些新的标记语言(也叫标记集)要通过文档类型定义(Document Type Definitions,
DTD)来定义。DTD 文档是这些新的标记语言的法律性文档。如果 XML 文档的语法符,DTD
的定义和规定,那么就称为一个合法的 XML 文档,否则就是非法的 XML 文档。合法的
XML 文档在实际应用中的地位很重要,因为只有合法的 XML 文档才能被应用软件有效地
处理。
DTD 定义了文档的逻辑结构,规定了文档中所使用的元素、实体、元素的属性、元素
与实体之间的关系。其作用主要表现在以下几个方面。
(1) 使用 DTD 可以提供一种统一的格式。XML 的可扩展性为文档的作者提供了很高
的灵活性,可有时候需要的是统一,要求某一类文档具有相同的结构。
(2) 使用 DTD 可以保证数据交流和共享的顺利进行。
(3) DTD 使用户能够不依赖具体的数据就知道文档的逻辑结构。在没有 XML 文档的时
候,也可以根据 DTD 为 XML 文档编写样式单,编写处理程序,这样可以有效地提高工作
效率。
(4) 使用 DTD 可以验证数据的有效性。DTD 对文档的逻辑结构进行了约束,这种约束
可以比较宽松,也可以十分严格。可以根据 DTD 检查数据,以验证其是否符合规定和要求,
这可以保证数据的正确和有效。
·64· XML 实用教程

4.2 DTD 元素

DTD 中描述的基本部件是元素和属性,它们负责确定 XML 文档的逻辑结构。元素表


示一个信息对象,而属性表示这个对象的性质。所有元素中有且只有一个根元素,其他的
元素都是它的子元素,除根元素外,每个元素都被其他元素包含,一个元素可以有几个不
同类型的子元素。

4.2.1 元素的基本类型

元素的基本类型大致可分为两种,一种称为简单型,另一种称为复合型。简单型具有
文本数据,即可析字符数据,该类型也称为上下文中的“#PCADTA”;复合型可以包含其
他元素和文本数据。
1. 简单型
“#PCDATA”(Parsed Character Data)表示标记的内容是可解析文本,所谓的可解析文
本就是非标记文本。用“#PCDATA”规范了的元素不能再包含子元素。例如 How do you do
是不包含标记的文本,而 How do you <list>do</list>就不是可解析的数据类型,因为其中包
含有标记<list>和</list>。另外 DTD 文档中不同元素定义的次序没有先后关系,但文档的语
法对大小写敏感。
“#PCDATA”的声明格式:
<!ELEMENT Element_Name (#PCDATA )>
【例 4.1】 “#PCDATA”的用法,代码如源程序 code4_1.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE bookinfo [
<!ELEMENT bookinfo (title,author,publisher,price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publisher>高等教育出版社</publisher>
<price>19.7</price>
</bookinfo>

其显示结果如图 4.1 所示。


2. 复合型
复合型元素与简单型元素相对,复合型元素可包含其他元素。

·64·
第4章 XML 文档类型定义 ·65·

图 4.1 “#PCDATA”的用法

【例 4.2】 复合型元素的用法,代码如源程序 code4_2.xml 所示。


<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE bookinfo [
<!ELEMENT bookinfo (title,author,publish,price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT publish (publisher,ISBN,pubdate)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT ISBN (#PCDATA)>
<!ELEMENT pubdate (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>

其显示结果如图 4.2 所示。

图 4.2 复合型元素的用法

·65·
·66· XML 实用教程

4.2.2 元素的声明

1. 元素声明的基本语法
元素的声明格式:
<ELEMENT Element_Name Element_Defination>
其中,Element_Name 为声明的元素名称,Element_Defination 为元素内容格式的定义。
合法的元素声明语句如:
<!ELEMENT bookinfo (title,author,publish,price)>
<!ELEMENT publisher (#PCDATA)>

2. 空元素的声明
在第 3 章中已介绍了空标记的使用方法,那么在 DTD 中如何对与其对应的空元素进行
声明呢?其声明格式:
<ELEMENT Element_Name EMPTY>
例如下面的语句:
<ELEMENT hr EMPTY>

3. 不限定元素内容的声明
ANY 是 DTD 中使用很频繁的一个关键字,特别是对于文档根元素的声明。在定义一
个 DTD 文档时通常很难准确地确定一个元素是否具有子元素的情况,此时一般的做法是指
定该元素的子元素为 ANY 型(表示可以是任意的元素),这样在它之中可以包含任何数据、
任何声明的子元素及其数据和子元素的组合。
ANY 元素的声明格式:
<!ELEMENT Element_Name ANY>
而在文档刚开始定义时,并不明确将来的应用领域中会有多少个元素,所以唯一的做
法就是标记为 ANY 类型,表示可以包含任何元素和可解析数据。例如:
<!ELEMENT person ANY>

然后在文档的实际开发过程中再逐步完善该元素的子元素的具体定义,将 ANY 关键
字替换掉。
【例 4.3】 ANY 的用法,代码如源程序 code4_3.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE bookinfo [
<!ELEMENT bookinfo ANY>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]>
<bookinfo>

·66·
第4章 XML 文档类型定义 ·67·

<title>计算机导论</title>
<author>丁跃潮等</author>
<publisher>高等教育出版社</publisher>
<price>19.7</price>
</bookinfo>

显示结果与例 4.1 的相同。


文档中能有多个 ANY 型的元素吗?这是完全可以的,因为 ANY 型的元素不一定是根
元素。
【例 4.4】 包含多个 ANY 型元素的 XML 文档,代码如源程序 code4_4.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE bookinfo [
<!ELEMENT bookinfo ANY>
<!ELEMENT title ANY>
<!ELEMENT author ANY>
<!ELEMENT publisher ANY>
<!ELEMENT price ANY>
]>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publisher>高等教育出版社</publisher>
<price>19.7</price>
</bookinfo>

ANY 型的元素在文档中应尽量少使用,因为这与 XML 文档的数据结构性相违背。但


多数情况之下在定义一个元素的所有子元素之前,总是首先以 ANY 代替,最后再以实际
的子元素替代 ANY 关键字,定义出具体的 DTD 文档。
4. 子元素列表的设定
在 XML 中有一种针对复合元素的最为严格的设定方法,称为子元素列表的设定。这
种方式下,元素都拥有哪些子元素、每个子元素出现的次数和位置都有明确的规定,在具
体文档实现时,必须严格执行。
子元素列表的设定语法如下:
<!ELEMENT Element_Name(Child_Element1, Child_Element2,…)>
其中“(Child_Element1, Child_Element2,…)”部分为 Element_Name 所拥有的子元素列表。
【例 4.5】 子元素列表的设定,代码如源程序 code4_5.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE bookinfo [
<!ELEMENT bookinfo (title,author,publish,price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT publish (publisher,ISBN,pubdate)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT ISBN (#PCDATA)>
<!ELEMENT pubdate (#PCDATA)>

·67·
·68· XML 实用教程

<!ELEMENT price (#PCDATA)>


]>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<pubdate>2004.6</pubdate>
<ISBN>7-04-014768-8</ISBN>
</publish>
<price>19.7</price>
</bookinfo>

上面程序是一个不合法的文档,原因在于,标记<pubdate></pubdate>和<ISBN></ISBN>
的使用顺序与 DTD 中定义的顺序不一致。在一个标记后面的子标记列表中,子标记出现的
次序代表了将来 XML 文档中的子标记出现次序,而且这种次序不能被违背。
5. 可选择的子元素
有些时候,需要在两个或多个互斥的元素中进行选择。即多选一的情况,如一个人的
性别可以是男或女,两者中只能有一种情况。DTD 有专门的语法来处理这种情况,其语法
格式如下:
<!ELEMENT Element_Name(Child_Element1|Child_Element2|……)>
其中,“(Child_Element1|Child_Element2|…)”部分为选择性元素组合,具体使用时必
须要在这个列表中选择其一。
【例 4.6】 选择性元素列表的设定,代码如源程序 code4_6.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE bookinfo [
<!ELEMENT bookinfo (title,author,publish,price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT publish (publisher|ISBN|pubdate)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT ISBN (#PCDATA)>
<!ELEMENT pubdate (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
</publish>
<price>19.7</price>
</bookinfo>

·68·
第4章 XML 文档类型定义 ·69·

6. 元素出现次数的控制

在 DTD 中定义一个元素的子元素无非是解决该元素可以包含什么元素,各个子元素的
出现次序以及能够出现的次数的问题。DTD 可以在一定程度上控制出现的次数。太精确太
复杂的控制是不必要的。如明确规定一个元素出现 3 次或 4 次,是容易使到的,使用上面
介绍的子元素列表的设定方法即可实现,但如果重复出现的次数较多时,这种方法就显得
十分笨拙,这时可用以下方法来对其进行控制。
(1) 一个元素可能出现一次,也可能不出现。这时可通过在元素名后面加上一个“?”
来实现。
(2) 一个元素可能不出现,也可能出现多次。这时可通过在元素名后面加上一个“*”
来实现。
(3) 一个元素可能出现一次,也可能出现多次,但至少也要出现一次。这时可通过在
元素名后面加上一个“+”来实现。

7. 元素组

在声明复合型元素的时候,可以使用括号将其部分子元素组合在一起,成为一个元素
组,该元素组在特性上与普通元素没什么区别,可以对其使用“?”、
“*”、
“+”等控制字符。
【例 4.7】 元素组的使用,代码如源程序 code4_7.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE bookinfo [
<!ELEMENT bookinfo ((title,author,price)+)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<price>19.7</price>
<title>三国演义</title>
<author>罗贯中</author>
<price>50.0</price>
</bookinfo>

其显示结果如图 4.3 所示。


在实际应用中,使用元素组可能不是最好的方案。这时也可以先将准备分组的元素定
义为一个复合元素,再在原来的元素中引用刚定义的复合元素,这样文档的结构更清晰。

·69·
·70· XML 实用教程

图 4.3 元素组的使用

【例 4.8】 较好的方案,代码如源程序 code4_8.xml 所示。


<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE bookinfo [
<!ELEMENT maininfo (title, author, price)>
<!ELEMENT bookinfo (booknumb, maininfo+)>
<!ELEMENT booknumb (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]>
<bookinfo>
<booknumb>2</booknumb>
<maininfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<price>19.7</price>
</maininfo>
<maininfo>
<title>三国演义</title>
<author>罗贯中</author>
<price>50.0</price>
</maininfo>
</bookinfo>

其显示结果如图 4.4 所示。

图 4.4 较好的方案

·70·
第4章 XML 文档类型定义 ·71·

8. 混合型元素
还有另一种元素,其内容既可以为字符数据,也可以为子元素,这种元素称为混合型
元素。混合型元素的声明格式:
<!ELEMENT Element_Name(#PCDATA|Child_Element1|Child_Element2,…)>
混合型元素的存在破坏了文档的层次结构化,不利于应用软件对 XML 文档的处理,
在 XML 文档开发过程中,它可以作为一个不成熟的 DTD 文档,一步一步地在 XML 文档
中添加元素,边添加边测试其正确性,这时可将尚未处理的部分作为字符数据组织到一个
混合型元素中,以便使文档通过测试。但在文档最后完成时,要通过添加新元素的方法来
清除这种非结构化信息。

4.3 DTD 属性

什么是属性?简单来讲就是元素的附加特性,在 DTD 中声明元素时,也必须对该元素


的属性进行声明。

4.3.1 属性的声明

在 DTD 中,属性的声明格式:
<!ATTLIST Element_name Attribute_name TYPE Default_value>

其中,<!ATTLIST>为属性声明的关键字,Element_name 为元素名,Attribute_name 为
属性名,TYPE 是属性类型,Default_value 为没有设定属性值时的默认值。
【例 4.9】 属性的声明,代码如源程序 code4_9.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE bookinfo [
<!ELEMENT bookinfo (title,author,publisher,price)>
<!ATTLIST bookinfo ISBN CDATA "7-04-014768-8">
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]>
<bookinfo ISBN="7-04-014768-8">
<title>计算机导论</title>
<author>丁跃潮等</author>
<publisher>高等教育出版社</publisher>
<price>19.7</price>
</bookinfo>

其显示结果如图 4.5 所示。

·71·
·72· XML 实用教程

图 4.5 属性的声明

在声明属性时有以下需要注意的事项。
(1) 可以多次为一个元素声明其中所包含的属性。如在 XML 文档中有如下语句:
<bookinfo id="001" bookcategory="文艺" >
</bookinfo>

属性声明可以为
<!ATTLIST bookinfo id CDATA "001">
<!ATTLIST bookinfo bookcategory CDATA "文艺" >
<!ELEMENT bookinfo (#PCDATA)>

(2) 属性的声明在文档中的次序没有严格的要求,可位于与其相连的元素声明之前或
之后。如在 XML 文档中有如下语句:
<bookinfo id="001" bookcategory="文艺" >
</bookinfo>

属性声明可以为
<!ATTLIST bookinfo bookcategory CDATA "文艺" >
<!ATTLIST bookinfo id CDATA "001">
<!ELEMENT bookinfo (#PCDATA)>

(3) 所有元素的属性,都要在各自所对应的标记中声明。如在 XML 文档中有如下语句:


<bookinfo id="001" bookcategory="文艺" >
</bookinfo>
<publish publisher="高等教育出版社" ISBN="7-04-014768-8">
</publish>

属性声明可以为
<!ATTLIST bookinfo bookcategory CDATA "文艺" >
<!ATTLIST bookinfo id CDATA "001">
<!ELEMENT bookinfo (#PCDATA)>
<!ATTLIST publish publisher CDATA "高等教育出版社" >
<!ATTLIST publish ISBN CDATA "7-04-014768-8">
<!ELEMENT publish (#PCDATA)>

·72·
第4章 XML 文档类型定义 ·73·

(4) 属性有 4 种不同类型的默认值,可在属性声明中的 Default_value 部分指定。


① default:表示使用提供的默认值,default 不是一个关键字,它代表一个预设的字
符串。
<!ATTLIST bookinfo bookcategory("文艺"|"自然科学")"文艺" >

此例句表示当在 XML 文档中省略了对 bookinfo 元素的 bookcategory 属性值进行设定


时,该属性的默认值就是“文艺”。
② #REQUIRED:表示属性值必须指定。
③ #IMPLIED:表示元素的这个属性可用可不用。
④ #FIXED:表示元素的这个属性值是一个固定值,且必须是指定的值。

4.3.2 属性的类型

在属性的声明中 TYPE 部分为属性的类型设定,DTD 中属性的类型有 10 种,下面将


对这些数据类型进行逐一的介绍。
1. CDATA 型
CDATA 型表明属性值为不包含“<”和“"”的任意字符串,如果属性值中需要包含
“<”和“"”,则可使用特殊字符来代替。
2. Enumerated 型
如果属性值并不是任意的字符串,而是在几个可能的值中进行选择,如书籍的“类别”
属性,其值可为“文艺”,也可为“自然科学”,而不可能为其他情况时,则可以将书籍
的“类别”属性设定为 Enumerated 型。
3. ID 型
当元素的某个属性值是不能重复时,如书籍的 ISBN 属性、个人的“身份证号”属性
等,要定义这样的属性则需使用属性的 ID 类型。在一个 XML 文档中,所有元素的 ID
类型属性的属性值必须是唯一的,不可重复,另外,一个元素不能有超过一个 ID 类型的
属性。
4. IDREF 与 IDREFS 型
IDREF 为 Identifier Reference 的缩写,IDREF 与 ID 类型属性的关系为子元素与父元素
的关系,即 IDREF 类型属性的值必须是其他元素的 ID 类型属性的值,且该 ID 类型属性的
值必须在文档的其他地方被设定过。IDREFS 类型属性的属性值可有多个,每一个都必须
是在文档其他地方被设定了的 ID 类型属性的值,而这多个属性值之间用空格隔开。
【例 4.10】 IDREFS 的使用,代码如源程序 code4_10.xml 所示。
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE school [
<!ELEMENT school (teacher, subject*)>
<!ELEMENT teacher (#PCDATA)>
<!ELEMENT subject (#PCDATA)>
<!ATTLIST teacher

·73·
·74· XML 实用教程

teach IDREFS #IMPLIED


>
<!ATTLIST subject
number ID #REQUIRED
>
]>
<school>
<teacher teach="c0001 c0002 c0003">
丁潇
</teacher>
<subject number="c0001">
PowerBuilder
</subject>
<subject number="c0002">
AutoCAD
</subject>
<subject number="c0003">
XML
</subject>
</school>

其显示结果如图 4.6 所示。

图 4.6 IDREFS 的使用

5. ENTITY 与 ENTITIES 型
ENTITY 类型的属性提供了把外部二进制形式的文件(如.jpeg、.mp3 等)和外部不可解
析实体链接到 XML 文档的功能。因此其属性值也必须为不可解析的链接外部实际数据的
通用实体名。ENTITIES 类型属性的属性值可由多个不可解析的外部实体名称组成,各实体
名称之间使用空格隔开。
【例 4.11】 ENTITY 与 ENTITIES 的使用,代码如源程序 code4_11.xml 所示。
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE customers [
<!ELEMENT customers (customer*)>
<!ELEMENT customer (username, password, picture)>
<!ELEMENT username (#PCDATA)>
<!ELEMENT password (#PCDATA)>

·74·
第4章 XML 文档类型定义 ·75·

<!ELEMENT picture EMPTY>


<!ATTLIST picture pic ENTITIES #REQUIRED
>
<!ATTLIST customer
ID #REQUIRED
>
<!ENTITY pic1 SYSTEM "a.jpg">
<!ENTITY pic2 SYSTEM "b.jpg">
<!ENTITY pic3 SYSTEM "c.jpg">
<!ENTITY pic4 SYSTEM "d.jpg">
]>
<customers>
<customer ID="c0500103">
<username>cheaperget</username>
<password>12345678</password>
<picture pic="pic1 pic2"/>
</customer>
<customer ID="c0500208">
<username>dreamingboy</username>
<password>22345678</password>
<picture pic="pic3 pic4"/>
</customer>
</customers>

本例不是所有 XML 浏览器都可以自动识别的通用格式,仅仅某些浏览器和应用程序


可能采用的在文档中嵌入非 XML 数据的方法而已。
6. NMTOKEN 与 NMTOKENS 型
NMTOKEN 类型的属性限定属性值是有效的 XML 名称,这个属性值可以由英文、数
字、“.”、 “_”、“-”、“:”等组成,这里有几点需要注意。
(1) 不能包括空格。
(2) 以上字符中除“:”以外,其他字符都可以作为开头字符。
(3) “:”可以出现在中间,但由于它是命名域的关键字符,所以一般不提倡使用。
正因为 NMTOKEN 类型的属性对于字符的严格要求,使得它在一些常用编程语言中,
都是合法的数据,这就为这些编程语言对 XML 文档数据的操作打下了良好的基础。
NMTOKENS 类型的属性具有与 NMTOKEN 属性相近的形式。这种类型的属性可以使如
下情况合法——属性由若干 XML 名称组成,彼此间由空格隔开。通常可为使用 NMTOKEN
属性相同的理由而使用 NMTOKENS 属性,但仅仅在需要多个名字的时候。
7. NOTATION 型
XML 文档中引入了外部不可解析的实体后,解析器无法解析这些二进制文件,这时,
就可以使用 NOTATION 类型的属性为这些二进制文件指定与其对应的应用软件以对其进
行处理。
【例 4.12】 NOTATION 的使用,代码如源程序 code4_12.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE customers [

·75·
·76· XML 实用教程

<!ELEMENT customers (customer*)>


<!ELEMENT customer (username,password,picture)>
<!ELEMENT username (#PCDATA)>
<!ELEMENT password (#PCDATA)>
<!NOTATION mspaint SYSTEM "C:\WINDOWS\system32\mspaint.exe">
<!ELEMENT picture EMPTY>
<!ATTLIST picture pic ENTITIES #REQUIRED>
<!ATTLIST picture procedure NOTATION #REQUIRED>
<!ATTLIST customer ID ID #REQUIRED>
<!ENTITY pic1 SYSTEM "a.jpg">
<!ENTITY pic2 SYSTEM "b.jpg">
<!ENTITY pic3 SYSTEM "c.jpg">
<!ENTITY pic4 SYSTEM "d.jpg">
]>
<customers>
<customer ID="c0500103" >
<username>cheaperget</username>
<password>12345678</password>
<picture pic="pic1 pic2" procedure="mspaint"/>
</customer>
<customer ID="c0500208" >
<username>dreamingboy</username>
<password>22345678</password>
<picture pic="pic3 pic4" procedure="mspaint"/>
</customer>
</customers>

4.4 DTD 中的实体

在第 3 章中已经接触了预定义实体,在 DTD 中,还存在自定义实体,定义后依照一定


的语法规则可在 XML 文档或 DTD 中进行引用。

4.4.1 实体的概念

实体是包含了文档片段的虚拟存储单元,可用来存储 XML 声明、DTD、其他形式的


文本及二进制数据等。简单来讲就是一段代码或数据的代称,这个代称即为实体的名字。
当需要在文档中引用某段代码或数据时,可以引用与这段代码或数据相对应的实体名称来
代替实体的具体内容。具有正确性检查功能的 XML 处理器在提交文档给最终应用程序之
前或在显示文档以前,将先把所有不同的实体引用替换为与其对应的具体内容,从而构成
一个结构完整的文档。

4.4.2 实体的分类

按照实体的具体内容来分类,实体可分为可解析与不可解析两类。可解析实体的具体
内容为简单的字符、数字、文本块,而不可解析实体的具体内容则为图片、声音等二进制
文件。

·76·
第4章 XML 文档类型定义 ·77·

按照逻辑存储来分类,实体可分为内部实体与外部实体两类。内部实体的内容是在文
档内部设定的;而外部实体则是一个外部独立的物理存储对象,如某个外部文件。
按照使用的范围来分类,实体可分为一般实体与参数实体两类。一般实体都用来构成
文档的具体内容,可出现在 XML 文档中,也可出现在 DTD 中;而参数实体只能出现在
DTD 中,不能出现在 XML 文档中。
1. 内部一般实体
内部一般实体就是在文档实体内部定义和使用的实体,其内容通常是一段文本字符。
这种实体要在 DTD 中通过 DTD 语句的定义,可以在 XML 文档中使用,也可在 DTD 中使
用。其定义的语法格式如下:
<!ENTITY Eentity_name "Replacement" >

其中,<!ENTITY>为关键字,Eentity_name 为实体名称,Replacement 为实体所代替的


文本内容。引用内部一般实体的方法如下:
&Eentity_name;

【例 4.13】 内部一般实体的使用,代码如源程序 code4_13.xml 所示。


<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE bookinfo [
<!ELEMENT bookinfo (title, author, publish, price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT publish (publisher, ISBN, pubdate)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT ISBN (#PCDATA)>
<!ELEMENT pubdate (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ENTITY thepublisher "高等教育出版社">
]>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher> &thepublisher; </publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>

其显示结果与 4.2 节的图 4.2 相同。


当内部一般实体在 DTD 中引用时,有以下几方面需注意。
(1) 不能在元素及属性的声明中引用内部一般实体,如下面的语句即为非法的:
<!ENTITY pcd (#PCDATA)>
<!ELEMENT title &pcd;>

·77·
·78· XML 实用教程

(2) 在语句中不能出现循环,如下面的语句即为非法的:
<!ENTITY thepub "北大&pub;">
<!ENTITY pub "出版社&thepub;">

2. 外部一般实体
所谓外部一般实体就是在文档实体以外定义的,要通过一个 URL 才能引用到的实体。
外部一般实体为独立的文件,可被多个文档所引用。正因为每一个完整的 XML 文档都是
一个合法的实体,所以 XML 通过对外部一般实体的引用,可以在一个 XML 文档中嵌入另
一个 XML 文档,或者将多个文档组合成一个文档。其定义的语法格式如下:
<!ENTITY Eentity_name "URL" >

其中,URL 为引用的外部实体的 URL 地址。引用外部一般实体也与引用内部一般实


体的方法一样:
&Eentity_name;

假如有一个 XML 文档 code4_14out.xml 如下:


<?xml version="1.0" encoding="gb2312" ?>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>

可以通过下面的例子把它作为外部实体来引用。
【例 4.14】 外部一般实体的使用,代码如源程序 code4_14.xml 所示。
<?xml version="1.0" encoding="gb2312" standalone="no"?>
<!DOCTYPE bookinfo [
<!ELEMENT bookinfo (title,author,publish,price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT publish (publisher,ISBN,pubdate)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT ISBN (#PCDATA)>
<!ELEMENT pubdate (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ENTITY pub SYSTEM "code4_14out.xml">
]>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
&pub;
<price>19.7</price>
</bookinfo>

其显示结果仍与 4.2 节的图 4.2 相同。

·78·
第4章 XML 文档类型定义 ·79·

在引用外部一般实体时,有以下几方面需注意。
(1) 因为在一个文档中需引用某些外部文件,所以该文档声明中的 standalone 属性不再
是默认值 yes,而应该为 no。
(2) 作为外部一般实体的文档,若使用的是 XML 的默认字符集即 UTF-8 或 UNICODE,
则可以在文档头部不进行 XML 声明,否则,必须有 XML 声明,且声明时,一定要说明
ecoding 属性。
3. 内部参数实体
内部参数实体是指在独立的外部 DTD 文档的内部定义和使用的实体,其内容为仅能为
DTD 而非 XML 文档内容的书写文本。这里提到参数实体与前面所讲的一般实体是有区
别的:
(1) 在引用形式上,一般实体的引用为“&Eentity_name;”,而参数实体的引用则为
“%Eentity_name;”
(2) 在引用范围上,一般实体可在 XML 文档中引用,也可在 DTD 中引用,而参数实
体只可在 DTD 中引用。
定义内部参数实体的语法格式如下:
<!ENTITY % Eentity_name "Replacement" >

【例 4.15】 内部参数实体的使用,代码如源程序 code4_15.dtd 所示。


<?xml version="1.0" encoding="gb2312" ?>
<!ELEMENT bookinfo (title,author,publish,price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ENTITY % pub "(publisher,ISBN,pubdate)">
<!ELEMENT publish %pub;>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT ISBN (#PCDATA)>
<!ELEMENT pubdate (#PCDATA)>
<!ELEMENT price (#PCDATA)>

4. 外部参数实体
外部参数实体是指在独立的外部 DTD 文档的外部定义和使用的实体,外部参数实体用
于将多个独立的 DTD 文档组合成一个大的 DTD 文档。定义外部参数实体的语法格式如下:
<!ENTITY % Eentity_name "URL" >

【例 4.16】 外部参数实体的使用,代码如源程序 code4_16.xml 所示。


<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE bookinfo SYSTEM "code4_16_1.dtd">
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>

·79·
·80· XML 实用教程

<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>

程序 code4_16_1.dtd 为
<?xml version="1.0" encoding="gb2312"?>
<!ELEMENT bookinfo (title,author,publish,price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ENTITY % pub SYSTEM "code4_16_2.dtd">
%pub;
<!ELEMENT price (#PCDATA)>

程序 code4_16_2.dtd 为
<?xml version="1.0" encoding="gb2312" ?>
<!ELEMENT publish (publisher,ISBN,pubdate)>
<!ELEMENT publisher (#PCDATA)>
<!ELEMENT ISBN (#PCDATA)>
<!ELEMENT pubdate (#PCDATA)>

经过几次引用,显示结果仍然同 4.2 节的图 4.2 相同。

4.5 使用 DTD

前面几节讲述了 DTD 各组成部分的语法格式。本节将讲述如何引用 DTD。引用 DTD


的方法有两种:内部 DTD 引用与外部 DTD 引用。内部 DTD 引用即在 XML 文档中直接设
定 DTD,外部 DTD 引用则是在 XML 文档中引用一个扩展名为.dtd 的独立文件。

4.5.1 内部 DTD

内部 DTD 的定义语句和 XML 文档在同一个文档中,且通常放置在 XML 文档的头部。


在定义内部 DTD 时,定义内部 DTD 的语句要全部放置在文档类型声明中,其语法格式:
<!DOCTYPE Root_Element_Name [

]>

其中,<!DOCTYPE>为关键字,Root_Element_Name 为根元素名,[…]部分则为内部
DTD 定义语句。如例 4.1,即是一个包含内部 DTD 的 XML 文档。

4.5.2 外部 DTD

外部 DTD 就是有关文档定义的语句都被独立出来放在一个外部文件中,对其进行独立
的管理。跟据其内容的性质,可分为两种,一种是私有文件,指未公开的、属于某组织或

·80·
第4章 XML 文档类型定义 ·81·

个人私有的 DTD 文件;另一种是公开文件,是指由国际标准组织如 ISO 等或可发布技术


建议的组织如 W3C 等,为某一领域所制定的公开的标准 DTD。
引用私有 DTD 文件的语法格式:
<!DOCTYPE Root_Element_name SYSTEM "URL">

其中,URL 为外部 DTD 文件的相对路径或绝对路径,该语句必须置于 XML 文档的头


部,且在 XML 文档处理指令中要将 standalone 属性值设定为 no。如例 4.14。
引用公开 DTD 文件的语法格式:
<!DOCTYPE Root_Element_name PUBLIC "Public_Dtd_name" " Public_Dtd_URL">

其中,PUBLIC 为公开 DTD 文件的关键字。Public_Dtd_name 为公开 DTD 文件的文件


名,这个文件名由 4 个部分组成:第一部分为 DTD 的发布者,若是 ISO 发布,则第一部
分为 ISO;若是非 ISO 的标准组织发布,则为“+”;若是非标准组织发布,则为“-”。
第二部分为所有者的名字。第三部分为表明这个 DTD 文件的主要内容或类别的简要文本。
第四部分为所使用的语言,该语言标志必须是 ISO639 所定义过的标准标志。这 4 部分之间
用“//”隔开。Public_Dtd_URL 为公开 DTD 文件的相对路径或绝对路径。

4.5.3 混合 DTD

所谓混合 DTD,即为内部 DTD 与外部 DTD 混合使用。在 DTD 使用的实际情况中, 很


少使用完全标准的 DTD,往往是公司先为所有的开发小组提供一分公共的 DTD 作为外部
DTD,然后各个成员在实际的使用过程中再进行扩展定义,这时的扩展定义常常是使用内
部 DTD 来实现的。
【例 4.17】 混合 DTD 的使用,代码如源程序 code4_17.xml 所示。
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE bookinfo SYSTEM "code4_16_2.dtd"[
<!ELEMENT bookinfo (title,author,publish,price)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT author (#PCDATA)>
<!ELEMENT price (#PCDATA)>
]>
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>

·81·
·82· XML 实用教程

4.6 综 合 实 例

现在对 XML 文档及 DTD 有了一定的认识,下面将使用本章所学知识设计一个图书信


息管理系统的 XML 文档,使其具有严格的标记语言。首先要做出图书信息管理系统的标
记结构图,如图 4.7 所示。

books

author book publisher

a_name sex email b_namem price p_name address

图 4.7 图书信息管理系统的标记结构图

再根据以上标记结构图进行设计,设计过程如下:
(1) 分别设计作者、书籍、出版社信息的 DTD 语句;
(2) 使用外部实体的方式设计系统的 DTD 文档;
(3) 根据设计好的 DTD 文档,编写 XML 文档;
(4) 生成完整的 XML 文档。

4.6.1 DTD 片段

【例 4.18】 图书信息管理系统。
(1) 程序 code4_18_1.dtd,与作者相对应的 DTD 片段。
<?xml version="1.0" encoding="gb2312" ?>
<!ELEMENT authors (author*)>
<!ELEMENT author (a_name,sex,email*)>
<!ATTLIST author id ID #REQUIRED>
<!ATTLIST author ISBN IDREFS #REQUIRED>
<!ELEMENT a_name (#PCDATA)>
<!ELEMENT sex (#PCDATA)>
<!ELEMENT email (#PCDATA)>

作者信息中 authors 根元素下有 author 子元素,author 子元素又包含了 a_name、sex、


email 这 3 个子元素,其中 email 子元素可有可无,也可有数个。author 子元素有两个属性,
分别为作者的 ID 和作者所编书籍的 ISBN,且这两个属性的属性值必须指定。
(2) 程序 code4_18_2.dtd,与书籍相对应的 DTD 片段。

·82·
第4章 XML 文档类型定义 ·83·

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


<!ELEMENT books (book*)>
<!ELEMENT book (b_name,price)>
<!ATTLIST book ISBN ID #REQUIRED>
<!ELEMENT b_name (#PCDATA)>
<!ELEMENT price (#PCDATA)>

书籍信息中 books 根元素下有 book 子元素,book 子元素又包含了 b_name、price 两个


子元素。book 子元素有一个属性,即书籍的 ISBN,且这个属性的属性值必须指定。
(3) 程序 code4_18_3.dtd,与出版社相对应的 DTD 片段。
<?xml version="1.0" encoding="gb2312" ?>
<!ELEMENT publishers (publisher*)>
<!ELEMENT publisher (p_name,address)>
<!ATTLIST publisher ISBN IDREFS #REQUIRED>
<!ELEMENT p_name (#PCDATA)>
<!ELEMENT address (#PCDATA)>

作者信息中 publishers 根元素下有 publisher 子元素,publisher 子元素又包含了 p_name、


address 两个子元素。publisher 子元素有一个属性,即其出版社所印书籍的 ISBN,且这个
属性的属性值必须指定。

4.6.2 系统 DTD 文档

程序 code4_18.dtd,XML 文档直接引用的 DTD。


<?xml version="1.0" encoding="gb2312" ?>
<!ELEMENT volume (authors|books|publishers)*>
<!ENTITY % author SYSTEM "code4_4.dtd">
%author;
<!ENTITY % book SYSTEM "code4_5.dtd">
%book;
<!ENTITY % publisher SYSTEM "code4_6.dtd">
%publisher;

在 XML 文档直接引用的 DTD 中,用到外部参数实体,从而将作者、书籍、出版社相


对应的 DTD 片段与 XML 文档直接引用的 DTD 组成一个整体,以便 XML 主文档的引用。

4.6.3 XML 文档片段

程序 code4_18_1.xml,作者信息 XML 文档片段。


<?xml version="1.0" encoding="gb2312" ?>
<authors>
<author id="a0001" ISBN="ISBN7-04-014768-8">
<a_name>丁跃潮</a_name>
<sex>男</sex>
<email> ding@jmu.edu.cn</email>
</author>

·83·
·84· XML 实用教程

<author id="a0002" ISBN="ISBN7-113-05892-2">


<a_name>龚涛</a_name>
<sex>男</sex>
</author>
</authors>

程序 code4_18_2.xml,书籍信息 XML 文档片段。


<?xml version="1.0" encoding="gb2312" ?>
<books>
<book ISBN="ISBN7-04-014768-8">
<b_name>计算机导论</b_name>
<price>19.7</price>
</book>
<book ISBN="ISBN7-113-05892-2">
<b_name>PowerBuilder 入门教程</b_name>
<price>48.0</price>
</book>
</books>

程序 code4_18_3.xml,出版社信息 XML 文档片段。


<?xml version="1.0" encoding="gb2312" ?>
<publishers>
<publisher ISBN="ISBN7-04-014768-8">
<p_name>高等教育出版社</p_name>
<address>北京市东城区沙滩后街 55 号</address>
</publisher>
<publisher ISBN="ISBN7-113-05892-2">
<p_name>中国铁道出版社</p_name>
<address>北京市宣武区右安门西街 8 号</address>
</publisher>
</publishers>

4.6.4 生成完整的 XML 文档

程序 code4_18.xml,XML 主文档。
<?xml version="1.0" encoding="gb2312" ?>
<!DOCTYPE volume SYSTEM "code4_18.dtd"[
<!ENTITY authors SYSTEM "code4_18_1.xml">
<!ENTITY books SYSTEM "code4_18_2.xml">
<!ENTITY publishers SYSTEM "code4_18_3.xml">
]>
<volume>
&authors;
&books;
&publishers;
</volume>

在 XML 主文档中运用了外部一般实体,将作者、书籍、出版社信息的 XML 文档片段

·84·
第4章 XML 文档类型定义 ·85·

与主文档联系起来,并将主文档与系统 DTD 文件关联在一起,以组成一个结构完整的 XML


文档。运行程序 code4_18.xml,最终显示结果如图 4.8 所示。

图 4.8 图书信息 XML 文档运行显示结果

4.7 小 结

DTD 文档是 XML 文档的法律性文件,它定义了文档的逻辑结构,规定了文档中所使


用的元素、实体、元素的属性、元素与实体之间的关系。
DTD 中描述的基本部件是元素和属性,它们负责确定 XML 文档的逻辑结构。元素表
示一个信息对象,而属性表示这个对象的性质。实体是包含了文档片段的虚拟存储单元,
可用来存储 XML 声明、DTD、其他形式的文本及二进制数据等。
引用 DTD 的方法有两种:内部 DTD 引用与外部 DTD 引用。

·85·
·86· XML 实用教程

4.8 习 题

1. DTD 的作用表现在哪几个方面?
2. DTD 中的元素可分为哪两类,有何区别?
3. DTD 中的属性有几种不同类型的默认值,各种默认值之间有何区别?
4. 实体按其逻辑存储及使用范围,可分为哪几种类型?
5. 在引用内部一般实体时,要注意哪些问题?
6. 如图 4.9 所示,为其系统设计标记语言。

博物馆

油画 雕塑 古币
作者

作者

质量

币值
成画时间

使用年代

图 4.9 标记结构图

·86·
第 5 章 XML Schema 结构

教学提示:XML Schema 是 DTD 之后第二代用来描述 XML 文件的标准。是用来对 XML


文档的类型定义的语言,用来规定 XML 文档的数据类型及组织方式,同时还是丰富的元
数据资源。XML Schema 是一种定义文件的方式,拥有许多类似 DTD 的准则,但又要比
DTD 更为强大一些。W3C 协会宣称,与 DTD 相比 XML Schema 拥有许多优势。
教学目标:理解 XML Schema 的含义及用途,了解 XML Schema 如何为 XML 文档和
结构、内容和数据类型建模并提供严格而完整的标准,了解 XML Schema 的元素、属性和
类型等构件,理解 XML Schema 的名称空间的概念。

5.1 Schema 概述

XML Schema 是 2001 年 5 月正式发布的 W3C 的推荐标准,经过数年的大规模讨论和


开发如今终于尘埃落定,成为全球公认的 XML 环境下首选的数据建模工具。
使用 DTD 虽然带来较大的方便,但是,DTD 存在一些缺陷:一是它用不同于 XML
的语言编写,需要不同的分析器技术。这增加了工具开发商的负担,降低了软件瘦身的可
能性,此外开发人员需要多学一门语言及其语法。而 XML Schema 是按标准 XML 规则编
写的,更容易掌握。二是 DTD 不支持名称空间。随着大部分的数据处理日益以 XML 为中
心,信息的相互联系变得日益普及与深入,名称空间作用也将凸现。三是 DTD 在支持继承
和子类方面的局限性。由于面向对象技术的出现,对继承和子类的支持已成为软件技术领
域的主流概念。最后,DTD 没有数据类型的概念,无法对特定元素施加数据类型,对强制
性结构化无计可施,例如,如何规定名为 Date 的数据必须包含有效值。
这些就要依靠 XML Schema 了。XML Schema 不仅可以定义 XML 文档的结构而且还
允许约束文档的内容,这不同于 DTD。另外,一个 XML Schema 自身就是一个 XML 文档,
其基于标签的语法比 DTD 中的特殊字符要清楚多了。XML Schema 正是针对这些 DTD 的
缺点而设计的,它完全使用 XML 作为描述手段,具有很强的描述能力、扩展能力和处理
维护能力。
XML Schema 是用一套预先规定的 XML 元素和属性创建的,这些元素和属性定义了文
档的结构和内容模式。
XML Schema 也是 Web Services 技术中需要使用的一个基本工具,然而并不是 XML
Schema 的所有特性都会被广泛地使用,因此,本书将不对 XML Schema 规范做系统的介绍。
目前主要有两种重要的模式:Microsoft XML Schema 和 W3C XML Schema,本章主要讨论
W3C XML Schema。
·88· XML 实用教程

在 下 面 的 例 子 中 , 通 过 使 用 出 现 在 Schema 元 素 中 的 名 称 空 间 声 明 xmlns:xsd=
“http://www.w3.org/2001/XMLSchema”,使得模式文档中的每一个元素都有一个与 XML
Schema 名称空间相关联的名称空间前缀 xsd。尽管在语法上,可以使用任意的前缀形式,
但是,名称空间前缀 xsd 被约定用于表示 XML Schema 名称空间。由于使用同样的前缀,
所以同样的关联就会出现在内置的简单类型的名字中,例如 xsd:string。这种形式关联的目
的是用来表示当前的元素或简单类型属于 XML Schema 语言的内置定义,而不属于模式文
档作者自己的词汇表。为了在这里清楚并且简单地表示,仅提及元素的名字和简单类型名,
而忽略它们的前缀 xsd。

5.2 Schema 的格式和使用

一个 XSDL(XML Schema Definition Language)文档由元素、属性、名称空间和 XML 文


档中的其他结点构成,并且至少要包含:schema 根元素、XML 模式名称空间的定义和元
素定义。

5.2.1 简单实例

【例 5.1】 关于书籍信息的 XML 文档,代码如源程序 code5_1.xml 所示。


<?xml version="1.0" encoding="gb2312"?>
<book isbn="0-764-58007-8">
<title>三国演义</title>
<author>罗贯中</author>
<price>80.00 </price>
<resume>滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白
发渔樵江渚上,惯看秋月春风。一壶浊酒喜相逢。古今多少事,都付笑谈中。
</resume>
<recommendation>经典好书</recommendation>
<publish>
<publisher>文艺出版社</publisher>
<pubdate>1998.10</pubdate>
</publish>
</book>

如何写这个 XML 文档的 Schema 呢?可以简单地依照它的结构来定义它的每个元素。


首先加入一个 xsd:schema 元素。
<?xml version="1.0" encoding=" gb2312"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">

每个 Schema 文档都是从 schema 元素开始,并且只能有一个,用以控制 Schema 所使


用的名称空间和另外几个选项,现在的 Schema 标准有好几种,这里决定它所采用的标准,
因此是非常重要的。
对应着 XML 文档的 book 元素,同样也定义一个名为 book 的元素(element)。因为这个
元素有属性(attributes)和非文本的子元素(non-text children),所以认为它是一个复杂类型

·88·
第5章 XML Schema 结构 ·89·

(complexType)。而对于简单类型,只能有值,不能有子元素或者属性。同时还注意到 book
元素下的子元素,都按照一定的顺序排列,因此使用顺序元素(sequence element)来描述。
<xsd:element name="book">
<xsd:complexType>
<xsd:sequence>

顺序元素(sequence element)是一个定义子元素排列顺序的元素,在下面的章节,还将
介绍其他类似的元素,如选择(choice)和全选(all)。
接着定义 title 和 author,都是 xsd:string 类型的简单元素,因为没有属性(attributes)或
者子元素。xsd:string 是一个已经在名域中预定义了的 XML Schema 类型中的一个。
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="price" type="xsd:integer" />
<xsd:element name="resume" type="xsd:string" />
<xsd:element name="recommendation" type="xs:string" />

接着,来处理 publish 元素,它也是一个复杂类型,注意它的基数的定义。


<xsd:element name="publish" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>

同其他 Schema 定义语言不一样,W3C XML Schema 允许定义一个元素的使用基数,


能指定元素的 minOccurs(最小数)和 maxOccurs(最大数)。这里设置 maxOccurs 为 unbounded,
这意味着能有任意多的 publish 元素。这两个属性的默认值都是 1。下面,用同样的方法定
义其他的子元素。
<xsd:element name="publisher" type="xsd:string" />
<xsd:element name="pubdate" type="xsd:date" />

下面封闭 complexType 和 element 等元素。


</xsd:sequence>
</xsd:complexType>
</xsd:element>

这样 publish 元素就完成了,然后封闭 book 的 sequence 元素。


</xsd:sequence>

现在,声明 book 元素的属性,通常是在最后这么做。这样做没有什么特别的原因,只


不过 W3C XML Schema 工作组认为在元素后定义属性感觉更加自然。
<xsd:attribute name="isbn" type="xsd:string"/>

最后,封闭所有剩下的元素。
</xsd:complexType>
</xsd:element>
</xsd:schema>

至此,一个 Schema 已经完成了。其中,最关键的在于根据文档的上下关系来定义每一个

·89·
·90· XML 实用教程

元素和属性,并且允许有多个同名元素带有不同的内容。为了这个目的,W3C XML Schema


被设计成一种有作用域的语言,它的每一个定义只能被它定义的子元素所看见。
【例 5.2】 关于书籍信息模式定义的完整例子,代码如源程序 code5_2.xsd 所示。
<?xml version="1.0" encoding=gb2312" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="book">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="title" type="xs:string" />
<xsd:element name="author" type="xs:string"/>
<xsd:element name="price" type="xs:integer" />
<xsd:element name="resume" type="xs:string" />
<xsd:element name="recommendation" type="xs:string" />
<xsd:element name="publish" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="publisher" type="xs:string" />
<xsd:element name="pubdate" type="xs:date" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="isbn" type="xs:string" />
</xsd:complexType>
</xsd:element>
</xsd:schema>

5.2.2 Schema 的使用

符合某个模式的文档称为实例。实例可以根据特定的模式进行验证。需要声明 XML
文档的 Schema 实例名称空间(xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”),
并把名称空间映射到前缀 xsi。实例与模式之间有多对多的关系。一个模式可以描述多个有
效的实例(通过使用不同的根元素类型来实现),同样,一个实例也可以被多个模式描述。
例如一个实例可能拥有多个模式,它们有不同的验证级别。其中一个模式可能只验证结构,
而另一个模式则根据数据类型来检查每一个数据项。
1. Schema 的作用
Schema 文档用来验证 XML 文档的正确性,用来判断实例是否符合模式中所描述的所
有约束,涉及到检查实例中所有的元素和属性。
Schema 主要检验如下内容:
(1) 验证数据的显示格式是否正确及是否超出值的范围;
(2) 验证所有必需的信息都存在;
(3) 确保不同使用者对文档理解的方式相同。
除了对 XML 文档的验证外,Schema 文档还在一定程度上扩充实例:
(1) 为元素和属性添加默认值和固定值;
(2) 使具有简单类型的元素和属性值中的空白符规范化。

·90·
第5章 XML Schema 结构 ·91·

2. Schema 的引用
一个模式可能由多个模式文档构成。多个模式文档通过包含或导入机制来形成模式,
当其他模式文档与主模式文档具有相同的目标名称空间时,需要使用包含;当模式文档之
间各自拥有不同的目标名称空间时,需要使用导入。下面的例子建立一个单独用来验证实
例的模式文档。
【例 5.3】 关于多个模式文档通过包含实现定义的例子,代码如源程序 code5_3.xsd 所示。
<?xml version="1.0" encoding="gb2312" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://example.org/ord"
targetNamespace="http://example.org/ord">
<xsd:include schemaLocation="moreBookInfo.xsd"/>
<xsd:import namespace="http://example.org/ord"
schemaLocation="publish.xsd" />
<!--…-->
</xsd:schema>

要验证 XML 文档,必须指定 Schema 文档的位置。模式的位置可以利用带有名称空间模


式的 xsi:schemaLocation 属性以及不带名称空间 XML 模式的 xsi:noNamespace SchemaLocation
属性来指定,它们位于根/顶级元素中或 XML 文档的任何其他元素中。
当 Schema 文档不包括 targetNamespace 属性时,
应当通过 XML 文档根元素的 noNamespace
SchemaLocation 属性及 W3C 的 Schema 实例名称空间(xmlns:xsi=“http://www.w3.org /2001/XML
Scheam-instance”)来引用 XML Schema 文件。针对上面的实例修改如下:
<?xml version="1.0" encoding="gb2312" ?>
<book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="books.xsd"
isbn="0-764-58007-8">
<!--…-->
</book>

然而,如果 Schema 文档包含了一个 targetNamespace 属性,在 XML 文档中就将通过


schemaLocation 属性而不是 noNamespaceSchemaLocation 属性来引用 Schema 文档。而且,
这个属性所指定的值必须是完整的。它需要包含以空格分开的两部分,前一部分是 URI,
这个 URI 与 Schema 文档的 targetNamespace 属性内部引用的 URI 是一致的;后一部分是
Schema 文件的完整路径及名称。另外,XML 文档的根元素也必须声明 Schema 实例名称空
间(xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”)。Schema 文档如下所示:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://tempuri.org/book">
<!--…-->
</xsd:schema>

则修改上面的实例为
<?xml version="1.0" encoding="gb2312" ?>
<book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tempuri.org/book book.xsd"

·91·
·92· XML 实用教程

xmlns="http://tempuri.org/book"
isbn="0-764-58007-8">
<!--…-->
</book>

5.3 Schema 元素的声明

元素是创建 XML 文档的主要构建材料。在 W3C XML Schema 中,元素通过使用 element


元素实现。元素声明用于给元素指定元素类型名称、内容和数据类型等属性。在 XSDL 中,
元素声明可以是全局的,也可以是局部的。

5.3.1 schema 根元素

在 schema 文档中必须定义一个且只能定义一个 schema 根元素。根元素不但表明了文


档类型,而且还包括模式的约束、XML 模式名称空间的定义,其他名称空间的定义、版本
信息、语言信息和其他一些属性。定义如下:
<?xml version="1.0" encoding="gb2312" ?>
<xsd: schema name="mySchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

</xsd: schema>

其中 name 属性指定 Schema 名称,也可以不需要。xmlns 指定所属名称空间,紧跟在


后面的 xsd 则是该名称空间的名称,名称空间 http://www.w3.org/2001/XMLSchema 被映射
到 xsd 前缀,在后面将详细说明名称空间。

5.3.2 element 元素

XSD 中的元素是利用 element 来声明的。其中 name 属性是元素的名字,type 属性是元


素值的类型,在这里可以是 XML Schema 中内置的数据类型或其他类型。具体定义格式
如下:
<xsd:element name=“author” type=“xsd:string” />

其中,name 是元素类型的名称,必须是以字母或下划线开头,而且只能够包含字母、
数字、下划线、连接符及句号。type 属性是必要的,说明元素的数据类型。
下面的例子定义全局元素声明 author,为简单字符串类型。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="author" type="xsd:string"/>
</xsd:schema>

与以上文档对应的有效 XML 文档如下:


<?xml version="1.0"encoding="gb2312"?>
<author>罗贯中</author>

·92·
第5章 XML Schema 结构 ·93·

在元素的定义中还有两个属性:minOccurs 和 maxOccurs。其中 minOccurs 定义了该元


素在父元素中出现的最少次数(默认为 1,值为大于等于 0 的整数),maxOccurs 定义了该元
素在父元素中出现的最多次数(默认为 1,值为大于等于 0 的整数)。在 maxOccurs 中可以把
值设置为 unbounded,表示对元素出现的最多次数没有限制。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="author" type="xsd:string"minOccurs="0"
maxOccurs="unbounded"/>
</xsd:schema>

表示元素 author 的类型为 string,出现的次数最少为 0(就是可选),最多不限制。


一般来说,如果元素声明出现在 Schema 文档的顶级结构中,也就是说,它的父元素
是 schema,那么这些元素为全局元素。
相反,局部元素声明只出现在复杂类型定义的内部,局部元素声明只在该类型定义中
使用,而不被其他复杂类型引用或在替换组中使用。不同的复杂类型,可以有相同元素类
型名称的局部元素。
【例 5.4】 显示 title、author 和 price 三种局部元素声明的模式文档,代码如源程序 code5_4.xsd
所示。
<?xml version="1.0" encoding="gb2312"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
<xsd:complexType name="book">
<xsd:sequence>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="xsd:string" minOccurs="0"
maxOccurs="unbounded"/>
<xsd:element name="price" type="xsd:integer"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

5.3.3 设置默认值和固定值

默认值和固定值通过给空元素增加值的方式来扩展实例。如果文档中存在空的元素,
模式处理器根据模式文档的定义,会插入默认值或固定值。在 XSDL 中,默认值和固定值
分别通过 default 和 fixed 属性设置。两个属性只能出现其中之一,因为它们是互斥的。
如果元素为空,就填入默认值。下例中,声明了 city 元素,并指定了默认值为“佚名”。
<xsd:element name="author" type="xsd:string" default="佚名"/>

必须注意的是,元素声明中“空”的定义根据数据类型不同而有所不同。某些数据类
型允许空值,包括 string 等。任何允许空字符串值的类型,元素都不会认为是空的,从而
对于字符串类型元素,默认值不会被填充。相反,integer 数据类型的空元素通常会被认为
是空的,从而将填入默认值。此外,如果元素的 xsi:nil 属性被设置为 true,那么就不会插
入它的默认值。
<?xml version="1.0" encoding="gb2312"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2000/10/XMLSchema">
<xsd:element name="title" type="xsd:string"/>

·93·
·94· XML 实用教程

<xsd:element name="author" type="xsd:string" default="N/A" />


<xsd:element name="price" type="xsd:integer" default="30" />
</xsd:schema>

元素的默认值行为见表 5-1。

表 5-1 元素的默认值行为

情 况 填充实例结果 填充之前 填充之后


指定值 保持原始值 <author>罗贯中</author> <author>罗贯中</author>
空元素(integer) 填充值 <price></price> <price>30</price>
空元素(string) 没有填充值 <author></author> <author></author>
元素为空 没有填充值 <price xsi:nil="true"/> <price xsi:nil="true"/>

固定值与默认值在相同的情况下添加,它们的差别仅在于如果元素拥有一个值,则该
值必须和固定值相等。当模式解析器确定元素值和固定值实际上是否相等时,会考虑到元
素的数据类型。price 元素的数据类型为 integer,所以整数 1 的所有形式在实例中都会被接
受,包括 01、+1 和周围包含空白符的 1。相反,对于 author 元素具有数据类型为 string,
字符串“01”是无效的,因为与字符串“1”并不相等。
<xsd:element name="author" type="xsd:string" fixed="1"/>
<xsd:element name="price" type="xsd:integer" fixed="1"/>

按照以上定义,元素的固定值行为见表 5-2。

表 5-2 元素的固定值行为

有效实例 无效实例

<price>1</price> <price>2</price>
<price>01</price> <author>01</author>
<price>+1</price> <author>+1</author>
<price></price> <author></author>
<price /> <author> </author>
<author>1</author> <author />

5.3.4 引用元素和替代

引用是利用 element 元素的 ref 属性实现的。主要适用于避免在文档中多次定义同一个


元素,应当将经常使用的元素定义为根元素的子元素,即为全局元素,这样方便在文档的
任何地方引用它。如每本书籍都有作者,其他产品也会有作者,因此可以把 author 属性声
明为全局元素,供文档中多处引用。
【例 5.5】 引用元素定义的模式文档,代码如源程序 code5_5.xsd 所示。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="author" type="xsd:string"/>

·94·
第5章 XML Schema 结构 ·95·

<xsd:element name="book">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="author" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

在这里还可以为某个定义的元素起一个别名,
主要是利用 element 元素中的 substitutionGroup
属性实现的。
方法如下:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="writer" type=xsd:string"
substitutionGroup="author" />
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="book">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="author" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

以上文档对应的有效 XML 文档如下:


<?xml version="1.0"?>
<book>
<author>罗贯中</author>
</book>

或者:
<?xml version="1.0"?>
<book>
<writer>string</writer>
</book>

5.4 Schema 的属性声明

属性声明用于命名属性并使之与某个特定的简单类型相关联。在 XSDL 中,实现的方


法是使用 attribute 元素。在 XML Schema 文档中可以按照定义元素的方法定义属性,但受
限制的程度较高。它们只能是简单类型,只能包含文本,且没有子属性。属性是没有顺序
的,而元素是有顺序的。
使用属性十分简练,元素的功能比属性强大,但在某些场合属性是非常有用的。通常,
对于元数据使用属性,而对于数据则使用元素。如用属性描述单位、语言或元素值的时间
相依性。

·95·
·96· XML 实用教程

5.4.1 创建属性

定义属性的方法如下:
<xsd:attribute name="isbn" type="xsd:string"/>

该语句定义了一个名为 isbn 的属性,它的值必须是一个字符类型。


属性也分全局和局部属性。全局声明的属性是 schema 元素的子元素,在模式文档中必
须是唯一的。复杂类型的元素,使用 ref 属性通过名称来引用属性。局部属性声明只出现在
复杂类型定义中,它们仅能在类型定义中使用,而不能被其他类型重用。下面的例子显示
了两个属性——isbn 和 amount 的全局声明,然后定义了一个复杂类型,使用 ref 属性通过
名称来引用这两个属性。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:attribute name="isbn" type="xsd:string"/>
<xsd:attribute name="amount" type="xsd:integer"/>
<xsd:complexType name="book">
<xsd:attribute ref="isbn" use="required"/>
<xsd:attribute ref="amount">
</xsd:complexType>
</xsd:schema>

其中,use 属性用于指示属性是必需的还是可选的,它出现在属性引用而不是属性声明
中,因为它关系到属性在复杂类型中的出现,而不是属性本身。上面的例子定义的是全局
的属性定义方式,如果要在复杂类型里声明属性,可以参照下面的例子:
<xml ID="xmldata" SRC="code7_1.xml"></xml>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="book">
<xsd:attribute name="isbn" type="xsd:string" use="required"/>
<xsd:attribute name="amount" type="xsd:integer"/>
</xsd:complexType>
</xsd:schema>rbut
上面的例子描述了 isbn 和 amount 两个属性的局部声明,它们完全出现在复杂类型的
定义中。局部声明的属性名称,作用范围仅限于复杂类型内,在同一个复杂类型定义中,
两个属性使用相同的限定名称是非法的。只有当属性会被多个名称空间的多个元素声明使
用到时,才提倡将该属性声明为全局属性。

5.4.2 为属性指派类型

所有的属性声明都把属性指定为某种简单类型。所有的属性都具有简单类型而不是复
杂类型,因为它们本身不能有子元素和属性。
属性声明有 3 种方式:
(1) 在属性声明中通过用 type 属性指定命名简单类型。它可以是内置类型,也可以是
用户自定义类型。
(2) 通过指定 simpleType 子属性来指定匿名类型。
(3) 既没有 type 属性,又没有 simpleType 子属性,从而不指定特定类型。在这种情况

·96·
第5章 XML Schema 结构 ·97·

下,属性的类型为 anySimpleType,它可以拥有任何值,只有它是结构合理的 XML 文档。


下例显示 4 个属性的声明,采用了不同的类型指定方法。定义了grade 属性并赋予
gradeType 类型,amount 属性指定了内置类型 integer,同时使用内嵌的匿名简单类型来声
明 bookcategory 属性,anything 属性没有指定特定的类型。
<xsd:attribute name="amount" type="xsd:integer"/>
<xsd:attribute name="grade" type="gradeType"/>
<xsd:attribute name="bookcategory">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="文艺"/>
<xsd:restriction>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="anything"/>

5.4.3 属性的默认值和固定值

对于属性来说,也可以通过默认值和固定值的方式增加未出现的属性来扩充实例。定
义和扩充的方式与元素一致。在 XSDL 中,默认值和固定值分别通过 default 和 fixed 属性
设置。两个属性只能出现其中之一,因为它们是互斥的。
如果属性在元素中默认,它的默认值将会被填入。如果属性出现,且包含任意值,它
将保持该值不变。下面的例子显示了 book 元素的声明,它包含一个 amount 属性,该属性
被指定了默认值。
<xsd:element name="book">
<xsd:complexType>
<xsd:attribute name="amount" type="xsd:integer" default="100"/>
</xsd:complexType>
</xsd:element>

固定值与默认值在基本一样的情况下被插入,区别在于,其值应和固定值相等。同时
也会考虑属性的类型。
<xsd:element name="book">
<xsd:complexType>
<xsd:attribute name="isbn" type="xsd:string" fixed="100"/>
<xsd:attribute name="amount" type="xsd:integer" fixed="100"/>
</xsd:complexType>
</xsd:element>

·97·
·98· XML 实用教程

5.5 Schema 的数据类型

W3C XML Schema 可以把 XML 文档中的元素声明为特定的类型,准许解析器检查文


档的内容及其结构。XML Schema 定义了两种主要的数据类型:预定义简单类型和复杂类
型。这两种数据类型之间的主要区别是复杂类型可以像数据一样包含其他元素而简单类型
则只能包含数据。简单类型给予了 XML Schema 低级类型检查能力。

5.5.1 简单类型

元素和属性声明都可以使用简单类型来描述数据类型。

1. 简单类型的种类

原子类型(不可分割的类型,如 string、integer 等系统内建的类型)、列表类型、联合类


型合起来统一称为简单类型。XML Schema 具有低级类型检查能力,允许把元素定义为
表 5-3 中的任何类型之一。赋予简单类型的元素具有字符类型内容,但没有子元素或属性。
(1) 原子类型具有不可分割的值,如 10 和 large。
(2) 列表类型的值为用空格符隔开的原子值列表,如<availableSizes>10 large 2</available
Sizes>
(3) 联合类型的值可以是原子值,也可以是列表值。它们的区别在于该类型的有效值
集是两个或多个其他简单类型值空间的联合。如要对学生的成绩评定等级,可以定义一个
联合类型,它允许的值既可以是 0~100 的整数,也可以是优、良、合格或不合格。

表 5-3 XML Schema 支持的部分简单类型

内建类型 定 义

string 字符串数据,如"online book shop"

boolean 二元类型的 true 或者 false

date 表示日期,格式是 ccyy-mm-dd

dateTime 表示当前时间,由日期和时间组成,如 11/18/80,10:00am

time 24 小时格式的时间可根据时区调节

decimal 任意精度和位数的十进制数,如 27.93

integer 整数,如 34

float 标准的 32 位浮点数,如 11.87e-2

在前面一些例子中,有几个元素和属性被声明为简单类型。其中一些简单类型如 string
和 integer 是 XML Schema 中内置的类型,其他的一些则是源于(如果使用对象技术的语言
就是继承)内置的类型。

·98·
第5章 XML Schema 结构 ·99·

除此之外,新的简单类型可以通过从现有的简单类型(内置的简单类型以及源于内置简
单类型的简单类型)引出定义。通常,通过重新约束一个现有的简单类型来引出一个新的简
单类型。换句话说,新类型的合法值范围是现有类型的值范围的子集。使用 simpleType 元
素来定义和命名新的简单类型,使用 restriction 元素来指出现有的基类型,并且用它来标识
约束值范围的细节。
假设希望建立一个新的整数类型称为 myInteger,它的值范围为 10000~99999。那么定义
应当基于简单类型 integer,然后定义它的值范围为 10000~99999。为了定义 myInteger,这
样来约束 integer 的范围,示例如下:
<xsd:simpleType name="myInteger">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="10000"/>
<xsd:maxInclusive value="99999"/>
</xsd:restriction>
</xsd:simpleType>

这个例子显示了由一个基本类型定义和两个值域区间方面描述的组合,通过这 3 个要
素对 myInteger 实施定义。
2. 简单类型的命名定义
简单类型既可以为命名简单类型又可以为匿名简单类型。命名简单类型总是在全局定
义的,而且要求在模式的数据类型中具有唯一名称。类型的名称必须为 XML 无冒号名称,
即必须以字母或下划线开始,只能包含字、数字母、下划线、连字符和句点。如上面的例
子,简单类型名为 myInteger。
这种类型的模式构造非常直截了当,但有些不实用。特别是如果定义了许多只应用一
次而且包含非常少约束的类型,在这种情况下,一个类型应该能够被更简单的定义。这样
的简单定义通常的形式是一个省略了名称和外部引用开销的匿名类型。
在下面的示例中,publish 元素声明使用了匿名类型定义。一般来说,通过元素中是否
包含“type=”这个属性可以判断匿名属性定义(或者是匿名元素定义)。如果出现无名称的
类型定义,也可以认为是匿名属性(元素)定义。
<xsd:element name="publish">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="40"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:element>

3. 简单类型的限制
每个简单类型都是从另一个简单类型派生而来的,则另一个简单类型称为基类型。可
以从原子类型,也可以从用户定义的简单类型派生。上面的例子都从内置的原子类型派生
成新的简单类型。所有新的简单类型都以某种方式限制其基类型的值空间。下面的例子从
简单类型种类例子中定义的 myInteger 类型进一步限制。

·99·
·100· XML 实用教程

<xsd:simpleType name="bookInteger">
<xsd:restriction base="xsd:myInteger">
<xsd:minInclusive value="23"/>
<xsd:maxInclusive value="2046"/>
</xsd:restriction>
</xsd:simpleType>

简单类型定义时,都是通过 restriction 元素来定义限制,通过 base 属性来规定一种基


类型。在 restriction 内,可以任何顺序指定任何面(facet),来对类型取值进一步限制。根据
面的不同,这个元素或属性具有不同的有效值。XML Schema 面的定义见表 5-4。
表 5-4 XML Schema 面的定义

面 意 义

minExclusive 值必须大于 x,相对就有 maxExclusive

minInclusive 值必须大于等于 x,相对就有 maxInclusive

length 值的长度必须等于 x

minLength 值的长度必须大于等于 x,相对就有 maxLength

totalDigits 有效数字的位数必须小于等于 x

fractionDigits 小数位数必须小于等于 x

whiteSpace 是否保留、替换或压缩 whitespace,决定于 x

enumeration x 是一个有效值

pattern x 是值可以匹配一个正则表达式

对每个内置的原子类型来说,都有一套定义时可用的面。如果某个面适用于某种原子
类型,那么也适用于由该类型派生的简单类型。这里有必要举例说明枚举的简单类型定义,
下面的例子定义了一个简单类型 category,用于说明书籍的类别。
<xsd:simpleType name="category">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="小说"/>
<xsd: enumeration value="散文"/>
<xsd: enumeration value="传记"/>
<xsd: enumeration value="诗歌"/>
<xsd: enumeration value="武侠"/>
<xsd: enumeration value="纪实"/>
</xsd:restriction>
</xsd:simpleType>

4. 列表类型
除了使用简单类型中描述的原子类型,XML Schema 还定义了其他两种简单类型:列
表类型和联合类型。
列表类型由一组原子类型组成,因此它的每一个部分(原子)本身都是有意义的,定义
时以空格隔开原子值的列表。举例来说 category 是个列表类型。这个类型的元素将是
NMTOKEN 的列表,不同的 NMTOKEN 值使用空格分隔,如“小说 散文 传记”。XML

·100·
第5章 XML Schema 结构 ·101·

Schema 有 3 个内置的列表类型,它们是 NMTOKENS、IDREFS 和 ENTITIES。


除了使用内置的列表类型之外,还可以通过引用现有的原子类型建立新的列表类型(不
可以使用现有的列表类型来建立新的列表类型,也不能使用联合类型来建立新的列表类
型)。举例来说,可以建立一个名为 myInteger 的列表类型,并在实例文档中使用它。其中
示例的后半部分即为实例文档中与列表类型 listOfMyIntType 相一致的实例元素 myInt。
<!-- Schema Fragment -->
<xsd:simpleType name="listOfMyIntType">
<xsd:list itemType="myInteger"/>
</xsd:simpleType>
<xsd:element name="myInt" type="listOfMyIntType"/>

<!-- Instance Fragment -->


<myInt>20003 15037 95977 95945</myInt>

一些用于描述的参数能够被应用到列表类型的定义中,它们是 length、minLength、
maxLength 和 enumeration。举例来说,如果想定义一个列表类型,这个列表类型正好包含
了 6 个分类项名。首先从 category 类型定义一个新的列表类型,称为 cateList,然后通过限
制 cateList 导出只有 3 个项的 threeBookCate 类型。具体的定义如下:
<!-- Schema Fragment -->
<xsd:simpleType name="cateList">
<xsd:list itemType="category"/>
</xsd:simpleType>
<xsd:simpleType name="threeBookCate">
<xsd:restriction base="cateList">
<xsd:length value="3"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:element name="threeBookCategory" type="threeBookCate"/>

<!-- Instance Fragment -->


<threeBookCategory> 小说 散文 传记</threeBookCategory>

其中,类型为 threeBookCate 的元素必须有 3 个项,它们中的每一个项必须是一个枚举


类型 category 的原子类型(枚举类型将在后面的章节中介绍),在示例后半部分的实例文档中
就是一个具体的应用例子。
需要注意的是,从原子类型 string 可以导出一个列表类型,然而,在一个 string 中也许
会带有空格,而空格在一个列表类型实例中是作为分隔符使用的,因此当在使用基类型为
string 的列表类型时,应当格外小心。举例来说,假设定义了一个 length 取值为 3 的列表类
型,同时这个列表类型基于类型 string。下面由 3 个元素这样组成的列表是合法的 Asia Europe
Africa;而由 3 个元素这样组成的列表是不合法的 Asia Europe Latin America。即使 Latin
America 在列表外可以作为单独的一个字符串存在,但当它包含在列表中时,在 Latin 和
America 之间的空格使得第 4 个项被有效地生成了,因此后面的例子不符合只有 3 个项的
列表类型定义。
5. 联合类型
应用原子类型和列表类型,一个元素或者属性的值可以为一个或者多个原子类型(列表

·101·
·102· XML 实用教程

类型)的实例。与之相比较,一个联合类型(Union Type)包含了多个原子类型或者列表类型,
而应用了联合类型的元素或属性,它们的值可以是联合类型中所包含的这些原子类型或列
表类型中的任何一个类型实例。为了说明这一点,建立一个用于表示学生成绩的由评定等
级或者数字列表的联合类型。gradeUnion 联合类型由一个原子类型和一个列表类型构成。
<!-- Schema Fragment -->
<xsd:simpleType name="gradeUnion">
<xsd:union>
<xsd:simpleType name="scoreType">
<xsd:restriction base="xsd:integer">
<xsd:minInclusive value="0"/>
<xsd:maxInclusive value="100"/>
</xsd:restriction>
</xsd:simpleType>
<xsd:simpleType name="gradeType">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="优"/>
<xsd:enumeration value="良"/>
<xsd:enumeration value="及格"/>
<xsd:enumeration value="不及格"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:union>
</xsd:simpleType>

组成联合类型的简单类型称为它的成员类型。成员类型必须是简单类型,不存在复杂类
型的联合。除了直接用简单类型来规定成员类型外,还可以使用 union 元素的 memberTypes
属性来规定成员类型。假定已经在模式文档的其他地方定义了 gradeType 和 scoreType,改
写上面的例子:
<!-- Schema Fragment -->
<xsd:simpleType name="gradeUnion">
<xsd:union memberTypes="scoreType gradeType"/>
</xsd:simpleType>
<xsd:element name="stuScore" type="gradeUnion"/>

<!-- Instance Fragment -->


<stuScore>87</stuScore>
<stuScore>优</stuScore>

当在定义一个联合类型时,union 元素的 memberTypes 属性的值包含了联合类型中所


有类型的列表。现在,假定声明了一个 gradeUnion 类型的元素,称为 stuScore,stuScore
元素有效的实例可参见上面的实例。
此外,对于联合类型而言,还有两个描述性质的参数 pattern 和 enumeration 也可以应
需要使用。

5.5.2 复杂类型

复杂类型的元素拥有子元素和属性,还可以有字符内容。复杂类型和简单类型之间最
根本的区别就是:复杂类型的内容中可以包含其他元素或属性,但简单类型既不能包含子

·102·
第5章 XML Schema 结构 ·103·

元素,也不能带有任何属性。复杂类型有 4 种不同的内容类型:简单类型、纯元素类型、
混合类型及空类型。下例中给出了具有复杂类型的元素:book 是带有属性的元素、bookinfo
是包含子元素的纯元素复杂类型、chapter 是混合类型的复杂类型元素以及内容为空的元素
price。它们分别属于下面要描述的 4 种不同的内容类型。
<?xml version="1.0" encoding="gb2312" ?>
<book isbn="0-764-58007-8">no.1</book>
<bookinfo>
<title>三国演义</title>
<author >罗贯中</author>
</bookinfo>
<chapter >宴桃园豪杰三结义 斩黄巾英雄首立功
<para>话说天下大势,分久必合,合久必分。</para>
</chapter>
<price value="30"/>

复杂类型由 complexType 元素创建,同简单类型一样,复杂类型可以是命名的,也可


以是匿名的。命名的复杂类型可以被多个元素声明使用,一般在全局范围内定义。相反,
匿名的复杂类型完全在元素声明中进行定义,而且只可以被该声明使用一次。有 3 种不同
的方法:
(1) 单个 complexContent 子元素,可以使用它从一个复杂类型派生出新的复杂类型;
(2) 单个 simpleContent 子元素,用于从简单类型派生出复杂类型;
(3) 组(group、all、choice 或 sequence)加属性,用于定义一种非派生于特定类型的复杂
类型。
1. 内容类型
所谓元素的内容是在标记之间的字符数据和子元素。复杂类型子元素的顺序和结构称
为它的“内容模型”。复杂类型的内容类型有 4 种:简单内容、纯元素内容、混合内容和
空内容。内容类型不依赖于属性,所有这些内容类型都允许有属性。
简单内容只允许有字符数据,它没有子元素。一般说来,简单类型和具有简单内容的
复杂类型的唯一区别在于后者可以有属性,如下面的 book 元素。
<book isbn="0-764-58007-8">no.1</book>

要定义如上所示的 book 元素,必须按如下方法定义。复杂类型 bookType 的字符数据


内容符合简单类型 string,而且还添加了 isbn 属性。
<xsd:compleType name="bookType">
<xsd:simpleContent>
<xsd:extension base="xsd:string">
<xsd:attribute name="isbn" type="xsd:token">
</xsd:extension>
</xsd:simpleConten>
</xsd:compleType>

纯元素内容只允许有子元素,而没有字符数据内容。下例显示了具有纯元素内容的
bookinfo 元素,它有两个子元素:title 和 author。

·103·
·104· XML 实用教程

<bookinfo>
<title>三国演义</title>
<author>罗贯中</author>
</bookinfo>

可以按如下方式进行定义:
<xsd:compleType name="bookinfoType">
<xsd:sequence>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="xsd:string"/>
</xsd:sequence>
</xsd:compleType>

混合内容既允许有字符数据又允许有子元素。经常用于字母和文档等形式的自由文本。
下例中显示了具有混合内容的 chapter 元素。chapter 元素中直接包含字符数据以及子元
素 para。
<chapter>宴桃园豪杰三结义 斩黄巾英雄首立功
<para>话说天下大势,分久必合,合久必分。</para>
</chapter>

在创建所示的 chapter 元素类型定义时,需要设置 complexType 的 mixed 属性为 true,


允许有字符数据内容。mixed 的默认值为 false。
<xsd:compleType name="chapterType" mixed=true>
<xsd:sequence>
<xsd:element name="para" type="xsd:string"/>
<!--…-->
</xsd:sequence>
</xsd:compleType>

空内容既不允许有字符数据也不允许有子元素。带有空内容的元素通常在属性中具有
值。有某些情况下,甚至可以没有属性,但空内容的元素存在本身就有意义。如 XHTML
中的<br/>元素就表示一个新行。
<price value="30"/>

要定义空内容元素的类型时,只需指定属性,不用做其他内容的说明。
<xsd:compleType name="priceType">
<xsd:attribute name="value" type="xsd:integer">
</xsd:compleType>

2. 利用组合器控制结构
模式组允许把子元素声明或引用组合起来,从而构建更有意义的内容模型。模式组共
有 3 种:sequence、choice 和 all。
sequence 组合器,定义了一列元素并且必须按照模式中指定的顺序显示,所有子元素。
如果出现的话,都必须按照该顺序出现。示例如下。

·104·
第5章 XML Schema 结构 ·105·

<xsd:element name="book">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="publisher" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>

下面显示了一些 book 的有效实例。它的子元素都以正确的顺序出现。


<book>
<title>三国演义</title>
<author>罗贯中<author/>
<publisher>文艺出版社<publisher/>
</book>

choice 组合器用来声明只有一个相容元素必须出现,用于互斥情况。示例如下。
<xsd:element name="book">
<xsd:complexType>
<xsd:choice>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="publisher" type="xsd:string"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>

下面的实例都是有效的,每一个实例包含一个符合 choice 组中声明的子元素。如果出


现多个子元素,或者根本没有任何元素出现,那么该实例将是无效的。
<book>
<title>三国演义</title>
</book>

<book>
<author>罗贯中</author>
</book>

choice 组合器还可以允许任意数量的子元素以任意顺序出现。只要通过把 choice 组的


maxOccurs 属性设置为 unbounded 即可允许子元素以任何顺序出现,出现任意次数。另外,
为了指定更加高级的内容,sequence 和 choice 可以彼此嵌套,可以进行任意层数的嵌套。
<xsd:complexType name="tempType">
<xsd:sequence>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="xsd:string"/>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="amount" type="xsd:integer"/>

·105·
·106· XML 实用教程

<xsd:element name="price" type="xsd:integer"/>


</xsd:choice>
</xsd:sequence>
</xsd:complexType>

all 组合器用来表示符合元素声明的所有元素都应该出现(以任何顺序)且只能出现一
次。all 组合器与 choice 和 sequence 的不同之处在于:
(1) 只能包含元素声明和引用,而不能包含其他组。
(2) 不能出现多次。对于所包含的每个子元素,maxOccurs 必须为 1,而 minOccurs 只
可以为 0 或 1。不能出现在其他模式组中。all 组必须在复杂类型的最高层。
示例如下。
<xsd:element name="book">
<xsd:complexType>
<xsd:all>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="xsd:string"/>
<xsd:element name="publisher" type="xsd:string"
minOccurs="0"/>
<xsd:element name="price" type="xsd:integer" minOccurs="0"/>
</xsd:all>
</xsd:complexType>
</xsd:element>

根据上面的定义,下面显示了 book 的两个有效实例。


price 和 publisher 元素定义了 minOccurs
等于 0,因此可以不出现。
<book>
<title>三国演义</title>
<author>罗贯中</author>
<publisher>文艺出版社</publisher>
<price>30</price>
</book>

<book>
<title>三国演义</title>
<author>罗贯中</author>
</book>

5.6 Schema 的名称空间

名称空间是 XML Schema 中的重要部分,它提供了一种避免元素命名冲突的方法。名


称空间的用途在于为 XML 中使用的名称提供一个容器。

5.6.1 命名冲突

XML 是可扩展的,而这种扩展不受到控制。因为 XML 文档中使用的元素不是固定的,

·106·
第5章 XML Schema 结构 ·107·

那么就可能会出现多个不同的 XML 文档使用同一个名字来描述不同类型的元素的情况。


而这种情况又往往会导致命名冲突。请看下面两个例子。
如下 XML 文档在 table 元素中携带了水果的信息:
<table>
<tr>
<td>Apples</td>
<td>Bananas</td>
</tr>
</table>

如下 XML 文档在 table 元素中携带了桌子的信息:


<table>
<name>African Coffee Table</name>
<width>80</width>
<length>120</length>
</table>

如果上面两个 XML 文档片断碰巧在一起使用的话,那么将会出现命名冲突的情况。


因为这两个片断都包含了 table 元素,而这两个 table 元素的定义与所包含的内容又各不
相同。

5.6.2 使用前缀解决命名冲突问题

前面的例子中所出现的命名冲突问题就是由于 XML 的可扩展性导致的,没有办法能


够防止任何人以与其他人不兼容的方式对文档进行扩展。名称空间的出现就是为了解决这
个问题的。名称空间定义了一个标记的容器,为所有在文档中使用的标记名称提供语境。
实例文档中的元素类型或属性的名称可能直接与名称空间关联,或者就属于某个名称空间。
这样就可以避免命名的冲突。因此,可以这样改造上面的 XML 文档,在 table 元素前面加
上前缀。
<h:table>
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h<h:ta:table>

则家具 table 的信息变成:


<f:table>
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>

现在已经没有元素命名冲突的问题了,因为这两个文档对各自的 table 元素使用了不同


的前缀,table 元素在两个文档中分别是<h:table> 和<f:table>。但是,前缀还不能彻底解决
问题,因为任何人都可以创建前缀,如果两个文档创建了相同的前缀,则又出现冲突问题。

·107·
·108· XML 实用教程

为了避免前缀冲突,可以使用如下的前缀声明。
f="http://www.example.org/html"
h="http://www.example.org/furniture"

将统一资源标识符(Uniform Resource Identifier,URI)跟前缀联系起来。因为 URI 跟标


记或前缀不同,它具有唯一性。这就是名称空间的解决方法。

5.6.3 使用名称空间

名称空间属性一般放置在元素的开始标记处,从 xmlns 属性开始,后面是前缀。其使


用语法格式如下:
xmlns:namespace-prefix="namespace"
具体示例如下:
xmlns:f="http://www.w3.org/2000/10/XMLSchema"

前缀只是起着名称空间的代理作用。名称空间的名称是 URI,而不是前缀,在比较两
个元素时,解析器是根据 URI 来识别它们的名称空间,而不是根据前缀识别。上面的例子
则可以与不同的名称空间关联到一起。
<h:table xmlns:h="http://www.example.org/html">
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>

下面是携带了家具 table 的信息 XML 文档。


<f:table xmlns:f="http://www.example.org/furniture">
<f:name>African Coffee Table</f:name>
<f:width>80</f:width>
<f:length>120</f:length>
</f:table>

5.6.4 URI、URL 和 URN

名称空间的声明将一个全局名称(URI)跟元素的名称联系在一起。URI 只作为标识符。
仅就作为 XML 名称空间来说,URI 不必是有效的。也就是说,它不必指向任何位置。XML
名称空间只将它们作为字符串处理。比较是逐个字符进行的,因此,下面的两个 URI 是不
同的,虽然指向同一个文档。
http://www.example.org
http://example.org

而且名称空间是区分大小写的。即使仅有大小写区别,也会被解析为不同的 URI。
大多数的 URI 都是 URL 或 Internet 地址。可能指向网络上的某个文件、用户电子邮箱
(mailto:branch@example.org)或者是新闻组(news:comp.exmaple.xml)。
目前正在开发另一种形式的 URI,称为 URN(Uniform Resource Name)。两者的区别在

·108·
第5章 XML Schema 结构 ·109·

于:对地址来说,如果文档移动了位置,那么地址就失效了,而 URN 不是地址,它们与文


档的位置无关。URN 是用“urn:”前缀构建的,后跟一个前缀表明该 URN 的类型,最后是值。
urn:isbn: 0-764-58007-8

这里 ISBN 的编号就是 URN 的实例。每个 ISBN 编号都代表了一本书。

5.6.5 名称空间的作用域

名称空间声明可以出现在文档的任何开始标记中,它的作用域是它在其开始标记中出
现的元素以及其所有子元素等。
<bk:book xmlns:bk="http://www.example.org/2005/book">
<bk:title>三国演义</bk:title>
<bk:author >罗贯中</bk:author>
<bk:price >80.00 </bk:price>
<bk:recommendation>经典好书</bk:recommendation>
<ph:publish xmlns:ph="http://www.example.org/2005/publish">
<ph:publisher>文艺出版社</ph:publisher>
<ph:pubdate>1998.10</ph:pubdate>
</ph:publish>
</bk:book>

上面的示例中声明了两个名称空间,bk 是顶层元素声明的,因此对所有元素都是有效
的。ph 是为 publisher 元素声明的,只对它的子元素有效。但是,如果还有一个 book 元素,
它的子元素 publisher 使用了 ph 前缀,则是不合法的名称空间,因为超出了其作用域。一
般来说,最好把所有名称空间声明都放到根元素的开始标记中。这样可以一下子看到文档
的所有名称空间,对于它们的作用域也不会混淆。

5.6.6 在 XSDL 中使用的名称空间

1. 目标名称空间
每一个XSDL 模式文档都可以是一个名称空间,这称为它的目标名称空间(Target
Namespace)。每个被全局声明所声明和定义的元素、属性、类型或组等都与该目标名称空
间有关。下例中声明了 http://www.example.org/2005/book 的目标名称空间。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.example.org/2005/book"
targetNamespace="http://www.example.org/2005/book">
<xsd:element name="book"type="BookType"/>
<xsd:complexType name="BookType">
<xsd:sequence>
<xsd:element name="title" type="xs:string" />
<xsd:element name="author" type="xs:string"/>
<xsd:element name="price" type="xs:integer" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

而下面的例子显示相应的元素如何出现在一个实例中。

·109·
·110· XML 实用教程

<bk:book xmlns:bk="http://www.example.org/2005/book">
<bk:title>三国演义</bk:title>
<bk:author>罗贯中</bk:author>
<bk:price>80.00 </bk:price>
</bk:book>

2. XML Schema 名称空间


由于XSDL 也是XML 文档, 所以名称空间也适用于它。 在XSDL 中使用的所有元素: schema、
element 和 simpleType,都在 XML Schema 名称空间中,其名称空间名称为 http://www.w3.org/
2001/XMLSchema。此外,内置的简单类型也在这个名称空间中。最常映射到这个名称空
间的前缀是 xsd 或 xs。如上面的例子,都采用 xsd 前缀。
3. XML Schema 实例名称空间
XML Schema 实例名称空间是实例中可以出现的 4 个与模式相关的属性的独立名称空
间,其名称空间名称为 http://www.w3.org/2001/XMLSchema-instance,一般映射到前缀 xsi。
当在实例中使用这 4 个属性:nil、type、schemaLocation 和 noNamespaceSchemaLocation 时,
需要声明 XML Schema 实例名称空间,在实例中它们的名称必须加前缀。
4. 模式文档中名称空间的声明
为了解析模式文档的引用,模式文档必须包含目标名称空间和 XML Schema 名称空间
的声明。可以把 XML Schema 名称空间映射到像 xsd 或 xs 这样的前缀,从而使目标名称空
间成为默认名称空间。这样由 XML Schema 定义就显得非常清楚了,示例如下。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.example.org/2005/book"
targetNamespace="http://www.example.org/2005/book">
<xsd:element name="book"type=“BookType"/>
<xsd:element name="title"type="xsd:string"/>
<xsd:complexType name="BookType">
<!--…-->
</xsd:complexType>
</xsd:schema>

另一种方法是把前缀映射到目标名称空间,并使 XML Schema 名称空间成为默认名称


空间。下例显示了这一方法。声明中的名称本身不需要加前缀,因为它们自动成为 XML
Schema 名称空间的一部分,唯一使用前缀的地方就是对其他组件的引用。如 book 元素通
过限定名称引用类型 BookType。如果不加前缀,那么解析器将在 XML Schema 名称空间中
寻找 BookType 的定义。
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:bk="http://www.example.org/2005/book"
targetNamespace="http://www.example.org/2005/book">
<element name="book"type="bk:BookType"/>
<element name="title"type="xsd:string"/>
<complexType name="BookType">
<!--…-->
</complexType>
</schema>

·110·
第5章 XML Schema 结构 ·111·

有时,把前缀映射到所有名称空间也是可以的,这样整个文档也非常清晰。
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:bk="http://www.example.org/2005/book"
targetNamespace="http://www.example.org/2005/book">
<xsd:element name="book" type="bk:BookType"/>
<xsd:element name="title" type="xsd:string"/>
<xsd:complexType name="BookType">
<!--…-->
</xsd:complexType>
</xsd:schema>

5.7 使用 XML Spy 建立 Schema 文档

利用前面有关的 XML 文档进行简化,现在使用 XML Spy 来建立 Schema 文档。


【例 5.6】 简化了的书籍 XML 文档,代码如源程序 code5_6.xml 所示。以此为例,逐步建
立 Schema 文档。
<?xml version="1.0" encoding="gb2312" ?>
<book isbn="0-764-58007-8">
<title>三国演义</title>
<author >罗贯中</author>
<price >80.00 </price>
<resume>滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。
白发渔樵江渚上,惯看秋月春风。一壶浊酒喜相逢。古今多少事,都付笑谈中。
</resume>
</book>

5.7.1 建立根结点

选择菜单 File | New,弹出 Create new document 对话框,选择里面的 xsd(XML Schema


file),这样一个空的 Schema 文档就会被建立,然后从 Schema/WSDL 视图区切换到 Grid 视
图区,如图 5.1 所示。

图 5.1 新建一个 Schema 文档

·111·
·112· XML 实用教程

窗体下方的几个按钮提供不同的视图来设计 Schema 文件。本例选择的是 Grid 视图,


可以有许多详细信息。
接着,单击左上角的黑三角,编码方式项 enconding 默认值为 UTF-8,将其改为 GB2312,
以便使用中文。在 element 处双击,添加根结点 book。双击右侧 Elements 面板里 Append
选项卡中的 xs:complexType,将其设置成复杂类型,紧接着选择 Insert 选项卡,设置为
xs:sequence,完成后如图 5.2 所示。

图 5.2 添加一个元素并设定元素类型

5.7.2 为根结点 book 添加子结点 title、author、price、resume 及属性 isbn

在右侧的 Elements 面板上面,选择 Add child | Element,为其增加 4 个子结点。并在


Attributes 面板上为每个子结点设置结点名和类型。同样利用 Elements 和 Attribute 再次为
ISBN 添加属性并设置属性的类型,结果如图 5.3 所示。

图 5.3 添加子结点信息

这样 Schema 文档就建立好了,保存为文件名 code5_6.xsd,切换到 Text 视图区,可以


看到代码如下:

·112·
第5章 XML Schema 结构 ·113·

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


<!-- edited with XMLSPY v2004 rel.2U(http://www.xmlspy.com) by Jerry (jmu)
-->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:element name="book">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string"/>
<xs:element name="author" type="xs:string"/>
<xs:element name="price" type="xs:integer"/>
<xs:element name="resume" type="xs:string"/>
</xs:sequence>
<xs:attribute name="ISBN" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>

切换到 Schema/WSDL 视图区,可以看到上例的结构图,如图 5.4 所示。

图 5.4 定义好的书籍文档结构

5.7.3 为 XML 文档指定 Schema

建立好了 Schema 文档,就需要用它来检验 XML 文档。XML Spy 也可以为 XML 文档


指定 Schema 文档。打开 XML 文档,选择 DTD/Schema 菜单下面的 assign Schema,在出现
的对话框中选择 XML 文档对应的 Schema 文档即可。那么,程序 code5_6.xml 中关于 book
结点的说明就变为
<book xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="c:\ch5\code5_6.xsd"
isbn="0-764-58007-8" >

为 XML 文档指定 Schema 后,可以对 XML 文档进行有效性检查。如同第 6 章一样,


按 F8 键或单击工具栏上带绿色“√”的图标按钮,进行 XML 文档有效性的检查。如果检
查合格,则在文档下方会显示“This file is valid.”。

·113·
·114· XML 实用教程

另外,XML Spy 也可以利用现有的 XML 文档直接生成 Schema 文档。打开 XML 文档


后,选择 DTD/Schema 菜单下面的 Generate DTD/Schema,然后按照出现的对话框提示,一
步一步生成相应的 Schema 文档。
如同 XML 与 DTD 的关系一样,一般情况下,先规划好 XML 的文档结构,再设计 Schema
文档,最后根据 Schema 文档结构编辑 XML 文档。有了 Schema 文件,在 XML Spy 下建立
XML 文件,就只需在 Grid 视图区格架下填写元素和属性的值,就能很方便地建立 XML 文
档了。

5.8 小 结

Schema 是描述 XML 文档的文档,用来定义 XML 文档的格式。最常用的用法之一就


是依照预定义好的规则来验证 XML 文档的有效性。Schema 可以确认:
(1) 元素和属性的结构;
(2) 元素出现的顺序;
(3) 对元素和属性的数据值的取值范围进行限定;
(4) 保证实例中值的唯一性。
同时,在 Schema 处理过程中也可以扩充实例,为元素和属性插入默认值和固定值。
并根据数据类型规范化空白空间。
与 DTD 相比较而言,XML Schema 采用 XML 的语法,并且支持名称空间,提供丰富
的数据类型定义手段,具有很强的描述能力、扩展能力和处理维护能力。
元素和属性是 XML 文档的基本构件。Schema 主要包括元素和属性的声明及定义,模
式文档由元素、属性、名称空间和 XML 文档中的其他结点构成,并且至少要包含:schema
根元素、XML 模式名称空间的定义和元素定义。元素是利用 element 标记来声明的,其中
name 属性是元素的名字,type 属性是元素值的类型。属性实现的方法是使用 attribute 元素。
对于元素或属性,可以通过默认值和固定值的方式增加未出现的元素或者属性来扩充实例。
默认值和固定值分别通过 default 和 fixed 属性设置。两个属性只能出现其中之一,因为它
们是互斥的。
不管是元素还是属性,都要定义它的数据类型,XML Schema 定义了两种主要的数据
类型:预定义简单类型和复杂类型。简单类型包括原子类型、列表类型、联合类型合,新
的简单类型可以通过从现有的简单类型引出定义。使用 simpleType 元素来定义和命名新的
简单类型。属性只能定义为简单类型。复杂类型和简单类型之间最根本的区别就是:复杂
类型的内容中可以包含其他元素或属性,由 complexType 元素创建。
名称空间是 XML Schema 中的重要部分,它提供了一种避免元素命名冲突的方法。名称
空间的用途在于为 XML 中使用的名称提供一个容器。在 XSDL 中使用的名称空间主要有:
目标名称空间,是每个模式文档的名称空间;XML Schema 名称空间,其名称空间的名称为
http://www.w3.org/2001/XMLSchema;实例名称空间,其名称空间的名称为 http://www.w3.org
/2001/XMLSchema-instance。

·114·
第5章 XML Schema 结构 ·115·

5.9 习 题

1. XML Schema 与 DTD 比较,Schema 的优越性有哪些?


2. 对于 XML 文档,Schema 有哪些作用?
3. 编写好一个 Schema 文档,要使用它来验证一个 XML 文档是合法的,如何进行引用。
4. Schema 文档设置元素的固定值和默认值的用途是什么?分别是如何扩展实例的,举
例说明。
5. Schema 文档有那两种主要数据类型,分别适用于什么情况下定义数据类型?
6. 有关于默认值 Schema 定义:
<xsd:complexType>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="name" type="xsd:string" default="N/A"/>
<xsd:element name="size" type="xsd:integer" default="12"/>
</xsd:complexType>

那么对于下面的实例,当 Schema 扩充后,是什么样的结果:


<size>10<size>
<size/>
<name/>
<name><name/>

7. 有关于固定值 Schema 定义:


<xsd:element name="name" type="xsd:string",fixed="1">
<xsd:element name="size" type="xsd:integer"fixed="1">

那么对于下面的实例,哪些是有效的?
<size>1</size>
<size>2</size>
<size>+1</size>
<name>1<name/>
<name>+1<name/>

8. 对于衣服大小的号码,可以是 2~18 的整数,也可以是 small、medium 或 large。请


使用联合类型给出关于这种衣服大小的类型的定义。
9. 在一个 XML 文档中,需要用到一个 article 的结点,这个结点结构如下:
<article>
<HeadLine section="business">
<MainHead>Main headline goes here</MainHead>
<SubHead>A subheadline goes here</SubHead>
</HeadLine>
<ByLine>
<Author>John Doe</Author>
<title>Reporter</title>

·115·
·116· XML 实用教程

</ByLine>
<DateLine>April 30, 2005</Dateline>
<body>Content of story goes here…</body>
<stats>
<submitted>2005-03-02</submitted>
<wordCount>1523</wordCount>
</stats>
</article>

请在分别定义 HeadLine、ByLine、DateLine、stats 结点的数据类型基础上,再定义 article


的复杂数据类型。
10. 若第 9 题为多篇文章(articles),请为其建立完整的 XML Schema 文件,保存文件名
为 code5_7.xsd。
11. 在 XML Spy 中采用上题的 code5_7.xsd 文件新建 XML 文件 code5_7.xml,在 Grid
视图下填写 3 本书,并做文档的有效性检查。
12. 在 XML 文档中使用哪些名称空间,分别有什么用途?

·116·
第 6 章 层叠样式表

教学提示:XML 为存储结构化数据提供了强大的方法,但是它没有提供关于数据如何
显示的信息,这实际上是 XML 的优点——数据的结构完全与数据表示无关。当有必要表示
格式化 XML 文件中的数据时,格式化的详细信息放置在 CSS 中。
教学目标:理解 CSS 的概念,掌握 CSS 的方法,掌握 CSS 与 XML 结合的方法,学会
综合运用 CSS。

6.1 CSS 简介

在前面的知识中曾经介绍过,单纯的 XML 文档只是为数据提供结构,但是它没有涉


及数据如何显示,CSS 是用于为 XML 数据定义显示参数的一种技术,它利用简单的规则
来控制元素内容在浏览器中的表现方式。CSS 最初是被开发用来为 HTML 文档指定显示的,
同时也适合于 XML 数据。样式表中的显示规范与 XML 数据分离,这意味着相同的数据通
过应用不同的样式表可以不同的方式显示。同样,相同的样式表可以应用到多个 XML 文件
中。下面,就来学习一种 XML 很常用的样式表:CSS。

6.1.1 CSS 的概念

CSS(Cascading Style Sheet)层叠样式表,也称为级联样式表,用来进行网页风格设计。


在网页制作时采用 CSS 技术,可以有效地对页面的布局、字体、颜色、背景和其他效果实
现更加精确的控制。只要对相应的代码做一些简单的修改,就可以改变同一页面的不同部
分,或者页数不同的网页的外观和格式。它具有以下特点。
(1) 在几乎所有的浏览器上都可以使用。
(2) 以前一些必须通过图片转换实现的功能,现在只要用 CSS 就可以轻松实现,从而
更快地下载页面。
(3) 使页面的字体变得更漂亮,更容易编排。
(4) 可以轻松地控制页面的布局。
(5) 可以将许多网页的风格、格式同时更新,不用再一页一页地更新。可以将站点上
所有的网页风格都使用一个 CSS 文件进行控制,只要修改这个 CSS 文件中相应的行,那么
整个站点的所有页面都会随之发生变动。
CSS 是通过对页面结构风格控制的思想,控制整个页面风格的。CSS 放在页面中,通
过浏览器的解释执行,是完全的文本,任何懂得 HTML 的人都可以掌握,非常容易。甚至
对一些非常老的浏览器,也不会产生页面混乱的现象。
·118· XML 实用教程

大到一个网站,小到一个 HTML 标志,使用的形式不同,则 CSS 能规定的范围也有所


不同,如果要对一个站点的一些风格进行统一规定,那么用 CSS 文件就必不可少了;如果
想使用层叠样式表只规定某个页面的风格,那么内部文档头就能胜任这项工作;如果还想
使某些 HTML 标志有特殊的样式规定,那么就要用到直接插入方式。这 3 种存在方式就可
以使整个网站在风格统一的前提下,又各有特色,富于变化,将变化与统一这个矛盾的两
面有机地结合起来,这就是 CSS 能够实现的功能。
现在已经发表的 CSS 版本是 CSS1 和 CSS2,W3C 组织已经基本完成了 CSS3 标准的
制定,但目前还未发表。当前大部分主流浏览器及其他网页制作工具都建立了对 CSS1 和
CSS2 的支持。1998 年推出的 CSS2 比 CSS1 在功能上强大了很多,扩展的属性和方法使得
网页的表现手法更为丰富多彩。

6.1.2 CSS 的使用

1. CSS 的基本语法
在 XML 中,组成文档的单元是一个个的元素,因此元素的概念对于 XML 来说非常重
要。而在 CSS 中,几乎看不到 XML 语法的任何痕迹(当然,CSS 本来就不是为 XML 设计的)。
然而,CSS 也有自己的组成结构,而且也有类似 XML 中元素的结构单元。在这里,暂且
就叫这种结构单元为 CSS 元素。
CSS 的规则通过属性与属性值来共同设定。属性名称是 CSS 的关键字,如 font-family(字
体)、font-size(文字大小)、display(显示属性)和 color(颜色)等。属性用于指定元素某一方面
的特性,而属性值则用于指定元素特性的具体特征。
样式表的建立要符合 CSS 规则,它们一般被定义成以下形式的句法。
标志{标志属性 1:属性值 1;标志属性 2:属性值 2;标志属性 3:属性值 3;…}
其中标志不带尖括号,如 P、Div、Table 等,而不是<P>、<Div>以及<Table>。
“标志属性:属性值,”是一一对应的,每个属性与属性值对之间用分号隔开。有一点
要说明的是,在 CSS 中对属性设置与脚本语言中对属性设置有一点不同,即属性名称的写
法,在 CSS 中,凡属性名为两个或两个以上的单词构成时,单词之间以“-”隔开,比如,
背景颜色属性 background-color;而在脚本中,对象属性则连写成 backgroundColor,第二个
单词首字母大写,如有 3 个单词则第三个单词首字母也要大写。
下面是样式表的一个简单的例子:
P{background-color:red;font-size:12pt;color:black}

上面分别设置了背景色、字体大小以及字体颜色等。为了看起来直观一些,还可以
写成:
P{background-color:red;
font-size:12pt;
color:black}

在 CSS 中,有些属性可以表示多个属性的值,如字体设置,有 font-family(字体)、


font-size(文字大小)、font-style(字体风格),这些可用一个 font 属性来表示,如:

·118·
第6章 层叠样式表 ·119·

P1{font-size:16pt;
font-family:'宋体';
font-style:italic}

可直接用 P1{font:20pt 宋体 italic}来表示。


CSS 是一个完全的纯文本文件,一般以.css 作为扩展名,它的内容就包含了一组告诉
浏览器如何安排与显示特定 XML 文件中元素的规则。
在 XML 文档中,CSS 文件的使用分为内部 CSS 的使用、外部 CSS 的使用以及内外
CSS 的使用,本节通过几个简单的例子来介绍这 3 种方法的使用。
2. 无 CSS 的 XML 文件
【例 6.1】 这是一个没有应用 CSS 的 XML 文档,代码如源程序 code6_1.xml 所示。
<?xml version="1.0" encoding="gb2312" ?>
<poem>
<name>望庐山瀑布</name>
<writer>唐.李白</writer>
<content>日照香炉升紫烟</content>
<content>遥看瀑布挂前川</content>
<content>飞流直下三千尺</content>
<content>疑是银河落九天</content>
</poem>

其显示结果如图 6.1 所示。

图 6.1 没有 CSS 的 XML 文档显示结果

由于没有对应的 CSS,浏览器根本不知道应该如何处理元素内容的显示方式,所以只
能原样显示。
3. 使用 CSS 的 XML 文件
XML 文档中通过引用外部 CSS 来定义文档的表现形式。大部分 XML 文档都采用这种
方式,这也与 XML 的内容与形式分开的原则相一致。具体实现的方法是,在 XML 文档的
开头部分写一个关于样式单的如下声明语句:
<?xml-stylesheet type="text/css" href="mycss.css" ?>

这样一来,按照声明语句的指示,该文档在浏览器上的表现方式就由样式文件 mycss.css

·119·
·120· XML 实用教程

所决定了。
这个命令说明了该 XML 文档使用 CSS,CSS 文件为本地目录的 mycss.css。
当然,也可以使用完整的 URL 指定 CSS 文件,如下面这个例子:
<?xml-stylesheet type=" text/css" href=http://www.myhome.com/file/mycss.css ?>

通常情况下,将样式表处理指令加到 XML 文档的序文中,紧接在 XML 声明的后面。


XML 解析器在处理时如果顺利找到了指定的 CSS 文件,则会按照其中定义的格式显示
XML 文档。而当浏览器的 XML 解析器没有找到该指定的 CSS 文件,或者这个文件中定义
的格式不可识别,那么浏览器将会直接显示 XML 文件的源程序代码,而没有任何格式。
【例 6.2】 文档 code6_2.xml 使用了 CSS 文件 code6_2.css。
<?xml version="1.0" encoding="gb2312" ?>
<?xml-stylesheet type="text/css" href="code6_2.css"?>
<poem>
<name>望庐山瀑布</name>
<writer>唐.李白</writer>
<content>日照香炉升紫烟</content>
<content>遥看瀑布挂前川</content>
<content>飞流直下三千尺</content>
<content>疑是银河落九天</content>
</poem>

现在,定义 code6_2.css。
@charset "gb2312";
name{display:block;
font-family: 黑体;
font-size: 20pt;
letter-spacing:10pt;
text-align:center; }
writer{display:block;
font-family: 魏碑;
font-size:10pt;
font-weight:bold;
letter-spacing:10pt;
line-height:40pt;
text-align:center;
color: Black; }
content{display:block;
font-family: 隶书;
font-size: 20pt;
font-weight:bold;
line-height: 30pt;
letter-spacing:10pt;
text-align:center;
color: Black;}

在 IE 中打开后的效果如图 6.2 所示。

·120·
第6章 层叠样式表 ·121·

图 6.2 使用 CSS 后的显示结果

这样一来,原来界面单调的 XML 信息现在就有了一些活力。


6.2 节主要介绍在排版、版面设置中常用的 CSS,使用它们会使得整个页面更美观,视
觉效果更好。当然,CSS 属性不仅限于本节所介绍到的,感兴趣的读者可以翻阅其他参考
资料来使用其他属性。

6.2 设置字体属性

通常,XML 文档中最主要的信息是由文本信息构成的。换句话说,文字和符号是存储
信息的主要载体。现在就来学习 CSS 中控制文字格式的相关语法。

6.2.1 font 属性集

1. font 属性的分类
font 属性通常用于设置指定字体的风格、大小、亮度等参数。该属性在 XML 样式表分
类中属于通用字体类,由 CSS 定义。font 属性的常见子属性见表 6-1。

表 6-1 font 属性的常见子属性

font 属性 说 明

font-family 指定字体的字型
font-style 指定字体的风格
font-weight 指定字体的亮度
font-variant 指定字体全为大写字母
font-size 指定字体的大小
font-stretch 指定字体的压缩或拉伸方式

·121·
·122· XML 实用教程

2. font 属性的用法
与常见的 CSS 属性设置类似,font 属性的使用示例如下:
element{font-style:italic;font-size: "20pt"; font-family: "楷体_gb2312";}

该示例中,最前面是被指定格式的 XML 元素的名称。在接下来的字体样式设定中,


声明了使用的字体风格是斜体(italic),字体大小是 20 像素(20pt),字型为国标楷体(楷体
-gb2312)。
3. 字体字型 font-family 属性
font-family 属性用于指定字体名称,属性值使用逗号分隔的字体名称。如果字体名称
中出现空格,必须使用双引号将字体括起来,如“Times New Roma”。
font-family 属性可用的值取决于用户系统中已经安装了的字体,在 Windows 系统的安
装目录下的 fonts 文件夹中保存了系统安装的所有字体。
font-family 属性的参数值可以有几个,在指定 font-family 属性的时候,可以同时指定
几个字符集。这样,在浏览器找不到第一个字符集的时候可以按顺序使用第二个字符集显
示字体,例如:
element{font-family:"楷体_gb2312","宋体","黑体";}

该格式说明了可以使用楷体_gb2312、宋体、黑体 3 种字体来显示 element 元素。若系


统中找不到楷体_gb2312,则用宋体;若也没有宋体,则使用黑体,按出现的先后顺序优先
选择。
4. 字体风格 font-style 属性
font-style 属性用于指定字体的风格,例如显示斜体字样。font-style 属性的参数值见
表 6-2。

表 6-2 font-style 属性的参数值

font-style 属性 说 明

normal 表示不使用斜体,该参数是 font-style 属性的默认值


italic 表示使用斜体显示文字
oblique 表示使用倾斜幅度不大的斜体显示文字

读者阅读的普通文本就是正常体。倾斜字体(oblique)的文本十分类似于斜体文本。但
是,绝大多数情况下,倾斜字体的文本是由计算机根据简单的算术运算,使正常的文本倾
斜一定的角度实现的。用斜体字印刷文本通常是为了美观。
5. 字体亮度 font-weight 属性
font-weight 属性设置字体的粗体程度,用于决定文本以多黑(粗)或多浅(细)显示文本。
font-weight 属性的参数值见表 6-3。
font-weight 属性设置字体的粗体程度,常用取值为 bold 和 normal,例如:
element{font-weight:bold}

·122·
第6章 层叠样式表 ·123·

表示以粗体形式显示 element。font-weight 取值 normal 表示以正常形式显示字体,此


外 font-weight 还可取值 100,200,300,400,500,600,700,800,900 来表示其粗细程
度,100 表示最细、400 表示正常值、700 表示标准黑体,其他数字表示相对于区间内的黑度。

表 6-3 font-weight 属性的参数值

font-weight 属性 说 明

normal 表示使用标准字体(没有加深色彩),该参数是 font-variant 属性的默认值


bold 表示使用标准的黑体文本
bolder 表示使用比标准黑体还要深的颜色显示文字(为相对参数)
lighter 表示使用比标准黑体稍浅的颜色显示文字(为相对参数)

element{font-weight:900}
element{font-weight:200}

当取值越大时表示的字体越粗,当取值越小时表示的字体越细(取值为 900 时最粗,100


时最细)。
6. 设置为大写字母 font-variant 属性
font-variant 属性用于设置打印时英文字体的大小写变化。font-variant 属性的参数值见
表 6-4。

表 6-4 font-variant 属性的参数值

font-variant 属性 说 明

normal 表示在打印中大写字母没有变化,该参数是 font-variant 属性的默认值


表示设定用大写字母代替文本中的小写字母。font-variant 属性值设置为
small-caps
small-caps 将会用比主体文本字号小一些的大写字母代替小写字母

7. 设置字体大小 font-size 属性
font-size 属性用于指定字体的相对或者绝对大小。font-size 属性的参数值见表 6-5。

表 6-5 font-size 属性的参数值

font-size 属性 说 明
整数+pt 表示使用指定的像素大小显示字体,pt 表示像素(如 20pt、35pt)
整数+% 表示当前元素使用字体大小是前一个元素大小的百分数(如 40%、150%)
large 表示使用比父元素大一号的字体
x-small 表示使用字体比 small 字体小 1.2 倍
xx-small 表示使用字体比 x-small 字体小 1.2 倍
x-large 表示使用字体比 large 字体大 1.2 倍
xx-large 表示使用字体比 x-large 字体大 1.2 倍
medium 表示使用标准字体大小显示

·123·
·124· XML 实用教程

8. 文本属性
在 CSS 中,表示文本外观的属性有 8 个,使用说明见表 6-6。
例 如 : name{letter-spacing:.5em} 表 示 增 加 字 符 间 距 为 文 本 高 度 的 1/2 。 Name
{letter-spacing:-.5pt}表示减少字符间距 0.5 磅。若将 letter-spacing 值设为 normal 则表示使用
正常的字符间距。

表 6-6 文本外观的属性

文本属性 说 明
letter-spacing 设置字符间隔,可以增加或减少字符之间的间距
word-spacing 设置字符间隔。其使用方法与 letter-spacing 类似
vertical-align 设置或检索对象内容的垂直对齐方式
作用于块元素,用来设置块中文本的对齐方式,取值为:left(左对齐)、right(右
text-align
对齐)、center(居中)、justify(两端对齐)
设置第一行缩进距离。如 name{text-indent:2em},表示第一行缩进两个字的
text-indent
长度
inline-height 控制文本连续行之间的距离,可以用来调整文本垂直线的距离
设置显示文本的字母大小写的显示形式。取值关键字为:capitalize,首字母
text-transform 大写;uppercase,所有字母都大写;lowercase,所有字母都小写;none,
不改变字母的大小写状态
声明文本是否有划线,常用来装饰链接。取值关键字为:overline,有上划
text-decoration 线;line-through,有穿过文本的删除线;blink,使文字闪烁;underline,有
下划线;none,没有任何划线

name{word-spacing:.5em} 表示增加字符间距为文本高度的 1/2,name{letter-spacing:-.5em}


表示减少字符间距为文本高度的 1/2。
9. 在 CSS 中显示中文
在 XML 文档中使用中文元素名称时,需要在文档序文部分添加 encoding=“gb2312”的
XML 指令声明。但是在 CSS 中,要对目标元素进行格式指定,则要求目标元素只能是由
XML 的标准命名字符命名的(例如大小英文字符、数字、下划线等),而绝对不能使用中文
元素名称。
由于 CSS1 在支持非字符文字方面表现很不尽如人意,所以在 CSS2 中针对这个问题进
行了改善。CSS2 标准中对于多语言功能的支持是通过关键字“@charset”再加上需要使用
的语言字符集名称实现的,例如要使用的是中文国标字符集,就要在 CSS 文件的第一行加
入语句:
@charset"gb2312";

这样,就可以在 CSS 文件中使用各种中文字体了,当然,还是不能使用中文作为元


素名称。

·124·
第6章 层叠样式表 ·125·

6.2.2 实例

下面是一个使用字体属性的例子。
【例 6.3】 用 CSS 显示文档 code6_3.xml,CSS 文件为 code6_3.css。
<?xml version="1.0" encoding="gb2312" ?>
<?xml:stylesheet type="text/css" href="code6_3.css"?>
<poem>
<name>望庐山瀑布</name>
<writer>唐.李白</writer>
<contentA>日照香炉升紫烟</contentA>
<contentB>遥看瀑布挂前川</contentB>
<contentC>飞流直下三千尺</contentC>
<contentD>疑是银河落九天</contentD>
</poem>

现在,定义 code6_3.css 文件。


@charset "gb2312";
name{display:block;
font-family: 隶书;
font-size: 30pt;
letter-spacing:10pt;
text-align:center; }
writer{display:block;
font-family: 魏碑;
font-size:10pt;
font-weight:bold;
letter-spacing:10pt;
line-height:40pt;
text-align:center;
color: Black; }
contentA{display:block;
font-family: 隶书;
font-size: 20pt;
font-weight:bold;
line-height:100%;
letter-spacing:10pt;
text-align:center;
color: Black;
font-weight: lighter;}
contentB{display:block;
font-family: 隶书;
font-size: 20pt;
font-weight:bold;
line-height:100%;
letter-spacing:10pt;
text-align:center;
color: Black;
font-size:200%;

·125·
·126· XML 实用教程

font-weight: bolder;}
contentC{display:block;
font-family: 隶书;
font-size: 20pt;
font-weight:bold;
line-height:100%;
letter-spacing:10pt;
text-align:center;
color: Black;
font-size:300%;
font-weight: 700;}
contentD{display:block;
font-family: 隶书;
font-size: 20pt;
font-weight:bold;
line-height:100%;
letter-spacing:10pt;
text-align:center;
color: Black;
font-size:400%;
font-weight: 900;}

该程序在 IE 中运行的结果如图 6.3 所示。

图 6.3 使用字体属性的例子

本实例的目的是让大家熟悉各种与字体相关的属性设置的特点和用法。在 实 例
code6_3.css 文件中没有进行其他操作,只分别针对诗里不同的文字样式要求进行了属性的
字体设置,并综合运用了字体、字型、风格等文字修饰技术,可以说是字体设置方面知识
点的一个整合。
字体样式属性的设置操作起来是比较简单的。

·126·
第6章 层叠样式表 ·127·

6.3 设置色彩和背景图像属性

在互联网中,没有色彩的页面即使做得再精致也缺乏吸引力。CSS 中对于色彩和图像
的设定功能也是比较完善和强大的,接下来学习在 CSS 中添加色彩属性的定义。

6.3.1 定义前景色

与通常的页面文件类似,CSS 的色彩也由前景色和背景色构成。而 color 属性就是用于


对前景色进行设定的。
1. color 属性
color 属性用于设置指定字体元素字体的色彩参数。该属性在 XML 样式表分类中属于
通用混合类,由 CSS 标准定义,其中颜色名称参数对应的色彩数值见表 6-7。

表 6-7 颜色名称参数对应色彩数值

颜 色 十进制 RGB 十六进制 RGB RGB 百分数

纯红 RGB(255,0,0) #FF0000 RGB(100%,0%,0%)

纯蓝 RGB(0,0,255) #0000FF RGB(0%,0%,100%)

纯绿 RGB(0,255,0) #00FF00 RGB(0%,100%,0%)

白色 RGB(255,255,255) #FFFFFF RGB(100%,100%,100%)

黑色 RGB(0,0,0) #000000 RGB(0%,0%,0%)

浅紫 RGB(255,204,255) #FFCCFF RGB(100%,80%,100%)

浅灰 RGB(153,153,153) #999999 RGB(60%,60%,60%)

褐色 RGB(153,102,51) #996633 RGB(60%,40%,20%)

粉红 RGB(255,204,204) #FFCCCC RGB(100%,80%,80%)

橙色 RGB(255,204,0) #FFCC00 RGB(100%,80%,0%)

2. color 属性的用法
color 属性的语法比较简单,下面通过一个示例来进行介绍。
例如,有这样一个很简单的 XML 文档示例,内容是显示一段唐诗。现在,使用 color
属性对该 XML 文档进行前景色彩的设定,如例 6.4 的程序代码。
【例 6.4】 文档 code6_4.xml 的显示,使用的 CSS 文件为 code6_4.css。
<?xml version="1.0" encoding="gb2312" ?>
<?xml:stylesheet type="text/css" href="code6_4.css"?>
<poem>
<name>望庐山瀑布</name>
<writer>唐.李白</writer>

·127·
·128· XML 实用教程

<contentA>日照香炉升紫烟</contentA>
<contentB>遥看瀑布挂前川</contentB>
<contentC>飞流直下三千尺</contentC>
<contentD>疑是银河落九天</contentD>
</poem>

现在,定义 code6_4.css 文件。


@charset"gb2312";
name{display:"block";
font-size:"22pt";
color:blue;}
writer{display:"block";
color:red;}
contentA{display:"block";
color:"#FOF";}
contentB{display:"block";
color:rgb(100%,50%,50%);}
contentC{display:"block";
color:rgb(000,000,256);}
contentD{display:"block";
color:rgb(000,256,256);}

在 IE 中打开该 XML 文档,效果如图 6.4 所示。

图 6.4 color 属性的使用

在示例中,将前面介绍过的 color 属性的所有参数都使用了一遍。实际使用中,这此参


数基本是等效的(在色彩精度上有差异),读者可以根据自己的习惯灵活运用。

6.3.2 定义背景色

1. background 属性集
background 属性集用于对指定元素的背景进行设置,如色彩、图案等,见表 6-8。
2. 设置背景颜色
background-color 属性用于设置指定元素的背景颜色,其参数值有以下几种(与 color 属
性类似)。

·128·
第6章 层叠样式表 ·129·

表 6-8 background 属性集中常见的子属性

background 属性 说 明
background-color 用于对指定元素设置背景颜色
background-image 用于对指定元素设置背景图案
background-repeat 在背景图案小于指定元素的情况下,是否使用重复填充图案
background-attachment 用于指定设置的背景图案在元素滚动时是否一起滚动
background-position 用于指定背景图案的起始位置

1) “#RGB”
符号“#”加上表示 RGB 色彩的 3 位十六进制整数(如“#EB2”、“#FFF”等),其中
的 R、G、B 分别代表红色、绿色、蓝色,每个十六进制数字从 0 到 f 取值,数值越高表示
相应的色彩越浅,如白色就表示为“#FFF”。
2) “#rRGGBB”
符号“#”加上表示 RGB 色彩的 6 位十六进制整数(如“#0080FF”等),其中的每个
两位十六进制数从 00 到“ff”取值。同样是数值越高对应的色彩越浅,如白色就表示为
“#FFFFFF”。
3) RGB(RRR,GGG,BBB)
直接用 3 个 3 位十进制整数(如 RGB(010,128,256))表示,每个 3 位的十进制数从 000
到 256 取值。
4) RGB(r%,g%,b%)
直接用 3 个百分数表示(如 RGB(15%,20%,90%)),每个百分数取值从 0.0%到 100.0%,
数值越大表示对应色彩越浅。如白色就表示为 rgb(100.0%,100.0%,100.0%)。
5) 颜色名称
使用 red、blue、yellow 等表示颜色的英文字符指定元素的色彩。

3. 设置背景图案

background-image 属性用于设置指定元素的背景图案,其参数值用以下两种方式指定。
(1) background-image:定义背景图形。取值为 none、url,当取值为 none 时表示不用
图形作为背景,当取值为 url 时表示提供图形文件的 URL 地址。
(2) 直接的图像文件名称(如 image001.gif),这里是指和 CSS 文件在同一目录下的文件。

4. 设置背景图案重复方式

background-repeat 属性用于指定背景图案的重叠覆盖方式,其参数值有以下几个。
(1) repeat:使用背景图案完全填充元素大小的空间。
(2) repeat-x:使用背景图案在水平方向从左到右填充元素大小的空间。
(3) repeat-y:使用背景图案在竖直方向从上到下填充元素大小的空间。
(4) no-repeat:不使用背景图案重复填充元素。

·129·
·130· XML 实用教程

5. 设置背景图案滚动方式
background-attachment 属性用于背景图案的滚动方式,在需要设置的元素占用的空间
在浏览器中使用滚动条才能完整看到的时候,可以用该属性指定在文字元素滚动的同时,
背景图案是否一起滚动。
background-attachment 属性的参数值有以下两个。
(1) scroll:表示在文字页面滚动时,背景一起滚动。
(2) fixed:表示在文字页面滚动时,背景固定不滚动。
6. 设置背景图案起始位置
background-position 属性用于指定需要设置的背景图案的具体起始位置。
(1) top:表示背景图案位于指定元素的顶部。
(2) center:表示背景图案位于指定元素的中部。
(3) bottom:表示背景图案位于指定元素的底部。
(4) left:表示背景图案位于指定元素的左部。
(5) right:表示背景图案位于指定元素的右部。
background-position 属性还有两个子属性:
(1) background-position-horizontal 子属性用于控制背景图案的水平位置。
(2) background-position-vertical 子属性用于控制背景图案的竖直位置。

6.4 设置边界属性

在 CSS 中,提供了方框边界属性来对元素中文本的版面进行设置,它主要提供如下 3
种功能。
(1) 设置元素在文件中的位置;
(2) 在元素周围添加边框,并设置边框的样式、大小;
(3) 控制相邻元素的位置。
本节主要对 CSS 中的方框边界属性进行介绍。

6.4.1 设置边框属性

CSS 中设置边框属性的主要是 border-style,用于设置边框的样式。可取值为 none、


dotted、dashed、solid、double、groove、ridge、inset、outset,各取值的含义见表 6-9。
例如:
resume{border-style:solid dotted solid dotted}

当 border-style 被赋予 4 个不同的值时,表示对元素的 4 条边框设置不同的样式,这些


值依次是对顶、右、底、左边框进行设置。

·130·
第6章 层叠样式表 ·131·

表 6-9 border-style 各属性值的含义

border-style 属性 描 述
none 不显示边框,为默认值
dotted 点线
dashed 虛线
solid 实线
double 双线
groove 3D 陷入线
ridge 3D 山脊状线
inset 使页面有沉入感
outset 使页面有浮出感

border-width 属性用于设置边框的宽度。可取值为 thin、medium、thick 或指定尺寸,


各取值的含义见表 6-10。

表 6-10 border-width 各属性值的含义

border-width 属性 描 述
thin 细线边框
medium 中等边框
thick 粗线边框

例如:
resume
{ border-style:solid;
border-width:thick}
resume
{ border-style:solid dotted solid dotted;
border-width:thick 1px thick 1px}

和 border-style 相同,border-width 被赋予 4 个不同的值时,表示对元素的 4 条边框设


置不同的宽度,这些值依次是对顶、右、底、左边框进行设置。
border-color 属性用于设置边框的颜色。可取值为颜色名或 RGB 值,默认时边框和元
素的颜色相同,如:
resume
{ border-style:solid;
border-width:thick
border-color:red}
resume
{ border-style:solid dotted solid dotted;
border-width:thick 1px thick 1px
border-color:red blue yellow green}

·131·
·132· XML 实用教程

和 border-style 相同,border-color 被赋予 4 个不同的值时,表示对元素的 4 条边框设置


不同的颜色,这些值依次是对顶、右、底、左边框进行设置。如上例所示,对元素 resume
的顶、右、底、左边框设置的颜色分别为红、蓝、黄、绿。

6.4.2 设置填充属性

在边框属性设置完后,元素与边框的距离会过于接近,因此需要添加填充属性,使得
边框与元素之间的距离不会太靠近,从而提高显示时的美感。
要给元素与边框添加填充,可对以下属性进行设置:padding-top、padding-bottom、
padding-left、padding-right,依次表示给元素与顶、底、左、右边框添加填充,例如:
resume
{ border-style:solid;
border-width:thick
border-color:red
padding-top:1em
padding-bottom:1em
padding-left:50%
padding-right:50%
}

这个例子给元素与边框添加填充符,在元素与顶边框、底边框之间添加宽度为元素宽
度一倍的填充,在元素与左边框、右边框之间添加宽度为元素宽度的 50%的填空。从上面
的例子可以看到为元素与边框添加填充符时可以是具体的尺寸值,也可以是元素的父元素
宽度的百分比。此外,若添加填充符 padding-top、padding-bottom、padding-left、padding-right
四个属性取值一样时,可缩写成只设置 padding 的属性。
resume
{ border-style:solid;
border-width:thick
border-color:red
padding-top:1em
padding-bottom:1em
padding-left:1em
padding-right:1em
}

可简写为
resume
{ border-style:solid;
border-width:thick
border-color:red
padding:1em
}

·132·
第6章 层叠样式表 ·133·

6.4.3 设置大小属性

在 CSS 中设置边框大小的属性为 width 和 height。取值为 auto、指定大小或父元素宽


度的百分比。当 width 和 height 取值为 auto 时,表示根据元素大小自动调整 width 和 height
的取值。

6.4.4 设置定位属性

在默认的条件下,相同父元素的块级元素是一个紧挨一个显示的,因此需要设置定位
属性来控制相邻元素的位置。在 CSS 中,可使用 float 和 clear 来控制相邻元素的位置。定
位属性控制相邻元素位置的含义见表 6-11。

表 6-11 定位属性的含义

定位属性 描 述

float 设置文本相对于元素的位置。取值为:left、right、none

left 下一个文本位于元素的左边

right 下一个文本位于元素的右边

none 默认值,下一个文本紧接着显示出来

clear 设置浮动元素相对于元素的位置。取值为:left、right、none、both

left 浮动元素位于元素的左边

right 浮动元素位于元素的右边

both 浮动元素位于元素的两侧

6.4.5 设置页面边界属性

在默认情况下,元素的页边距为 0,在 CSS 中,设置页边距的属性有:margin-top、


margin-bottom、margin-left、margin-right,依次是对元素的顶部、底部、左边、右边添加页
边距。设置页边距可以使用指定大小的数值,例如:
resume
{ margin-top:3em
margin-bottom:3em}

设置 resume 的顶部页边距和底部页边距,其宽度为文本宽度的 3 倍,此外,还可以用


父元素宽度的百分数来设置页边距,例如:
resume
{ margin-top:50%
margin-bottom:50%}

设置 resume 的顶部页边距和底部页边距,其宽度为父元素宽度的 50%。

·133·
·134· XML 实用教程

6.5 CSS2 新增功能

CSS2 由 W3C 在 1998 年出版,它对 XML 和 HTML 文档格式化的功能比以前的 CSS1


更强大。完整的 CSS2 规范可参见 http://www.w3.org/TR/REC-CSS2/。
CSS2 能使人们更加准确地选择和格式化文档中的元素,可把不同的样式应用于在不同
媒体上出现的文档。对分页媒体的支持也获得了极大的改进,从而可对页面的分页符实现
更加强大的控制。CSS2 不仅对块和内联框中的元素格式化,也对表格中的元素格式化。可
自动地对顺序、列表加以编号和缩进排印。对非西方语言提供了更多的支持。并且,第一
次应用声觉样式来指定文档不是以何种方式显示,而是如何让人阅读。下面简单介绍一下
CSS2 的几个新增功能。

6.5.1 @规则

CSS2 中提供@规则用来完成某项任务,而不是选择元素或把一些样式应用于这一元
素。在 CSS2 中提供的@规则有 5 种,分别如下。

1. @page
@page 规则选择页面框,把样式应用于页面。通过它可以设计页面框大小、页面区域
和页边距等。@page 规则无法理解以 em 和 ex 为单位的尺寸,但对于所有的其他度量单位
是可以解析接受的。用于设置页边距的百分数也是总页面框的百分数。页边距可为负值,
表示把内容放在通常应用程序或打印机可访问的区域之外。在大多数情况下,只保留可见
或可打印区域内的信息。

2. @import
@import 规则把指定的外部样式单嵌入到现有的样式单中。这样可以根据多个较小、
较容易理解的片断生成大样式单。导入的样式单使用.css 扩展名。例如,下面的规则导入
mycss.css 文件:
@import uri(mycss.css);

3. @media
@media 规则把用于某种媒体的特性组合起来成为样式规则。CSS2 可为显示在不同媒
体中的相同元素指定不同的样式。CSS2 中可以将只准备用于一种媒体的多个样式规则放入
一条指明媒体名的@media 规则中。在一篇文档中,@media 规则的数量与指定的媒体类型
一样多。
CSS2 识别如下 10 种媒体类型。
(1) all:所有的设备。
(2) aural:语音合成器。
(3) braille:用于有视觉障碍的盲文反馈设备。
(4) embossed:分页盲文打印机。

·134·
第6章 层叠样式表 ·135·

(5) handheld:PDA 和其他掌上设备,如 Windows CE 掌上计算机、Palm Pilot 等。


(6) print:所有的打印、不透明材料。
(7) projection:幻灯片放映,可以直接从计算机上投影或打印在幻灯片上。
(8) screen:点位图显示器。
(9) tty:使用位置固定的、单色字符栅格的老式 PC 显示器。
(10) tv:电视类设备。

4. @font-face
@font-face 规则用来描述样式单中其他地方使用的字样。可提供字体名、URL 和有关
字体点阵的信息。@font-face 规则还指定如何根据设计者需要指定的字体来为文档选择
字体。

5. @charset
该规则用于定义样式单使用的字符集。指定编写样式单的字符集有 3 种方式,并且以
如下的顺序选择优先级:
(1) 网页头部标识元素 meta 中的 Content 属性参数 charset;
(2) @charset 规则;
(3) 与文档相关联的特性和属性。
@charset 规则必须出现在文档的最前,前面不能有任何其他字符。

6.5.2 新增属性

CSS2 扩充了许多新的属性,使得对于版面的设置更美观,更合理。下面对其中几个进
行简单介绍。
1. 字体属性
在 CSS2 中,对字体属性的设置主要增加了以下功能。
(1) font-size-adjust:设置或检索用于对象中文本的字体名称序列是否强制使用同一尺
寸,其取值分为 none 或数字,当取值为 none 时允许字体序列中每一字体遵守它自己的尺
寸,当取值为数字时表示为字体序列中所有字体强迫指定同一尺寸。
(2) font-stretch:设置或检索用于对象中文本的文字是否有横向的拉伸变形。
(3) text-shadow:设置或检索对象中文本的文字是否有阴影及模糊效果。
2. 文本属性
在 CSS2 中,对文本属性的设置主要增加了以下功能。
(1) direction:设置文本流的方向,表示文本流是从左到右还是从右到左的。
(2) unicode-bidi:在同一个页面里存在从不同方向读进的文本显示,主要和 direction
一起使用。
3. 其他属性
CSS2 中新增了定位属性检索对象的定位方式,具体有如下 6 种。
(1) position:检索对象的定位方式。

·135·
·136· XML 实用教程

(2) z-index :设置对象的层叠顺序。


(3) top:设置对象与最近一个定位的父对象顶部相关的位置。
(4) right:设置对象与最近一个定位的父对象右边相关的位置。
(5) bottom:设置对象与最近一个定位的父对象底边相关的位置。
(6) left:设置对象与最近一个定位的父对象左边相关的位置。
此外,CSS2 还增加了轮廓属性,可用于设置对象外线条轮廓的颜色、样式、宽度。

6.5.3 其他伪类

CSS 新增了下列伪类,使得在页面设置和排版方面的功能更加丰富了。
(1) focus:设置对象在成为输入焦点(该对象的 onfocus 事件发生)时的样式表属性。
(2) first-child:设置对象(Selector1)的第一个子对象(Selector2)的样式表属性。
(3) first:设置页面容器第一页使用的样式表属性(用于@page 规则)。
(4) left:设置位于装订线左边的所有页面使用的样式表属性(用于@page 规则)。
(5) right:设置位于装订线右边的所有页面使用的样式表属性(用于@page 规则)。
(6) lang:设置对象使用特殊语言的内容样式表属性。
由于篇幅关系, 关于 CSS2 的新增功能不能一一介绍, 其他相关内容读者可参考 http://www.w
3.org/TR/REC-CSS2/。

6.6 综 合 实 例

1. 实例简介
这里使用 CSS,将存在 XML 文档中的一段文字以指定的格式显示出来。同时,为整
个页面设置了一张图片。
2. 实例实现
(1) 打开一个文本编辑器,在其中输入如例 6.5 的 XML 文档和 CSS 样式文件。
(2) 将文件分别存为 code6_5.xml 和 code6_5.css。
(3) 用 IE 打开 XML 文件,查看没有使用 CSS 的文档效果。注释命令如下:
<!--先将链接 CSS 样式表的指令语句屏蔽起来。
-->

(4) 将 code6_5.xml 文档中的注释标记去掉,保存文件。


(5) 再用 IE 查看该文件,显示使用了 CSS 后的效果。
【例 6.5】 文档 code6_5.xml 使用名为 code6_5.css 的样式文件显示。
<?xml version="1.0" encoding="gb2312"?>
<?xml-stylesheet type="text/css" href="code6_5.css"?>
<paper>
<title>李白</title>
<number>(701-762)</number>
<syllabus>作者简介</syllabus>

·136·
第6章 层叠样式表 ·137·

<picture/>
<commentary> 李白(701-762),字太白。祖籍陇西成纪,隋末迁居中亚的碎叶城。
李白一生绝大部分时间是在玄宗统治的盛唐即开元、天宝年间度过的。在李白流
传下来的九百多篇诗中,大部分鲜明的表现了他对封建贵权的轻蔑,对腐朽政治
的揭露和对人民疾苦的同情,对祖国壮丽山川的赞美。同时也由于封建统治思想
的严重影响,李白的不少作品往往流露道家人生如梦、及时行乐和儒家“ 穷则
独善其身”的消极情绪。李白是我国唐代与杜甫并称的伟大诗人,他的诗歌各体
俱佳,而其中又以七言歌行与七言绝句最为擅长。李白代表作《 望庐山瀑布 》。
</commentary>
<resume>日照香炉升紫烟,
遥看瀑布挂前川。
飞流直下三千尺,
疑是银河落九天。
作者 李白
</resume>
</paper>

将 CSS 样式表文件命名为 code6_5.css,并在 code6_5.xml 里添加<?xml-stylesheet


type=“text/css” href=“code6_5.css”?>。
code6_5.css 的具体内容如下:
title{
font-size:24pt;
font-weight:bold;
color:blue;
display:block;
margin-top:5pt;
text-align:center;
}
number{
font-family:宋体
font-size:15pt;
color:red;
display:block;
font-weight:bold;
text-align:center;
}
resume{
border-left:thin dotted yellow;
border-right:thin dotted yellow;
border-top:thin outset green;
border-bottom:thin outset green;
font-size:10pt;
font-style:italic;
display:block;
text-align:center;
font-weight:bold;
color:fuchsia;
margin-left:20pt;
margin-right:20pt;
line-height:1.5em

·137·
·138· XML 实用教程

}
syllabus{
display:"block";
font-style:italic;
font-weight:bold;
font-size:"15pt";
font-family:"楷体_gb2312";
}
picture {
background-image: url(PUBU.GIF);
background-repeat: no-repeat;
background-position: center;
float:left;
width: 240px;
height: 130px;
}
commentary{
font-size:12pt;
font-weight:bold;
font-style:italic;
text-align:right;
color:orange;
text-indent: 0.75cm;
}

在 IE 中打开该 XML 文档,效果如图 6.5 所示。

图 6.5 综合实例的执行效果

3. 实例说明
本实例的主要目的是让读者熟悉 CSS 的使用方法和特点,并在与未使用样式表的 XML
文档作对比的过程中,了解 CSS 的强大功能。在实例中,综合运用了字体样式控制、字体
大小和字型控制、元素定位技术以及图片设置技术等,使得提取出来的 XML 信息重新组
织成一幅漂亮的画面。读者可以通过这个实例,对本章介绍的 CSS 的基本结构有更为形象
的认识。

·138·
第6章 层叠样式表 ·139·

6.7 小 结

本章从 CSS 的概念和背景知识入手,先让读者对 CSS 技术的产生和作用建立起较深刻


的印象。再通过建立具体的 CSS 样式文件,介绍 CSS 的基本结构和语法特点。最后,通过
一个完整的对比示例让读者真正建立起对 CSS 强大功能的信心。
在文字样式的处理方面,本章也有相应的内容来介绍 CSS 的强大功能。在实际的样式
表运用中,文字的样式设定是很常见的一个页面效果增强手段,特别在中文页面的文档格
式中,文字的样式更是影响整个版面效果的关键因素。因此,熟悉此相关属性的用法对于
设计一个好的 CSS 是很重要的。
在色彩设置方面,本章也用了相当长的篇幅进行了详尽的介绍。在多媒体时代到来之
前,色彩就在信息领域里发挥着非常重要的作用。在今天成千上万的各类网站中,没有色
彩和图案修饰的页面是很难想象的。在无数类似的站点之中,好的美工设计也是能否吸引
人们注意的重要因素。当然,好的设计离不开丰富的艺术细胞,但将那些动人的构想变为
现实,终归是页面设计的技术问题。在本章中,常用的有关色彩设置的属性及其参数都已
经介绍了,一些高级的应用也都是由这些基础的语句组成的,读者可以在实践中进一步熟
悉这些属性的用法。

6.8 习 题

1. 什么是 CSS?CSS 文件的特点有哪些?


2. 如何在 XML 文档中引用 CSS 样式文件?
3. 如何设置字体的风格、大小和亮度?试制作 CSS 文件设置字体风格、大小和亮度。
4. 如何设置 CSS 样式文件中样式关键字的属性和属性值?
5. 制作由 CSS 样式文件设计的全班同学通讯录网页。

·139·
第 7 章 XML 数据源对象

教学提示:XML 文档是一个层状结构的信息体,XML 比 HTML 具有更大的灵活性,


侧重于如何结构化地描述信息,但是它不能代替 HTML。实际上,XML 与 HTML 配合,
能够很好地展示和更新信息。XML 可以作为数据源,XML 的元素和属性可以与 HTML 的
元素绑定,使得 XML 中的信息能够通过 HTML 元素展现出来。本章介绍 XML 作为数据
源对象的相关技术,数据岛的概念、数据绑定的方法、支持 DSO 的 HTML 标记和 XML 文
件的嵌入,XML 数据源对象的综合运用。
教学目标:理解数据岛和数据源对象的概念,掌握数据绑定的方法,熟悉 HTML 文档
中嵌入 XML 数据的方法,了解支持 DSO 的 HTML 元素,掌握 HTML 与 XML 结合的方法,
学会综合运用 DSO。

7.1 数据岛、XML 数据源对象和数据绑定

从数据库这个术语的本质来看,XML 文档就是数据库,它是数据的集合。从 XML 的


结构来看,XML 文档是层状数据库系统,在某一层的局部看来,相当于关系型数据库,即
二维表。因此,XML 文件可以作为网页中数据的来源,层状的系统结构,又使 XML 有着
优越性,适合信息的层次分类。在 J2EE 和.NET 两大体系结构中广泛采用 XML 文件作为
应用系统各项参数的配置文件。
XML 文档所包含的信息可以被提取,并且在 HTML 页面中予以显示,数据岛、XML
数据源对象和数据绑定是 XML 信息显示的几个重要概念。

7.1.1 数据岛和 XML 数据源对象

XML 数据岛(Data Island)是指嵌入 HTML 文档中的扩展标记信息(XMI)。HTML 网页


就像是一个大海,在其中适当的位置采用一定的 HTML 标记导入 XML 元素或属性的值。
XML 数据岛技术是 IE 5.0 以上版本用于绑定和显示 XML 数据的一种特定方法。HTML 文
档中的 XML 数据岛来自于 XML 文件。
XML 数据源对象(Data Source Object,DSO)允许开发人员连接到结构化 XML 数据,
并用动态 HTML 的数据绑定机制将它提供给 HTML 页面。XML DSO 为开发人员提供了构
造下一代丰富、灵活的 Web 应用程序技术。开发人员使用 XML DSO,可以为网页提供结
构化数据,并且用 XML 对象模型计算、更新、存储数据。
DSO 从一个外部 XML 文件或嵌入 Web 页面的 XML 中分析提取 XML 数据,然后使
用 JavaScript 操作这些数据。为了初始化 XML DSO 对象,需要使用<OBJECT>标记。用于
第7章 XML 数据源对象 ·141·

XML DSO 的 CLLASID 是:


CLLASID:550dda30-0541-11d2-9ca9-0060b0ec3d39

这个 ID 唯一标识 XML DSO。下面的代码在一个 Web 页面中初始化一个名为 myID 的


DSO 对象:
<OBJECT ID="myID"
CLLASID="CLLASID:550dda30-0541-11d2-9ca9-0060b0ec3d39"></OBJECT>

7.1.2 数据绑定

1. 数据绑定的作用和意义
要在 HTML 网页中使用 XML 文档中的数据,必须进行数据绑定(Data Binding)。数据
绑定就是将外部数据,如 XML 文档、数据库或使用 OLE-DB 链接的外部数据集成到 HTML
文件中,然后使表格等 HTML 元素绑定 XML 文档元素,从而实现 XML 数据在 HTML 页
面中的显示。HTML 绑定意味着和一个 HTML 元素关联的值是由一个特定来源提供的。绑
定 HTML 元素时,更新其值会造成关联结点的文本同时更新。
当 IE 打开包含 XML 数据岛的 HTML 页面时,其内置的 XML 解析器读取并分析 XML
文档,同时创建一个名为数据源对象 DSO 的 ActiveX 对象,它可以存储或缓存 XML 数据,
并提供对这些数据的访问。DSO 把 XML 数据当成记录集(recordset)存储,XML 文档包含
树状的数据库,每一个分支都有一系列类型相同的记录元素,每一个记录元素又可包含嵌
套(分支)的记录。当 XML 文档包含很多记录时,可以使用分页功能一次显示一组记录。
数据绑定体系结构包括 4 个组成部分:数据源对象(Data Source Object)、数据显示对象
(Data Consumers)和两个代理器(Binding Agent 与 Table Repetition Agent)。数据源对象向网
页提供数据,数据显示对象就是显示数据的 HTML 元素,代理器则用来保证前两者的工作
同步。
2. 使用表格时数据绑定的方法
数据控件主要负责管理数据,并为 HTML 元素提供数据,而 HTML 元素则将数据显
示在屏幕上。为了将数据源与 HTML 元素绑定,需要进行以下操作:
(1) 建立 HTML 文档。确定所要进行的信息展示或处理工作,依照程序员喜欢的界面
风格建立好一个 HTML 文档。
(2) 加入<XML>标记。在 HTML 文档中加入<XML>标记,从而在 HTML 中嵌入 XML
格式的数据,或者引用外部的 XML 格式的文件。设置<XML>标记的 id 属性,可以通过脚
本访问这些数据,也可以把它与<table>捆绑到一起。还可以设置<XML>的 src 属性,导入
外部的 XML 格式数据。
(3) 建立表格。根据所要展示的字段个数,设置表格的表头和表体,表体中建立一
个空白行。
(4) 定义数据源 datasrc。在表格标记<table>中加入 datasrc 属性,并赋值为数据源的
名称,这样表格就成为包含数据的数据控件。注意,在数据源名称前必须要加“#”。
(5) 确定被绑定的字段 datafld。在表格要显示数据的各列标记<td>中加入<span>、<div>

·141·
·142· XML 实用教程

或其他支持 DSO 的标记,给这个标记加入 datafld 属性,属性值就是所要显示的字段名,


这些字段是数据控件管理的数据中的列名,即 XML 文档中的元素或属性名。
【例 7.1】 HTML 表格中绑定显示 XML 文档内容的简单实例,代码如源程序 code7_1.htm
所示。
<HTML>
<HEAD><title>使用表格绑定 XML</title></HEAD>
<BODY>
<XML id="XMLdata" src="code7_1.XML"></XML>
<center><b><font size="4">HTML 表格中绑定显示 XML 文档内容
</font></b></center>
<table datasrc="#XMLdata" border="1" cellpadding="5" align="center">
<thead>
<th>customerID</th>
<th>order_date</th>
<th>order_status</th>
<th>items</th>
</thead>
<tr>
<td><span datafld="customerID"></span></td>
<td><span datafld="order_date"></span></td>
<td><span datafld="order_status"></span></td>
<td><span datafld="items"></span></td>
</tr>
</table>
</BODY>
</HTML>

被例 7.1 引用的 XML 文件为 code7_1.XML。


<?XML version="1.0" encoding="gb2312" ?>
<orders>
<order>
<customerID>c0500069</customerID>
<order_date>20050517</order_date>
<order_status>pending</order_status>
<items>
<item>
<bookID>001</bookID>
<quantity>10</quantity>
<item_status>pending</item_status>
</item>
</items>
</order>
<order>
<customerID>c500701</customerID>
<order_date>20050712</order_date>
<order_status>pending</order_status>
<items>
<item>
<bookID>002</bookID>

·142·
第7章 XML 数据源对象 ·143·

<quantity>30</quantity>
<item_status>pending</item_status>
</item>
<item>
<bookID>003</bookID>
<quantity>20</quantity>
<item_status>pending</item_status>
</item>
</items>
</order>
</orders>

其显示结果如图 7.1 所示。

图 7.1 使用表格绑定 XML 的结果

其中 items 栏中无内容,这将在后面的章节讨论。表格能够显示 XML 的所有元素,自


身隐含着循环,有多少条记录,就有多少行的表格。如果要显示当前的元素(记录),可以
直接用<div>或<span>标记,而无须表格。
3. 只显示单条记录时数据绑定的方法
以上说明了表格绑定 XML DSO 的步骤。如果是单条记录的显示,则不必采用表格,
选择合适的 HTML 标记即可,每一个绑定的 HTML 元素都要同时确定数据源(datasrc)和绑
定的字段(datafld)。
【例 7.2】 显示单条记录时的绑定方法,代码如源程序 code7_2.htm 所示,被引用的 XML
文件仍为 code7_1.XML。
<HTML>
<HEAD> <title>显示单条记录时的绑定方法</title> </HEAD>
<BODY>
<XML id="XMLdata" src="code7_1.XML"></XML>
<center><b><font size="3">只显示单条记录时数据绑定的方法
</font></b></center>
customerID: <span datasrc="#XMLdata"
datafld="customerID"></span><br>
order_date: <span datasrc="#XMLdata"
datafld="order_date"></span><br>
order_status: <span datasrc="#XMLdata"
datafld="order_status"></span><br>
</BODY>
</HTML>

·143·
·144· XML 实用教程

其显示结果如图 7.2 所示。

图 7.2 显示单条记录的结果

7.1.3 XML 与 HTML 结合的优势

1. 数据可以在本地处理
XML 分析器可以在读取数据后,将它递交给本地应用程序(例如浏览器)进一步查看或
处理。数据也可以由使用 XML 对象模型的脚本或其他编程语言来做各种处理。
2. 提供给客户端结构化数据视图
传递到客户端的数据形成本地数据集,可以用多种方式表示。如程序员可以根据需要
和配置等因素,以视图的形式动态地表现给浏览器。
3. 集成不同来源的结构化数据
在服务器端可以集成来自不同后台数据库和其他多种应用程序的数据,使该数据以
XML DSO 的方式传递给客户端或者其他服务器,做进一步聚合、处理和分布。由于 XML
是可扩展和自描述的,所以它可以用于描述来自不同数据库或应用程序的数据,不需要数
据的内置描述,也能够接收和处理数据。
4. 通过粒度更新来提高性能
XML 允许粒度更新,开发人员不必在每次有改动时都发送整个结构化数据集。当数据
更新时,只需要刷新中间显示数据的部分,而页面的其他部分不变,就好像没有刷新一样,
显示效果更好。因为只下载了数据部分,网页的其他部分没有重复下载,浏览速度更快。
如果灵活应用,还可以实现无刷新搜索和分页等功能。
5. 网页界面修改不易破坏数据
网页制作者可以灵活地改变页面风格而无须担心破坏数据显示代码,因为数据和页面
是分离的,相关代码也很少。

7.2 支持数据绑定的 HTML 元素

XML 与 HTML 相结合能够完满地显示信息和处理信息,但是必须清楚哪些 HTML 元


素是支持 XML DSO 数据绑定的。
将 HTML 元素和 XML 文档绑定时,有 3 点需要注意。首先,并非每个 HTML 元素都

·144·
第7章 XML 数据源对象 ·145·

能绑定;其次,并非每个 HTML 元素都能更新数据岛;第三,并非每个 HTML 元素都将


数据岛的结点文本呈现为 HTML。
可以绑定的 HTML 元素见表 7-1,并指出对象是否可以更新数据岛以及数据岛的结点
文本是否能呈现为 HTML。
可供绑定的 HTML 元素共分为两大类:单值对象(Single-valued Consumer)和表对象
(Tabular Consumer)。单值对象显示 DSO 提供的当前记录的某一个域,而表对象中的每行元
素则分别对应一条记录中不同的域,并以此为模板重复显示数据集中的每条记录。数据显
示对象既可以在设计时绑定到 DSO,也可以在运行时动态绑定。

表 7-1 支持 DSO 的 HTML 元素

HTML 元素 可 更 新 呈现 HTML

a 否 否
applet 是 否
button 否 是
div 否 是
frame 否 否
iframe 否 否
img 否 否
input type=“button” 否 是
input type=“checkbox” 是 否
input type=“hidden” 是 否
input type=“password” 是 否
input type=“radio” 是 否
input type=“text” 是 否
legend 否 是
marquee 否 是
select 是 否
span 否 是
table 否 是
textarea 否 否

7.3 将 XML 文件数据嵌入 HTML

在 HTML 中,可以加入<XML>标记,从而在 HTML 页面中嵌入 XML 格式的数据,


或者引用外部的 XML 格式的文件。设置<XML>标记的 id 属性后,可以通过脚本访问这些

·145·
·146· XML 实用教程

数据,也可以把它与<table>捆绑在一起。还可以设置<XML>的 src 属性,导入外部的 XML


格式数据。

7.3.1 内部嵌入 XML

在 HTML 文档内部嵌入 XML 较为简单,只需要把 XML 文档的内容嵌入到 HTML 文


档中,以<XML id=“自定义 ID 号”>开始,以</XML>结束。嵌入的位置可以任意,一般
在 HTML 文档之前或<head>标记之后,<body>标记之前。
【例 7.3】 将例 7.1 改写成内部嵌入 XML 的 HTML 文档,显示 XML 文档内容,代码如
源程序 code7_3.htm 所示。
<HTML>
<HEAD><title>使用表格绑定内嵌 XML</title></HEAD>
<XML id="XMLdata">
<?XML version="1.0" encoding="gb2312" ?>
<orders>
<order>
<customerID>c0500069</customerID>
<order_date>20050517</order_date>
<order_status>pending</order_status>
<items>
<item>
<bookID>001</bookID>
<quantity>10</quantity>
<item_status>pending</item_status>
</item>
</items>
</order>
<order>
<customerID>c500701</customerID>
<order_date>20050712</order_date>
<order_status>pending</order_status>
<items>
<item>
<bookID>002</bookID>
<quantity>30</quantity>
<item_status>pending</item_status>
</item>
<item>
<bookID>003</bookID>
<quantity>20</quantity>
<item_status>pending</item_status>
</item>
</items>
</order>
</orders>
</XML>
<BODY>
<center><b><font size="3">HTML 表格中绑定显示 XML 文档内容
</font></b></center>

·146·
第7章 XML 数据源对象 ·147·

<table datasrc="#XMLdata" border="1" cellpadding="5" align="center">


<thead>
<th>customerID</th>
<th>order_date</th>
<th>order_status</th>
<th>items</th>
</thead>
<tr>
<td><span DATAFLD="customerID"></span></td>
<td><span DATAFLD="order_date"></span></td>
<td><span DATAFLD="order_status"></span></td>
<td><span DATAFLD="items"></span></td>
</tr>
</table>
</BODY>
</HTML>

其显示结果同例 7.1,如图 7.1 所示。

7.3.2 使用外部的 XML 文件

使用外部的 XML 文件时,只需要以<XML id=“自定义 ID 号”src=“外部 XML 文件路径


及文件名”>开始,以</XML>结束。例 7.1 即是使用的外部 XML 文件,这里不必再举例。
但是如图 7.1 所示中 items 不显示数据,这是因为 items 具有次级元素,形成表中套表。要
解决这个问题,应采用分层嵌入的方法。先将表头改成“一栏多列”,然后在需要显示 items
的格内嵌套一个 3 列的表。
【例 7.4】 对例 7.1 的改进,代码如源程序 code7_4.html 所示。
<HTML>
<HEAD><title>使例 7.1 中 items 栏目值显示</title></HEAD>
<XML id="XMLdata" src="code7_1.XML"></XML>
<body>
<center><b><font size="3">对例 7.1 的改进</font></b></center>
<table datasrc="#XMLdata" border="1" cellpadding="5" align="center">
<thead>
<th>customerID</th><th>order_date</th><th>order_status</th>
<th>
<table border="1" width="100%" id="table2">
<tr>
<td colspan="3">
<p align="center"><b>items</b></td>
</tr>
<tr>
<td>bookID</td>
<td>quantity</td>
<td>item_status</td>
</tr>
</table>
</th>
</thead>

·147·
·148· XML 实用教程

<tr>
<td><span DATAFLD="customerID"></span></td>
<td><span DATAFLD="order_date"></span></td>
<td><span DATAFLD="order_status"></span></td>
<td>
<table datasrc="#XMLdata" datafld="items">
<tr><td><div datafld="$text"></div></td></tr>
</table>
</td>
</tr>
</table>
</BODY>
</HTML>

代码中在需要显示 items 值的单元格内用了“$text”数据字段,这是因为 items 是 3 个


值构成的。使用“$text”字段能够将所指定的字段(结点)内所有元素值都显示出来,以空
格分开。经过改进后的显示结果如图 7.3 所示。

图 7.3 使例 7.1 中 items 栏目值显示

改进后的结果仍不如人意,c0500069 号客户只有一个 item,但没有对齐;c500701 号


客户有两个 item,却被排在一行。因此,还需要改进。
【例 7.5】 对例 7.4 进行改进,代码如源程序 code7_5.htm 所示。
<HTML>
<HEAD><title>改进例 7.4 中 items 栏目值的显示</title></HEAD>
<BODY>
<XML id="XMLdata" src="code7_1.XML"></XML>
<h2 align="center"><font size="3">对例 7.4 的改进</font></h2>
<table datasrc="#XMLdata" border="1" align="center">
<thead>
<th>customerID</th><th>order_date</th>
<th>order_status</th><th>items</th>
</thead>
<tr>
<td><span datafld="customerID"></span></td>
<td><span datafld="order_date"></span></td>
<td><span datafld="order_status"></span></td>
<td>
<table datasrc="#XMLdata" datafld="items">

·148·
第7章 XML 数据源对象 ·149·

<tr><td>
<table border="1" datasrc="#XMLdata" datafld="item">
<thead>
<th>bookID</th>
<th>quantity</th>
<th>item_status</th>
</thead>
<tr>
<td><span datafld="bookID"></span></td>
<td><span datafld="quantity"></span></td>
<td><span datafld="item_status"></span></td>
</tr>
</table>
</td></tr>
</table>
</td>
</tr>
</table>
</BODY>
</HTML>

其显示如图 7.4 所示。

图 7.4 改进例 7.4 中 items 栏目值的显示

上例代码中采用 3 层嵌套的表格实现数据的显示。外层表格(第一层)和各级内嵌表格
的 数 据 源 都 定 义 为 datasrc=“#XMLdata” , 内 嵌 的 第 二 层 表 格 的 具 体 数 据 定 义 为
datafld=“items”,再往里嵌套的第三层表格数据指定为 datafld=“item”,这样 item 的次级元
素的值就能对应到具体的单元格了。对于多元素的单元格,应当在 td 元素内部嵌套一个
表格。

7.4 结合脚本语言的 XML

XML 数据源对象能视为 ADO Recordset 对象,可以结合脚本语言,操作记录集,能方


便地编制出展现数据的界面。

·149·
·150· XML 实用教程

7.4.1 HTML 中的 XML 数据岛记录编辑与添加

XML 对象赋予 ID 号后,这个 ID 所代表的数据源对象具有若干方法。下面给出更多使


用 JavaScript 操作 XML DSO 的方法。
movePrevious():指向前一个数据项。
moveNext():指向下一个数据项。
moveFirst():指向第一个数据项。
moveLast():指向最后一个数据项。
addNew():增加一个数据项。
对于 VBScript,使用时只需要把上述方法后面的括号“()”去掉即可。
指向 DSO 的 RecordSet 对象还有以下属性。
EOF:这个属性用来检测是否已经到达数据记录的底部。
Absoluteposition:获取目前 XML 元素的索引编号。
Recordcount:获取拥有多少个 XML 元素。
【例 7.6】 HTML 中的 XML 数据岛记录编辑与添加,代码如源程序 code7_6.htm 所示。
<HTML>
<HEAD><title>HTML 中的数据岛中的记录集</title></HEAD>
<BODY>
<XML id="XMLdata" src="code7_6.XML"></XML>
<center><b><font size="3">HTML 中的 XML 数据岛记录编辑与添加
</font></b></center><hr>
书名:<input type=text datasrc="#XMLdata" datafld="title"
size="53"><br>
类别:<input type=text datasrc="#XMLdata" datafld="bookcategory"
size="22">&nbsp;&nbsp;&nbsp;&nbsp;
书号:<input type=text datasrc="#XMLdata" datafld="ISBN"
size="18"><br>
作者:<input type=text datasrc="#XMLdata" datafld="author"
size="53"><br>
出版社:<input type=text datasrc="#XMLdata" datafld="publisher"
size="53"><br>
定价:<input type=text datasrc="#XMLdata" datafld="price"
size="15"><span lang="zh-cn">元&nbsp;
</span>&nbsp;&nbsp;&nbsp;&nbsp;
剩余数量:<input type=text datasrc="#XMLdata" datafld="remain"
size="15">
<hr>
<input id="first" type="button" value="<<第一条"
onclick="XMLdata.recordset.moveFirst">
<input id="prev" type="button" value="<上一条"
onclick="XMLdata.recordset.movePrevious">
<input id="next" type="button" value="下一条>"
onclick="XMLdata.recordset.moveNext">
<input id="last"type="button" value="最后一条>>"
onclick="XMLdata.recordset.moveLast">

·150·
第7章 XML 数据源对象 ·151·

<input id="Add" type="button" value="添加新"


onclick="XMLdata.recordset.addNew">
</BODY>
</HTML>

例 7.6 中引用的 XML 文件为 code7_6.XML。


<?XML version="1.0" encoding="gb2312"?>
<books>
<book id="0001" bookcategory="文艺" amount="150" remain="80"
discount="8.5">
<title>三国演义</title>
<author>罗贯中</author>
<publisher>文艺出版社</publisher>
<ISBN>0-764-58007-8</ISBN>
<price>80</price>
</book>
<book id="0002" bookcategory="文艺" amount="300" remain="180"
discount="8.7">
<title>红楼梦</title>
<author>曹雪芹</author>
<publisher>三秦出版社</publisher>
<ISBN>7805468397</ISBN>
<price>22</price>
</book>
<book id="0003" bookcategory="文艺" amount="200" remain="175"
discount="8.5">
<title>西游记(上下册)</title>
<author>吴承恩</author>
<publisher>人民文学出版社</publisher>
<ISBN>7020008739</ISBN>
<price>40.12</price>
</book>
<book id="0004" bookcategory="文艺" amount="300" remain="192"
discount="8.7">
<title>水浒传(上下册)</title>
<author>吴承恩</author>
<publisher>时代文艺出版社</publisher>
<ISBN>7538714014</ISBN>
<price>40.85</price>
</book>
<book id="0065" bookcategory="文学" amount="120" remain="86"
discount="8.0">
<title>外国文学史(亚非卷)</title>
<author>朱维之</author>
<publisher>南开大学出版社</publisher>
<ISBN>7-310-01122-8</ISBN>
<price>20</price>
</book>
<book id="0076" bookcategory="文学" amount="130" remain="84"
discount="8.0">

·151·
·152· XML 实用教程

<title>20 世纪欧美文学简史</title>
<author>李明滨</author>
<publisher>北京大学出版社</publisher>
<ISBN>7-301-04616-2</ISBN>
<price>21.8</price>
</book>
<book id="0098" bookcategory="文学" amount="140" remain="76"
discount="7.0">
<title>西方文艺理论名著教程(上)</title>
<author>胡经之</author>
<publisher>北京大学出版社</publisher>
<ISBN>7-301-00649-7</ISBN>
<price>24</price>
</book>
<book id="0012" bookcategory="文学" amount="210" remain="60"
discount="8.5">
<title>西方文艺理论名著教程(下)</title>
<author>胡经之</author>
<publisher>北京大学出版社</publisher>
<ISBN>7-301-00179-7</ISBN>
<price>23</price>
</book>
<book id="0036" bookcategory="文学" amount="100" remain="80"
discount="8.3">
<title>中国文学理论批评史教程</title>
<author>张少康</author>
<publisher>北京大学出版社</publisher>
<ISBN>7-301-04091-1</ISBN>
<price>25</price>
</book>
<book id="0018" bookcategory="计算机" amount="200" remain="100"
discount="8.2">
<title>计算机导论</title>
<author>丁跃潮等</author>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<price>19.7</price>
</book>
<book id="0218" bookcategory="计算机" amount="400" remain="300"
discount="8.5">
<title>程序设计基础</title>
<author>张杰敏主编</author>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-012652-4</ISBN>
<price>17.6</price>
</book>
<book id="0318" bookcategory="计算机" amount="100" remain="60"
discount="8.0">
<title>数据结构与算法</title>
<author>王晓东编</author>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-013204-4</ISBN>

·152·
第7章 XML 数据源对象 ·153·

<price>21.8</price>
</book>
<book id="0181" bookcategory="计算机" amount="250" remain="156"
discount="8.0">
<title>XML Web Service 开发</title>
<author>微软公司著</author>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-015825-6</ISBN>
<price>65.00</price>
</book>
<book id="0189" bookcategory="计算机" amount="230" remain="160"
discount="8.0">
<title>VB.NET 程序设计语言</title>
<author>微软公司著</author>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-013188-9</ISBN>
<price>86.00</price>
</book>
<book id="0028" bookcategory="计算机" amount="100" remain="90"
discount="7.5">
<title>JavaScript 速成教程</title>
<author>Michael Moncur 著</author>
<publisher>机械工业出版社</publisher>
<ISBN>7-111-09070-5</ISBN>
<price>28.00</price>
</book>
<book id="0074" bookcategory="计算机" amount="130" remain="78"
discount="7.8">
<title>软件工程 Java 语言实现</title>
<author>Stephen R.Schach</author>
<publisher>机械工业出版社</publisher>
<ISBN>7-111-06714-2</ISBN>
<price>51.00</price>
</book>
<book id="0109" bookcategory="计算机" amount="210" remain="160"
discount="8.0">
<title>人工智能</title>
<author>Nils J. Nilsson</author>
<publisher>机械工业出版社</publisher>
<ISBN>7-111-04738-6</ISBN>
<price>45.00</price>
</book>
<book id="0305" bookcategory="计算机" amount="115" remain="26"
discount="7.5">
<title>ASP 开发实例</title>
<author>清汉计算机工作室</author>
<publisher>机械工业出版社</publisher>
<ISBN>7-980039-74-2</ISBN>
<price>53.00</price>
</book>
</books>

·153·
·154· XML 实用教程

其显示结果如图 7.5 所示。

图 7.5 HTML 中的 XML 数据岛记录编辑与添加

7.4.2 HTML 中的 XML 数据岛记录集页面管理

上述使用数据岛处理 XML 标记时,采用内嵌 XML 文档或 src 属性导入 XML 文件。


XML 标记的处理还可以用<OBJECT>标记建立 DSO 对象。
<OBJECT id="XMLDSO"
classid="clsid:550dda30-0541-11d2-9ca9-0060b0ec3d39"></OBJECT>

可以使用脚本语言加载 DSO 数据源(XML 文件),如:


<script language="JavaScript">
var XMLdoc = XMLDSO.XMLDocument;
XMLDSO.async=false;
XMLdoc.load("code7_6.XML");
</script>

加载 XML 文档也可以使用 Java 自定义函数:


<script language="JavaScript">
function loadXML()
{
ver XMLdoc=XMLDSO.XMLDocument;
XMLdoc.load("code7_6.XML");
}
</script>

在 HTML 的<body>标记中加入属性 onload=“loadXML()”即可调用上述自定义函数。


如果不使用<OBJECT>标记建立 DSO,则需要做如下定义。
<XML id="XMLDSO"></XML>

这个<XML>标记定义了 id 号为 XMLDSO 的 XML 数据源对象,剩下就是加载 XML


文档,同前述一样。注意不能同时使用<OBJECT>和<XML>标记定义数据源。
成功声明 XML DSO 后,就可以在 HTML 文档的其他地方通过 id 标识号来实现对 DSO
数据源的访问了。
【例 7.7】 将例 7.6 的 XML 文档使用<OBJECT>标记建立 DSO 对象,代码如源程序
code7_7.htm 所示。

·154·
第7章 XML 数据源对象 ·155·

<OBJECT classid="clsid:550dda30-0541-11d2-9ca9-0060b0ec3d39"
id="XMLDSO">
</OBJECT>
<HTML>
<HEAD><title>使用表格绑定 XML</title></HEAD>
<script language="JavaScript">
function loadXML()
{ // 加载 XML 文件
var XMLdoc = XMLDSO.XMLDocument;
XMLdoc.load("code7_6.XML");
}
</script>
<BODY onload="loadXML()">
<h2 align="center"><font size="4">使用<OBJECT>标记建立 DSO 对象
</font></h2>
<table datasrc="#XMLDSO" border="1" align="center">
<thead>
<th>书名</th><th>类别</th><th>书号</th><th>作者</th>
<th>出版社</th><th>定价</th><th>剩余量</th>
</thead>
<tr>
<td><span datafld="title"></span></td>
<td><span datafld="bookcategory"></span></td>
<td><span datafld="ISBN"></span></td>
<td><span datafld="author"></span></td>
<td><span datafld="publisher"></span></td>
<td><span datafld="price"></span></td>
<td><span datafld="remain"></span></td>
</tr>
</table>
</BODY>
</HTML>

其显示结果如图 7.6 所示。

图 7.6 使用<OBJECT>标记建立 DSO 对象的显示数据

·155·
·156· XML 实用教程

使用脚本语言可以对 XMLDSO 数据源对象进行操作,如可通过下面的脚本从 XML


DSO 数据源中得到剩余书本数量:
Remain_value = XMLDSO.recordset.Fields("remain")

有了 DSO 对象,JavaScript 和 VBScript 都可以使用属性控制 XML 元素的显示。DSO


对象的 datapagesize 属性设定表格显示的 XML 元素数目,没有指定此属性将全部显示。
当使用 datapagesize 属性设定表格分页显示的条数后,就可以用表 7-2 的方法控制分页
显示。

表 7-2 控制表格每页显示记录条数的方法

方 法 说 明

nextPage 下一页

previousPage 上一页

firstPage 第一页

lastPage 最后一页

【例 7.8】 分页显示 XML 数据源的数据,代码如源程序 code7_8.htm 所示。


<OBJECT classid="clsid:550dda30-0541-11d2-9ca9-0060b0ec3d39"
id="XMLDSO" height=0 width=0></OBJECT>
<HTML>
<HEAD><title>分页显示书本信息</title></HEAD>
<script language="JavaScript">
var XMLdoc = XMLDSO.XMLDocument;
XMLDSO.async=false;
XMLdoc.load("code7_6.XML");
</script>
<body bgcolor="#eaeaea">
<center><b><font size="3">分页显示书本信息</font></b></center>
<table id=tblbooks datasrc="#XMLDSO" border="1" align="center"
datapagesize=3 >
<thead>
<th>书名</th><th>类别</th><th>书号</th><th>作者</th>
<th>出版社</th><th>定价</th><th>剩余量</th>
</thead>
<tr>
<td><span datafld="title"></span></td>
<td><span datafld="bookcategory"></span></td>
<td><span datafld="ISBN"></span></td>
<td><span datafld="author"></span></td>
<td><span datafld="publisher"></span></td>
<td><span datafld="price"></span></td>
<td><span datafld="remain"></span></td>
</tr>

·156·
第7章 XML 数据源对象 ·157·

</table><hr>
<center>
<input type="button" onclick="tblbooks.previousPage()" value="上一页">
<input type="button" onclick="tblbooks.nextPage()" value="下一页">
每一页<input type=text value="3" size="5"
onblur="tblbooks.dataPageSize=this.value;">笔
</center>
</BODY>
</HTML>

其显示结果如图 7.7 所示。

图 7.7 使用 DSO 分页显示 XML 数据

7.5 综合应用实例

通过上述学习可知,运用 XML 数据岛技术,可以方便地将 XML 文档的信息显示到表


格中,免去了复杂的编程,如循环结构的使用。这里将上面几个程序综合起来,形成较完
整的图书资料显示网页。
【例 7.9】 图书资料综合显示,代码如源程序 code7_9.htm 所示。
<XML id="XMLDSO" src="code7_6.XML"></XML>
<HTML>
<HEAD><title>分页分条显示书本信息</title></HEAD>
<script language=JavaScript>
var pageno=1;
function SelectRecord(Element)
{
// 获取记录的列号
RecordNo = Element.parentElement.rowIndex;
// 建立 XML 的 RecordSet
objbook = XMLDSO.recordset;
// 指定当前的位置
objbook.absoluteposition = RecordNo+(pageno-1)*tblbooks.dataPageSize;
// 获取元素的值
title.innerHTML = objbook("title").value;
bookcategory.innerHTML = objbook("bookcategory").value;

·157·
·158· XML 实用教程

ISBN.innerHTML = objbook("ISBN").value;
author.innerHTML = objbook("author").value;
publisher.innerHTML = objbook("publisher").value;
price.innerHTML = objbook("price").value;
remain.innerHTML = objbook("remain").value;
}
function pre_page()
{
if (pageno>1)
{ tblbooks.previousPage();
pageno=pageno-1; }
}
function next_page()
{
if (pageno<objbook.RecordCount/tblbooks.dataPageSize)
{ tblbooks.nextPage();
pageno=pageno+1; }
}
</script>
<BODY>
<center><b>分页显示书本信息</b></center>
<table ID=tblbooks datasrc="#XMLDSO" border="1" align="center"
datapagesize=3 >
<thead>
<th>书名</th><th>类别</th><th>书号</th><th>作者</th><th>出版社
</th><th>定价</th><th>剩余量</th>
</thead>
<tr>
<td onclick=SelectRecord(this)><span datafld="title"></span></td>
<td onclick=SelectRecord(this)><span datafld="bookcategory"></span></td>
<td onclick=SelectRecord(this)><span datafld="ISBN"></span></td>
<td onclick=SelectRecord(this)><span datafld="author"></span></td>
<td onclick=SelectRecord(this)><span datafld="publisher"></span></td>
<td onclick=SelectRecord(this)><span datafld="price"></span></td>
<td onclick=SelectRecord(this)><span datafld="remain"></span></td>
</tr>
</table>
<hr>
<center>
<input type="button" onclick="pre_page()" value="上一页">
<input type="button" onclick="next_page()" value="下一页">
每一页<input type=text value="3" size="5"
onblur="tblbooks.dataPageSize=this.value;">笔
</center>
<center>请单击上表有兴趣的图书行</center>
<hr>
<center>单本图书信息:书名: <span id="title"></span></center>
<table border="1" align="center" >

·158·
第7章 XML 数据源对象 ·159·

<tr><td width="50%">
分类: <span id="bookcategory"></span><br>
书号: <span id="ISBN"></span><br>
作者: <span id="author"></span><br>
</td>
<td width="50%">
出版: <span id="publisher"></span><br>
定价: <span id="price"></span> 元<br>
剩余: <span id="remain"></span>本<br>
</td>
</tr>
</table>
<hr>
</BODY>
</HTML>

其显示结果如图 7.8 所示。

图 7.8 使用 XML 数据源对象综合显示 XML 数据

7.6 小 结

XML 文档是一个层状架构的信息体, 可以作为数据源使用。使用 XML 数据岛和 HTML


绑定,相对于传统方式,只需极少编程量就能获得需要的效果,而最终得到的页面比传统
方式获得的页面更加简洁,因此页面能更快地载入,更方便用户。另外,由于减少了客户
端的脚本编程,所以产生错误的机会也会减少一些。
XML 数据岛是指嵌入 HTML 文档中的 XML 信息。XML 与 HTML 的结合在数据集成、
显示、更新和修改等方面具有明显的优越性。
数据绑定是将 XML 文档或其他外部数据集成到 HTML 文件中,然后使表格等 HTML
元素绑定 XML 文档元素,从而实现 XML 数据在 HTML 页面中的显示。数据绑定的体系
结构包括 4 个组成部分:Data Source Object、Data Consumers、Binding Agent 和 Table

·159·
·160· XML 实用教程

Repetition Agent。XML 文档信息需要显示多条记录时,绑定到 HTML 的表格元素,表格


能够显示 XML 的所有元素,自身隐含着循环;只需要单条显示时,选择合适的 HTML 标
记,每一个绑定的 HTML 元素都要同时确定数据源(datasrc)和绑定的字段(datafld)。可供绑
定的 HTML 元素共分为单值对象和表对象两大类。对于多层嵌套表格,要分层绑定数据源
和数据字段。
用于绑定的 XML 文档可以是嵌入到 HTML 文件内部的,也可以从外部载入。
XML 数据源对象能视为 ADO Recordset 对象,可以结合脚本语言操作记录集,方便地
编制出展现数据的界面。

7.7 习 题

1. 什么是数据岛?
2. 数据源对象的用途是什么?
3. XML 文档是数据库吗?试比较 XML 文档和数据库的特点、架构。
4. 试述数据绑定的作用和意义。
5. 试述使用表格时数据绑定的步骤。
6. XML 与 HTML 结合的优势有哪些?
7. 将 HTML 元素和 XML 文档绑定时要注意哪些问题?
8. 试用 HTML 的<a>标记绑定 XML 文档中的网址,编辑能够出现超文本链接的网页。
9. 在本书中找两个例子,使用 HTML 的<div>标记替换原来的<span>标记绑定 XML
文档。
10. 试用 3 种方法加载 XML 文档,分别写出代码。
11. 编写含有脚本的 HTML 代码,使用户能够翻阅前后条记录。
12. 编写含有脚本的 HTML 代码,使用户能够翻页查看记录。
13. 编写代码,使之能够查阅全班同学的通讯录。

·160·
第 8 章 XSL 转换
教学提示:XSL 的目的就是为生成 XML 文档提供一个功能强大而又容易使用的样式
语法。实际上 XSL 分为 XSL 转换(XSL Transformation,XSLT)和格式化对象
(Formatting Object,FO)。XSLT 是一种专门用来转换 XML 文档的语言。它将一个
XML 文档(输入或源文档)转换为另一篇 XML 文档(输出或结果文档)。XSLT 只是一
种转换机制,FO 用来描述如何对文档进行格式化。本章主要介绍 XSLT 的基础知识,
XSLT 中使用到的 XML 元素,模板等概念,以及综合运用 XSLT 将 XML 转换成 HTML
的实例。
教学目标:理解 XSL 的一些基本概念,弄清 XSL 的结构。了解 XPath 在 XSLT 中所
起的作用。掌握 XSLT 转换语言的基础知识,熟悉 XSLT 所使用的元素、模板、函
数等,通过具体实例,学会综合运用 XSLT 编写转换模板。

8.1 XSL 概述
可扩展的样式表语言(eXtensible Stylesheet Language,XSL)最早由 W3C(World
Wide Web Consortium)于 1999 年提出。它定义了如何转换和表示 XML 文档。比
CSS 功能要强大得多。XSL 能够向输出文件里添加新的元素或者移动元素,也
能够重新排列或者索引数据,它可以检测并决定哪些元素被显示,显示多少等。
它使用 XPath 匹配结点。把一个 XML 文档转换为另一个不同的文档。得到的文
档可以是 XML、HTML、无格式文本或任何其他基于文本的文档。XSL 的第二
部分是 XSL 格式化对象。格式化对象提供了另一种方式,来格式化显示 XML
文档,以及把样式应用到 XML 文档中。
8.1.1 XSL 的意义
XML 是一种计算机程序间交换原始数据的简单而标准的方法。它的成功并
不在于它容易被人们书写和阅读,更重要的是,它从根本上解决了应用系
统间的信息交换。因为 XML 满足了以下两个基本的需求。
(1) 将数据和表示形式分离。就像天气预报的信息可以显示在电视、手持式
移动电话机或者其他不同设备上一样,XML 的显示或表现形式可以是多样
的。
(2) 在不同的应用之间传输数据。电子商务数据交换的与日俱增使得这种需
求越来越紧迫。
为了使数据便于人们的阅读和理解,需要将信息显示或者打印出来,例如
将数据变成一个 HTML 文件,一个 PDF 文件,甚至是一段声音。同样,为
了使数据适合不同的应用程序,必须能够将一种数据格式转换为另一种数
据格式,比如需求格式可能是一个文本文件、一个 SQL 语句、一个 HTTP
信息、一定顺序的数据调用等。而 XSLT 就是用来实现这种转换功能的语
言。将 XML 转换为 HTML,是目前 XSLT 最主要的功能。
8.1.2 XSLT 和 CSS 的比较
CSS 同样可以格式化 XML 文档,那么有了 CSS 为什么还需要 XSLT 呢?
因为 CSS 虽然能够很好地控制输出的样式,比如色彩、字体、大小等,但
是它有严重的局限性,就是:
(1) CSS 不能重新排序文档中的元素;
(2) CSS 不能判断和控制哪个元素被显示,哪个不被显示;
·162· XML 实用教程

(3) CSS 不能统计计算元素中的数据。


换句话说,CSS 只适用于输出比较固定的最终文档。CSS 的优点是简洁,
消耗系统资源少。而 XSLT 虽然功能强大,但因为要重新索引 XML 结构树,
所以消耗内存比较多,CSS 与 XSLT 的比较见表 8-1。
因此,常常将它们结合起来使用,比如在服务器端用 XSLT 处理文档,在
客户端用 CSS 来控制显示,可以减少响应时间。
表 8-1 CSS 与 XSLT 的比较
CSS XSLT

适用在 XHTML 可以 可以

使用的语法 CSS 样式语法 XML 语法

8.1.3 浏览器对 XSL 的支持


为了用 XSL 来处理一个 XML 文档,需要一个带有 XSL 引擎的 XML 处理
器,包含原始数据的 XML 文档和用来转换该文档的 XSLT 文档。XSLT 处
理器把 XSLT 文档的规则应用到 XML 文档从而输出 XHTML、WML、SVG
或者其他任何 XML 格式的文档。
本文举例中的代码只在 IE 5.0 或更高版本中工作。IE 5.0 中的 XSL 引擎并
不是 100%的与最新发布的 W3C XSL 标准相吻合。在 XSL 标准完全固定下
来之前,IE 5.0 就已经发布了,并且当时的 XSL 标准还是一个工作草稿。
MSXML 2.0 是 IE 5.0 所携带的 XML 解析器,MSXML 2.5 是 Windows 2000
所携带的解析器,MSXML 3.0 是 XML 解析器的较高版本。IE 6.0 内嵌了最
新的 MSXML 4.0 解析器。Microsoft 公司的解析器可以从 Microsoft 公司网
站上下载,未来版本的 IE 和 Windows 都将携带 XML 解析器。更多信息请
查看 http://msdn.microsoft.com/xml/general/xmlparser.asp 。
目前流行的带有 XSL 引擎的 XML 处理器软件有以下 4 种。
(1) XSLT 标准制订者之一 James Clark 开发的 XT。下载网址为
http://www.jclark.com/xml/ xt.html
(2) IBM 公司的 XML for Java 软件包,名为 LotusXSL。下载网址为
www.alphaworks.ibm.com /tech/xml4j
(3) Saxon。下载网址为 http://www.wrox.com
(4) Microsoft 公司的 MSXML 4.0 sp2。下载网址为
http://www.microsoft.com/xml
8.2 XSL 基础
XSL 定义可用于 XML 文档的格式化或表示过程。由于 XSL 内容很多,包括
XSLT、XPath 和 XSL-FO 等,这可能会给 XSL 初学者带来困惑。下面首先介绍
一些有关 XSL 的基础知识。
8.2.1 XSL 的组成
XSL 主要由两部分组成:第一部分是 XSLT,可以把 XML 文档从一种格式
转换为另一种格式。它使用 XPath 匹配结点,把一个 XML 文档转换为另一
个不同的文档。得到的文档可以是 XML、HTML、无格式文本或任何其他
基于文本的文档。第二部分是 XSL 格式化对象(Formatting Object)。格式化
对象提供了 CSS 的另一种方式,来格式化 XML 文档以及把样式应用到 XML
文档上。因此,XSL 在转换 XML 文档时分为明显的两个过程,首先转换文
档结构,其次将文档格式化输出。这两步可以分离开来并单独处理,XSL

·162·
第8章 XSL 转换 ·163·

在发展过程中由此也逐渐分裂为 XSLT(结构转换)和 XSL-FO(格式化输出)


两种分支语言,其中 XSL-FO 的作用就类似 CSS 在 HTML 中的作用。而本
章重点讨论的是第一步的转换过程,也就是 XSLT。
8.2.2 XSLT 简介
XSLT 提供一套规则用于将一组元素描述的 XML 数据转换为另一组元素描
述的文档,或者是将该数据转换为一种自定义的文本格式。如员工的数据
XML 文件,通过 XSLT 转换,在公司的网站中会以 HTML 的格式输出显示,
而对于会计则只需要转换成自定义的文本格式员工数据就可以。
XSLT 把 XML 文档转换为完全不同的输出,这样可以把数据内容存储在 XML
文档中,然后通过各种媒体将其输出到各种介质中,如无线电、打印、语音
等格式。当数据发生变化时,只需要修改源 XML 文档,不需要在多处重复
相同的修改工作。通常情况下,XSLT 用于将 XML 文档转换为 HTML,目
的是可以在浏览器中进行显示。
最简单的 XSLT 应用情况首先涉及到两个文档:包含原始数据的 XML 文档
和用来转换该文档的 XSLT 转换文档。将 XML 文档输入,处理器根据 XSLT
文档作为模板进行转换,最终输出需要的文档,过程如图 8.1 所示。

·163·
·164· XML 实用教程

图 8.1 使用 XSL 转换 XML 文档


一些可能的 XSLT 应用包括:
(1) 以查看为目的添加元素,如向 XML 格式的订单中添加公司标
志或发送者的地址。
(2) 给现有内容创建新的内容,如创建目录。
(3) 从 XML 文档中提取信息,如向管理人员提供详细的信息,对
普通员工提供有限的信息。
(4) 在不同的 XML 字典或模型之间进行转换,如将公司专用的文
档转换为符合业界标准的文档。
(5) 将 XML 文档转换为 HTML,用以实现与现有浏览器之间的兼
容。
XSLT 的语法规则将在本章后续部分详细介绍。
8.2.3 XPath 简介
XPath 是 XSLT 的重要组成部分。它是一种专门用来在 XML 文档中查找信
息的语言。XPath 隶属于 XSLT,因此通常会将 XSLT 语法和 XPath 语法混
在一起阐述。可以这样来解释:如果将 XML 文档看为一个数据库,那么
XPath 就是 SQL 查询语言;如果将 XML 文档看为 DOS 目录结构,那么 XPath
就是 cd、dir 等目录操作命令的集合。
在 XSLT 中,XPath 表达式返回 4 种类型值:结点集合、布尔值、数字和字
符串。XSLT 元素通常用 XPath 表达式作为属性值,采用表达式的计算结
果。
基本上 XSLT 的最常规用法是返回结点集合或者字符串,具体取决于有关
的元素定义。例如,<xsl:template match=“chapter”> 定义了当前结点上下文
环境内针对 chapter 结点的模板。在这种情况之下,XPath 表达式 chapter 即
可返回结点集合作为以后 XSL 函数可用的新的上下文。那么在模板内的
<xsl:value-of select=“title”/>代码中,XPath 表达式将把当前上下文中任何 title
结点的原始内容以字符串的形式返回。
1. 结点导航
XPath 导航的外观和行为完全与文件系统导航一模一样。斜线分隔父子结
点:chapter/title,代表只在当前上下文的 chapter 结点内直接检索 title
结点。
与常用来进出目录层次的文件系统语法类似,即可检索结点的父结点:
“../title”,会指向当前结点的父结点内的 title 结点,检索图书的标题。
但是,这种导航方式毕竟还是与文件系统导航有所差别,特别是在文
件导航的情况下,同一位置是不可能出现两个同名文件的。而 XPath
却经常遇到同一类型的结点,因此 XPath 的定位,例如
chapter/paragraph,经常索引多个结点而非一个结点。

·164·
第8章 XSL 转换 ·165·

一般来说,XPath 中路径开始于当前上下文,但在文件系统中,路径可
以采用绝对定位而非相对定位的方式。XPath 中也可以有这种方式,使
用开始斜线“/”指向文档的根而不是文档的第一个结点,如“/book/title”
能返回顶级 book 结点内的 title 结点。
双斜线“//”是结点的通配路径。在有的例子中,<xsl:template
match=“//title”>会返回文档内各个位置的<title>结点而不论其是否在
“/book/title”还是位于“/book/chapter/title”。双斜线还可以位于路径
的中间,如“/book//title”则返回 book 结点下所有的<title>结点。
在路径的末尾加一个星号“*”会返回所有当前路径下所有的结点,这
与文件系统通配符的用法是完全一样的。在上面的例子中,
“/book/chapter/*”会同时检索出<book>根结点下的<chapter>结点下的
所有结点,而路径“//*”则会返回文档中的所有结点。
2. 访问数据
XPath 还提供了根据比较方法选择特定属性或结点值的语法。
“@”指结点的标记属性。假设 chapter 有 type 属性,按“@type”的
方式就可访问。如果为了可以从文档的任何地方访问它,访问路径应
该写成“/book/chapter/@type”。
方括号从一个集合中选出一个结点,很像是传统编程中的数组。为了
只选出第二个 chapter,可以用一个形如“/book/chapter[2]”的 XPath
表达式。注意,集合中的第一个结点的编号是 1,而不是大多数编程语
言中规定的 0。
同时,也可以把这些条件组合起来按照其属性值选择结点,在条件为
真时才返回结点。条件包含在方括号中,跟在要应用条件的元素之后,
如:

<xsl:template match="price[@unit='USD']">

这里 match 值的内容是一个正则表达式。“@unit”表示为 unit 属性。


例子说明要匹配的是这样一个结点:一个带 unit 属性的元素 price,而
且 unit 的值必须为‘USD’。例如,对应的一段 XML 代码是这样的:

<price>
<unit>USD</unit>
<amount>100</amount>
</price>
<price>
<unit>RMB</unit>
<amount>300</amount>
</price>

那么“price[@unit='USD']”条件匹配的内容就是:

<price>
<unit>USD</unit>
<amount>100</amount>
</price>

XPath 访问结点数据的特殊字符用法见表 8-2。

·165·
·166· XML 实用教程

表 8-2 XSL 匹配中使用的特殊字符


特殊符号 含 义 范 例 说 明
循环下降。符号后余下的部分可能与文 匹配<item>结点下,只要有
// item//itemName
档中的任何结点相匹配 <itemName>子结点
@ 前缀,表示紧接着的名称指向一个属性 book/@isbn <book>结点的 isbn 属性
可以在其内指定元素或属性,也可加上 <book>结点下有 isbn 属性的
[] book[@isbn]
额外的测试条件 结点
| 与多个结点匹配 book|title 与<book>或<title>匹配
. 当前结点 . 取得当前结点

结点选择功能还有许多,其内容已经超出了本文所涉及的范围,
有兴趣的读者可以查阅相关资料。
3. 高级方法
除了导航和数据提取之外,XPath 还提供了字符计数、变量设置、基本
数学计算、找出最近元素以及其他多种类型的模式匹配等函数。例如,
如果在转换时,只关心当前结点名称为 contactInfo 的结点,显出顾客
联系信息,那么可以这样使用:

[.!nodeName()='contactInfo']

一些常用的 XPath 函数见表 8-3。


表 8-3 一些 XPath 函数
函 数 含 义
nodeName 返回结点的确定名称
nodeType 返回表示被选择结点类型的数值
8.2.4 XPointer、XLink 和 XQuery
XPointer 是在 XPath 表达式基础上构建的,但在数据库模型和所支持的函数
中进行了扩展。XPointer 支持对 XML 内部结构部分的定位。XPath 提供了
表达定位的语法,XPointer 在这之上进行了扩展。XPath 通过谓词和轴(所
谓的轴就是指 child、descendant、parent、ancestor 等的关键字表明的查询范
围)对 XML 文档中树状结构的各部分进行选择,而 XPointer 还需要指定另
外意义上的文档结点。例如,可能要选择两个结点中的某一部分,而这两
个结点可能处于文档中不同的子树中。为了实现这一点,XPointer 把定位定
义为 XPath 的广义结点。Xpointer 关于范围的定义有如下几种。
(1) [Definition: point]:表示在 XML 文档中的位置。
(2) [Definition: range]:表示在一对 points 结点之间的 XML 文档。
(3) [Definition: location]:表示包括 points 和 range 的结点集合。
(4) [Definition: location-set]:表示一个 locations 的集合。
(5) [Definition: singleton]:它是对 point 和 range 的一个综合,也就是说,一
个 point 是一个 singleton,而一个 range 也是一个 singleton。
(6) [Definition: sub-resource]:表示在文档中的一个特定的资源,这里的资源
可以是一个特定的元素。
由于 XPointer 使用了 XLink 的一些特性用于定位 XML 文档的片段,所以
XML 链接语言 XLink 也是值得一提的内容。XLink 是描述在资源间进行链

·166·
第8章 XSL 转换 ·167·

接的语言,它提供类似于 HTML 的<a>元素那样的链接功能,而且还要提供


许多更加复杂的链接结构。链接反映了不同资源对象之间的关系,而对象
的选择是由定位来描述的(这就是 XPointer 的职责)。XLink 可以声明多个资
源之间的关系。资源可以是任何信息或服务的可定位单元,具体的资源例
子有文件、图像、文档、程序和查询结果。因此定位一个资源是非常重要
的环节,一般用 XPointer 进行资源的定位。例如,如果整个资源是一个 XML
文档的话,这个资源有用的一部分可能是文档内一个特定的元素,跟随一
个链接可能会产生多个结果,比如会加亮该元素并且文档滚动到该元素所
在的文档位置。当一个链接和一个资源的集合相联系的话,就认为这些资
源加入了这个链接的队列。当然 Xlink 可以链接任何资源,而不仅仅是 XML
文档的一部分。
XQuery 可能会成为 XPath 最为重要的实现。假定大量的信息是作为 XML
来处理的,而开发对这些信息进行高效查询的方式则是极为重要的。正如
XPath 经过扩展来支持 XSLT 和 XPointer 一样,XQuery 提供了一种更为程
序化、更清楚直接的方法,方便用户对 XML 文档中数据的查询,提取相关
数据和操作结果以创建不同格式的输出形式,包括 XHTML 和 HTML 或其
他格式等操作。
8.2.5 XSL-FO
XSL-FO 全称是 XSL 格式化对象(XSL Formatting Objects)。XSLT 只是一种
转换机制,需要使用目标语言来描述如何对文档进行格式化。在实际操作中,
混合使用 XSLT 和 HTML 来编写一本书是不可能实现的,于是就有了 FO。
就 XSL-FO 格式本身来说,可以看成是一种排版格式。一个完整的 XSL-FO
文档包含了信息内容及控制信息显示方式的版式,其对信息描述方法的多
样性可完全媲美于目前常用的文档格式如 pdf、ps、doc 等。遗憾的是,目
前能体现 XSL-FO 强大功能的浏览工具并不多。
XSL-FO 更重要的功能是与 XSLT 共同控制 XML 数据的显示方式。这里,
XSLT 通常用于描述怎样转换 XML 元素,而 XSL-FO 通常用来描述怎样表
示 XML 文档内容。设计良好的 XSL(这里指 XSLT + XSL-FO)可以作为模板
用于修饰功能相近的多个 XML 文档,这给重复性数据如数据库等的排版显
示带来了操作上的方便。
这里把 XSL-FO 看成是一种排版格式,并不是说要把它与用于传统印刷业
的排版格式相提并论,虽然它也可以表达这些排版格式所要表达的内容。
确切地说,它是一种“基于 Web 的排版格式”。XSL-FO 的目的之一就是
在网络上进行复杂文档的分页处理、大文档和复杂排版格式的处理以及网
络打印等。
从目前的使用情况来看,XSL-FO 可以应用于下列领域:政府公文传输排版
系统、政府公文集中打印系统、保险行销系统、市场调查分析用户报告生
成系统、PDF 自动发稿系统、报表管理系统、周刊杂志的页排版、技术手
册的制作等。
若想使用 XSL-FO,相应的工具是必不可少的。这主要包括 XSL-FO 编辑工具
及 XSL-FO 处理工具。由于 XSL-FO 是 XML 系列的组成部分,本身符合
XML 语法规则,所以用于 XML 的编辑工具也可应用于编辑 XSL-FO。目
前可使用的编辑工具主要有 XML Spy、XSL Fast、Tag Editor 等。XSL-FO
处理工具用于对 XSL-FO 进行显示、转换等处理。一个 FO 文档,结构如图
8.2 所示。

·167·
·168· XML 实用教程

图 8.2 XSL-FO 文档结构


8.3 XSLT 转换语言
XSLT 的功能很强大,它不只是负责转换 XML,而且自身还是一种完全意义上
的 XML 标准语言。它非常灵活,具有非常多的规则,这里只做最基本的介绍。
8.3.1 一个简单的 XSLT 示例
下面来看一个简单的 XML 文档及其 XSLT 应用例子。
【例 8.1】 一个 XML 格式的问候文档,代码如源程序 code8_1.xml 所示。

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


<greeting>XSL--Important Step in learning XML!</greeting>

这个 XML 文档很简单,结构树只包含一个结点,例 8.2 将建立显示它的


XSLT 文档 code8_2.xsl。XSLT 文件的默认扩展名为.xsl。
【例 8.2】 XML 文档 code8_1.xml 的格式转换示例,代码如源程序
code8_2.xsl 所示。

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


<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<html>
<head><title>First XSLT example</title></head>
<body>
<p>
<xsl:value-of select="greeting"/>
</p>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

现在可以用 IE 5.0 以上版本浏览器打开这个 code8_2.xsl 文件,看到 XSL 的


结构树。
紧接着,在 XML 中调用这个 XSL 文件。要让 XML 文件调用 XSL 样式表,
应在 XML 文档中加入<?xml-stylesheet type=“text/xsl” href=“code8_2.xsl”?>
这样的语句,指明 XML 文档的转换 XSL 样式表。
修改 code8_1.xml 的代码为

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


<?xml-stylesheet type="text/xsl" href="code8_2.xsl"?>
<greeting>XSL--Important Step in learning XML!</greeting>

·168·
第8章 XSL 转换 ·169·

到这一步原理上已经完成了所有的代码,接下来只要用一个 XSLT 处理器


(XML Processor)来执行程序 code8_5.xsl 就可以看到“XSL--Important Step in
learning XML!”的显示结果了。由于微软的 IE 内嵌了 XML 解析器,直接
在 IE 打开 code8_4.xml 文件,就可以看到结果。如果只看到 XML 结构树,
不是单独的“XSL--Important Step in learning XML!”字样,说明浏览器没有
安装解析器,需要安装解析器。
8.3.2 示例中的元素分析
下面根据例 8.2,仔细地分析其中的语法结果和关键所在。
首先注意到的是,XSL 文件本身就是一份 XML 文件,因此在 XSL 文件的
开头,一样有与 XML 文件相同的声明。 W3C 为 XSL 定义了很多标记(元素),
XSL 文件就是这些标记和 HTML 标记的组合。在 XSL 文件中,必须有如下
一行的代码:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">

其中,xsl:stylesheet 是 XSL 文件的根元素,在根元素中包含了所有的排版


样式,样式表就是由这些排版样式组合成的;
xmlns:xsl="http://www.w3.org/TR/WD-xsl"这部分主要用来说明该 XSL 样式
表是使用 W3C 所制定的 XSL 规范,设定值就是 XSL 规范所在的 URL 地址。
实际上,http://www.w3.org/TR/WD-xsl 就是一个命名空间,在前面关于 XML
Schema 语法介绍的时候已经进行过介绍。这是一个标准的名称空间。
stylesheet、template、for-each 等关键字都是这个名称空间所定义的。

·169·
·170· XML 实用教程

然后,在示例的代码中看到有如下的代码。

<xsl:template match="/">

</xsl:template>

这实际上是表示了 XSL 解析器对 XML 文档的处理过程,它从根结点(由


match="/"决定,“/”就表示根结点)开始,对 XML 文档进行遍历,并根据
具体的代码从 XML 文档中提取相关的内容。关于 match 属性的取值是一个
比较复杂的问题。在 XPath 部分将作介绍。
用<xsl:template match="具体匹配表达式">这条语句找到了一些结点集合以
后,就要从这个集合中找到特定的元素或者元素属性的值,那么采用什么
语句呢?就是用<xsl:value-of select = "">这样的语句来寻找特定的内容。
例如在下面的例子中<xsl:value-of select="书名">这行代码就是表示定位
XML 文档中的名称元素的内容。在指定集合中可能存在多个书名元素,如
果需要把它们一一列举出来进行处理的话,就需要用到语句<xsl:for-each
select ="">,注意这里涉及到一个作用范围的概念,也就是说<xsl:for-each
select = "">语句是在一个指定的集合空间中执行的,参见如下代码:

<xsl:template match="书籍">
<table Border="1">
<xsl:for-each select="书名" >

</xsl:for-each>
</table>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="书籍" />
</xsl:template>

这里的<xsl:for-each select="书名">是在<xsl:template match="书籍">所指定


的集合空间里面寻找元素“书名”的。
同时,需要注意的是上面的代码中,出现了如下这样一条语句。

<xsl:apply-templates select="书籍" />

实际上相当于 C++中的一个过程调用,当 XSL 解析器执行到该语句的时候,


它就会在代码中寻找以<xsl:template match="书籍">开头的代码,因此在上
面的例子程序中,以下的代码可以看成是过程的实现。

<xsl:template match="书籍">

</xsl:template>

将以上代码看成是过程的实现,有助于对 XSL 解析器执行过程的理解。这


里 match="书籍"可以理解为是传递给过程的参数,它表示过程实现体的集
合范围是该 match 所匹配的结点集合空间("书籍")。
如果要对表格中的元素进行排序该怎么办呢?假设在上面的例子中按照名
称进行排序,很简单,改写为如下的形式即可:

·170·
第8章 XSL 转换 ·171·

<xsl:for-each select="书名" order-by="+书名">

其中,“+”表示按降序排列,“-”表示按升序排列,order-by 是 XSL
语法中的关键字。
如果只想在列表中取出某几行该怎么操作呢?假设只想取出书名为“三国
演义”的行,见下面的代码:

<xsl:template match="书籍">
<table Border="1">
<xsl:for-each select="书名" order-by="+书名">
<xsl:if test=".[书名='三国演义']">
<tr>
<td><xsl:value-of select="书名"/></td>
<td><xsl:value-of select="价格"/></td>
</tr>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>

这里有一个新的句法为</xsl:if test="[书名='三国演义']">,它表示如果".[书
名='三国演义']"为 true,就执行该段里面的语句,如果为 false 就不执行。它
和 C++中的 if 语句的概念基本一样。
前面用<xsl:value-of select="元素名称"/>取出的都是一个元素的值,但是要
取出元素某一个属性的值该怎么做呢?可以采用下面的格式:

<xsl:value-of select="元素名称/@属性名称"/>

例如,有一段 XML 代码是这样的:

<罗贯中 网址="www.lai.org">罗贯中的生平介绍</罗贯中>

可以用<xsl:value-of select="罗贯中/@网址"/>来得到值 www.lai.org。


8.3.3 XSL 的执行过程
了解 XSL 的几条主要语句,知道这些语句的含义后,下面针对下面的实例
来分析一下 XSLT 的执行过程。
【例 8.3】 电子购物网站购物车的 XML 文档,代码如源程序 code8_3.xml
所示。

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


<?xml-stylesheet type="text/xsl" href="code8_4.xsl"?>
<shoppingCart>
<item>
<itemNo>1001</itemNo>
<itemName>三国演义</itemName>
<price>30.00</price>
<publisher>文艺出版社</publisher>
</item>
<item>
<itemNo>1002</itemNo>

·171·
·172· XML 实用教程

<itemName>红楼梦</itemName>
<price>120.00</price>
<publisher>文艺出版社</publisher>
</item>
</shoppingCart>

【例 8.4】 电子购物网站的购物车文档 code8_3.xml 对应的转换文档,代码


如源程序 code8_4.xsl 所示。

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


<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<html>
<head>
<title>网站购物车</title>
<style> .title{font-size:15pt; font-weight:bold;
color:blue } .name {color:red} </style>
</head>
<body>
<P class="title">Shopping Cart Contents</P>
<table border="1">
<thead>
<td><b>编 号</b></td>
<td><b>书 名</b></td>
<td><b>价 格</b></td>
<td><b>出 版 社</b></td>
</thead>
<xsl:for-each select="shoppingCart/item"
order-by="itemNo">
<tr>
<td>
<b>
<xsl:value-of
select="itemNo"/>
</b>
</td>
<td>
<xsl:value-of select="itemName"/>
</td>
<td>
<xsl:value-of select="price"/>
</td>
<td>
<xsl:value-of
select="publisher"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

其显示结果如图 8.3 所示。


本例的 XSL 样式表由一个模板构成,单一模板形式适合于简单的转换。就
上面的例子而言,转换从文档头部开始,有规则地向下进行。

·172·
第8章 XSL 转换 ·173·

图 8.3 购物车 XML 文档经过转换后的结果


如例 8.4 所示,当 XML 解析器解析 XML 文档时,首先遇到 XML
文档的根文档(由 match 属性值表示)时,需要执行这个模板,将前
面的一些元素(html、head、body 等)写到输出文档中去,然后执行
xsl:for-each 指令,把处理的结果依次放入输出文档中。处理就结
束了。
根据上面的分析,可以看到 XSL 实际上采用的是一种转换的思想,
它最终将 XML 文档转换为另一种可用于输出的文档,而 CSS 则
没有任何转换动作,在整个过程中没有任何新代码产生。另外,
在 XSL 中 90%的样式规定在 CSS 中都有定义,但仍然有一些效果
是 CSS 无法描述的,必须使用 XSL 不可。这些功能包括文本的置
换、根据文本内容决定显示的方式、文档内容排序等,都是 XSL
所独有的。再者,XSL 遵从 XML 的语法,而 CSS 的语法自成体
系。
8.3.4 应用 XSLT
从前面的例子中看出,要了解 XSLT 基本语法,首先要明白如何建立 XSLT
文档与 XML 文档的关联。
下面的例子假设 XML 和 XSL 文件都在一个目录下。直接使用 IE 5.0 以上
版本浏览器作为 XSL 处理器,因为它内置有 MSXML 的 XSLT 处理工具,
这样可以带来许多方便。
假设在这个例子中,用一个 XML 文档 books.xml 表示书籍目录,需要把这
个文档转换为可读的 HTML 格式。把相应的 XSLT 文档命名为 books.xsl。
将 XML 文件链接到该 XSLT 文档中,这样就可以在合适的浏览器中查看该
XML 文件,或者用 XML Spy 对其进行 XSLT 处理,转换成 HTML 文件。
要让 XML 文件调用 XSL 样式表,建立两者之间的链接,应在 books.xml
中加入:

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

指明 XML 文档的转换 XSL 样式表。其中 books.xsl 是指向 XSLT 文档的


URL。以上的方式对基于浏览器的格式转换是基本的要求。
8.3.5 stylesheet 元素
在理论上,完全可以编写负责自身格式转换的 XSLT 文档,因为 XSLT 文
档本身也是一种 XML 文档。这是一件比较有意思的事,但实际中这样的做
法没有意义。
XML 并不是一种通常意义上的语言, XML 是一种元语言,也就是建立 XML

·173·
·174· XML 实用教程

规范语言的结构(比如 XSL 和 XHTML 就是 XML 规范语言)。HTML 看起来


很像 XML,但实际上违反了很多 XML 规则。
XML 语言定义了一套用来把数据作为元素(或者可以说结点)的标记。例如,
就 XHTML 语法而言,table 标记就等于开始标记某个特定的 XML 结点。
XML 结点可以包含属性和内容体。属性是由字符串组成的名字/值对。内容
体可以是字符串或更多的 XML 结点。这就意味着 XML 是一种层次化的结
构,可以表示很复杂的数据格式。不妨思考如下的一个 XHTML 片段:

<table>
<tr>
<td>Hello world!</td>
<td><img src="earth.gif"/></td>
</tr>
</table>

在以上的代码段中,每个结点都有自己的开、闭标记,两个标记之间是更
多的结点和文本字符串。img 结点有一个 src 属性而没有内容,紧挨着开标
记的是一个终止斜线。这个终止斜线和文本都在 td 结点内嵌套,而后者又
在 tr 结点内嵌套,显然 tr 结点则在 table 内嵌套。
XSLT 文档通常被分解为离散的模板,每个模板负责处理 XML 文档内某一
类型的标记。在这些模板内,XSLT 要用到标量、传递参数、循环条件以及
其他转换 XML 的元素。
xsl:stylesheet 标记是任何 XSLT 风格表单的最外层标记,并要为文档指定版
本和一个或者多个命名空间,例如:

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

可以设置其他属性,但是,对几乎所有的基本 XSLT 文档来说,可以原样


使用这些 xsl:stylesheet 标记,其中可以嵌套模板元素。
8.3.6 XSLT 模板
模板是 XSLT 中最重要的概念之一,即使用模板将同样的格式应用于一个
XML 文档的重复元素。在某些元素下,模板就是要应用的规则。可以将模
板看成是一个模块,不同的模块完成不同的文档格式转换。
xsl:template 标记定义了用于进行转换的结点内容,其使用语法如下:
<xsl:template match="expression" name="name" priority="number"
mode="mode">
</xsl:template>
XSLT 处理器在发现 XSLT 文档中的一个显式调用或者在源 XML 文档中发
现匹配结点之后就会执行 xsl:template。最常见的情况是当 XSLT 处理器扫
描 XML 时遇到了匹配结点。匹配属性则用 XPath 表达式标识出源文档中的
结点,交由模板处理。向匹配的元素输出模板需要的内容。这些内容可能
由文本和非 XSLT 的标记所组成并直接写入某个新建文档乃至更多的 XSLT
元素。XSLT 元素只处理被模板激活的同类结点。
多个模板可以匹配一个结点。在这种情况下,采用模式和优先级属性的复
杂规则确定了应由哪个模板来处理结点。最简单的 XSLT 文档只包含匹配

·174·
第8章 XSL 转换 ·175·

给定结点的一个模板。
8.4 XSLT 模板体
使用 XPath 从 XML 文档中提取出要进行操作的结点集,接着需要使用 XSL 定
义的元素来转换这些结点。前面的例子已经显示了使用这些元素转换 XML 文
档。这些元素提供了类似于编程语言的功能。这些 XSL 元素见表 8-4。
表 8-4 XSL 元素列表
XSL 元素 含 义
xsl:value-of 插入被选择结点的值至输出文档
xsl:copy 复制指定结点下的内容到输出文档
xsl:comment 在输出中创建一个注释结点
xsl:when 在一个 xsl:choose 元素内提供单一的条件判断
xsl:if 简单的条件判断
xsl:template 为输出定义一个处理规则

这些都是在模板中要使用到的元素。下面具体介绍几个 XSLT 元
素。
8.4.1 索引与过滤
在介绍转换元素之前,先来看一下 order-by 和 select 属性。在上面的例子中
已经使用过 xsl:for-each 元素以及这两个属性了。
order-by 属性用于将元素的显示按一定的顺序排列,该属性带有一个“+”
或者“-”的符号,用来定义索引的方式,是升序还是降序排列。符号后
面的名字就是要索引的关键字,例如:

<xsl:for-each select="shoppingCart/item" order-by="+itemNo">

在 xsl:for-each 元素里加上 order-by 属性,显示出来的项目信息都会按照项


目编号升序排列。
如果只显示满足一定条件的 XML 数据应该怎么做呢?这时需要设置元素
的 select 属性值,例如:

<xsl:for-each select="shoppingCart/item[itemName='三国演义']">

即选择了 shoppingCart 结点下的 item 结点的所有子结点,这些子结点还必


须满足其 itemName 为‘三国演义’的条件。后面的操作就只针对满足这个条
件的结点进行。
这里的条件匹配表达式与前面的模板结点匹配条件表达式含义是一样的。
8.4.2 xsl:for-each
xsl:for-each 语法允许循环处理被选择的结点。它带有 select 和 order-by 属性。
由 select 属性决定什么样的结点符合条件,然后循环处理这个结点集合,处
理完的结果按 order-by 属性的规定进行排序。如上面的例子:

<xsl:for-each select="shoppingCart/item" order-by="+itemNo">


<!—item 结点各子结点样式的定义-->
</xsl:for-each>

·175·
·176· XML 实用教程

对某一结点下的内容进行循环输出,一般可用如下方式表示:

< xsl:for-each select="结点的路径" order-by="排序依据" >


<!--结点下各子结点样式的定义-->
< /xsl:for-each >

【例 8.5】 网上书店顾客联系信息的 XML 文档,代码如源程序 code8_5.xml


所示。

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


<?xml-stylesheet type="text/xsl" href="code8_5.xsl"?>
<contactInfo>
<customer>
<name>张三</name>
<email>Jerry@wlw.org</email>
<zipcode>361021</zipcode>
<address>中国福建省厦门市</address>
</customer>
<customer>
<name>李四</name>
<email>Lisi@wlw.org</email>
<zipcode>350001</zipcode>
<address>中国福建省福州市</address>
</customer>
</contactInfo>

·176·
第8章 XSL 转换 ·177·

要显示所有顾客的信息,则可以将 XSLT 代码 code8_5.xsl 写成。

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


<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<xsl:for-each select=".//*">
<div><xsl:value-of select="name"/></div>
</xsl:for-each >
</xsl:template>
</xsl:stylesheet>

在上面的例子中,设置 xsl:for-each 的 select 属性为“.//*”,参考表 8-2,


这个表达式可以理解为“当前结点的任何后裔结点”,即在 xsl:for-each 结
点中对 contactInfo 下的所有层次结点做循环操作。 当然,xsl:for-each 的 select
属性为“contactInfo/customer”更直接,运行速度更快。
8.4.3 xsl:value-of
xsl:for-each 用于选取文档的结点,并没有选取结点的值。而 xsl:value-of 则
用来选择源文档中元素的值写入输出文档。select 属性用来选择相匹配的结
点,如上例:

<xsl:value-of select="name">

选择出结点名为 name 的结点的值。即,若要在 XSL 文档某处插入某个 XML


标记(假定是 xml_mark 标记)的内容,可用如下方式表示。

< xsl:value-of select="xml_mark" ></xsl:value-of >



< xsl:value-of select="xml_mark"/ >

例如,上例中要求取出顾客的全部信息,则可以改写模板文件。

<xsl:template match="/">
<xsl:for-each select="contactInfo/customer">
<div><xsl:value-of select="name"/></div>
<div><xsl:value-of select="email"/></div>
<div><xsl:value-of select="address"/></div>
<div><xsl:value-of select="zipcode"/></div>
</xsl:for-each >
</xsl:template>

执行后,这些结点的值会被显示出来,xsl:value-of 语法说明需要输出一个
结点的值,而 select=“name”则定义需要被输出的元素为 name。整个过程与
数据库中查询数据类似。当然,xsl:value-of 查询方式还有更多,更复杂的
语法,因为是涉及寻找和定位的功能,与 XPath 语法密切相关。有兴趣可
以查阅相关的 Xpath 语法,这里不再介绍。
8.4.4 xsl:choose、xsl:when 和 xsl:otherwise
这 3 个元素组成了程序设计语言中的 switch 语句。xsl:choose 元素类似于
switch 语句的执行多条件判断。而 xsl:when 则是每一个判别,其 test 属性值
就是一个条件表示式。正如 switch 语句中的 default 分支,当所有条件都不
满足时,则执行的是 xsl:otherwise 元素;当条件满足时,元素的内容被得到
应用。一般形式:

·177·
·178· XML 实用教程

< xsl:choose>
<xsl:when test="pattern">
<!--样式定义-- >
</xsl:when>
<xsl:otherwise>
<!--样式定义-- >
</xsl:otherwise>
</xsl:choose>

假设上面的 XML 文档不但有顾客信息而且还有顾客订购书籍的信息。这


时,如果是顾客信息则为姓名设置蓝绿背景色,书籍信息则附加一条说明
订购清单的信息。

<xsl:template match="/">
<xsl:for-each select="contactInfo/*">
<xsl:choose>
<xsl:when test=".[.!nodename()=’customer] ">
<div
style="background-color:teal;font-size:12pt"><xsl:value-of
select="name"/></div>
</xsl:when>
<xsl:otherwise>
<div style="font-size:12pt">您所订购的图书:</div>
<!-- 关于图书的各子结点样式定义 -->
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>

这里的测试条件“.[.!nodeName()=’customer]”意为满足当前结点名为
customer 的所有结点。方法 nodeName()用来取得结点的名称。
8.4.5 xsl:if、xsl:element 和 xsl:attribute
xsl:if 是类似常规程序语言的 if 条件语句,允许设定结点满足某个条件时,
被模板处理。它没有 else 属性,要实现多分支只能用上面所介绍的
xsl:choose。xsl:element 是在输出文档中创建一个元素,而 xsl:atrribute 则是
创建一个属性。
例如当遇到顾客的地址时,需要改变字体大小,并且用粗体显示。可以这
样编写 XSL 文件。

<div>
<xsl:if test=".[.!nodeName()=’address’] ">
<xsl:attribute name="style">font-weight:bold</xsl:attribute>
</xsl:if>
</div>

使用 xsl:attribute 就会在 div 中增加一个属性,这个属性隶属于 div 元素。当


为某些项设置超文本链接,或是显示图形文件时,可以使用这两个元素。
具体请看下例:

·178·
第8章 XSL 转换 ·179·

<hyperlink>
<name>X_Agent</name>
<logo>gw.jpg</logo>
<homepage>http://www.csdn.net</homepage>
</hyperlink >

针对上面的 XML 文档,设计如下 XSL 文档。

<div class="b">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="hyperlink/homepage"/>
</xsl:attribute>
<xsl:element name="img">
<xsl:attribute name="src">
<xsl:value-of select="hyperlink/logo"/>
</xsl:attribute>
</xsl:element>
</xsl:element>
</div>
8.4.6 变量
XSL 还可以利用变量处理信息。可以为变量赋值的元素有 xsl:variable 和
xsl:param。一般 xsl:variable 使用格式:

<xsl:variable name = "变量名" select = "表达式" />


<!-- 内容: 模板 -->
</xsl:variable>

其中,使用 name 属性指定变量名(必须),select 属性用于为新建变量赋值。


如果属性和内容都不存在的话可以写成空字符串。对顾客所订购的书籍进
行统计,就可以使用变量进行。

<xsl:variable name="sum"
select="sum(shoppingcart/shoppingItem/item)"/>

创建了 variable 元素,其 name 属性为 sum,对顾客订购的项目总数进行存


储。select 属性的值为 sum(shoppingcart/shoppingItem/item),这是一个 XPath
表达式,它用于统计 shoppingItem 元素中 item 元素的个数。
定义了新变量 sum 后,可以使用<xsl:value-of select=“$sum”/>来引用变量。
用“$”来引用变量,用 xsl:value 元素输出变量 sum。
xsl:variable 元素和 xsl:param 元素基本上相同。区别在于 XML 解析器假定
xsl:param 变量中保存着默认值,并可以使用 xsl:with-param 元素向模板中传
值。
8.4.7 执行模板
模板不是什么复杂的东西,XSLT 在扫描 XML 文档时一旦遇到匹配结点就
会激活模板。可是,在增加了 XSLT 元素的情况下,就必须控制模板执行
的流程来满足要求。
xsl:apply-templates 元素用在模板内告诉 XSL 处理器把所提供的结点集合匹
配其他模板,其语法格式如下:

<xsl:apply-templates select="expression" mode="mode">

·179·
·180· XML 实用教程
</xsl:apply-templates>

在结点匹配某个模板的情况下,XSLT 通常假定这个模板会专注该结点的所
有内容而不去处理它们。模板内的 xsl:apply-templates 元素则告诉 XSLT 处
理器依次处理子结点内容。xsl:apply-templates 元素的使用可以实现模板的
递归调用。
xsl:apply-templates 默认地处理所有最近的子结点。select 属性可以指定特定
的派生结点进行处理。
那么 XSL 解析器如何知道从哪里开始执行模板呢?对于单模板样式文件,这
不成问题。然而,对于多模板样式文件,必须给处理程序一个提示,
xsl:apply-templates 用来执行哪一个结点被模板具体处理。可以将它理解为
程序中调用子函数。多模板样式表包含一个告知 XSL 解析器从哪里开始的
默认模板。首先执行默认模板,接下来依次处理每一个模板。XSL 寻找应
用于文档根元素的默认模板,例如:

<xsl:template match="/">
<p><xsl:apply-templates /></p>
</xsl:template>

斜杠“/”代表文档的根。XSL 处理程序从这里开始,并且按照模板体的指
令向下继续执行。对于 xsl:apply-templates 元素来说,还有 select 属性用来
定义确切的结点名称。xsl:apply-templates 总是包含在 xsl:template 元素中的。

<xsl:template match="/">
<xsl:apply-templates select="contactInfo"/>
</xsl:template>

这段代码说明模板匹配整个文档(根结点),具体执行时处理根结点下所有的
contactInfo 元素。

<xsl:template match="contactInfo">
<p><xsl:apply-templates/></p>
</xsl:template>

而这一段代码则表示模板匹配 contactInfo 结点,所有 contactInfo 下的子


元素都将被处理。
又如,假如对“/book”和“/book/chapter”都建立了模板,打算用“/book”
模板中的 xsl:apply-templates 来激活“/book/chapter”:

<xsl:template match="/book">
This book is entitled "<xsl:value-of select="title"/>"
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="/book/chapter">
This is chapter <xsl:number/>, entitled " <xsl:value-of
select="title"/>"
</xsl:template>

可以看到多个模板把控制权按照一定的指令链转交给了其他模板。这样做
把 XSLT 文档分解成可读的多个部分,使得模板的重用成为可能。

·180·
第8章 XSL 转换 ·181·

模板调用还有另一种方式就是:xsl:call-template。xsl:call-template 元素按照
名字执行其他模板,它的语法格式:

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

和 xsl:apply-templates 一样,xsl:call-templates 把命令的执行临时转给带有同


样名字属性的另一个模板。在不考虑其匹配值的情况下,被调用模板按照
调用模板同样的上下文环境执行,例如:

<xsl:template match="/book/chapter">
<xsl:call-template name="output-chapter-info"/>
</xsl:template>
<xsl:template name="output-chapter-info">
The name of chapter <xsl:number/> is "<xsl:value-of
select="title"/>".
</xsl:template>

应该注意的是,xsl:apply-templates 和 xsl:call-template 都用终止斜线代替封


闭标记。封闭标记用来嵌套其他附着于特定指令或者参数的 XSLT 元素
8.4.8 完整的样式表实例
上面讲解了 XSLT 基本转换语言,以下是一个完整的网站购物车的 XML 文
档,包含有订购商品的顾客信息以及他所订购的商品信息。
【例 8.6】 网站购物车的 XML 文档,代码如源程序 code8_6.xml 所示。

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


<?xml-stylesheet type="text/xsl" href="code8_7.xsl"?>
<shoppingcart>
<customer>
<name>赵子龙</name>
<email>Jerry@wlw.org</email>
<zipcode>361021</zipcode>
<address>中国福建省厦门市</address>
</customer>
<shoppingItem>
<item>
<itemNo>1001</itemNo>
<itemName>三国演义</itemName>
<price>30.00</price>
<publisher>文艺出版社</publisher>
</item>
<item>
<itemNo>1002</itemNo>
<itemName>红楼梦</itemName>
<price>120.00</price>
<publisher>文艺出版社</publisher>
</item>
</shoppingItem>
</shoppingcart>

·181·
·182· XML 实用教程

现在为上述网站购物车的 XML 文档编写一个样式表文件,将其转换为


HTML。
【例 8.7】 其相应转换文件,代码如源程序 code8_7.xsl 所示。

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


<xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">
<xsl:template match="/">
<html>
<head>
<title>书籍订单——E-shop</title>
<style> .title{font-size:15pt; font-weight:bold;
color:blue } .name {color:red} </style>
</head>
<xsl:apply-templates/>
</html>
</xsl:template>
<xsl:template match="shoppingcart">
<body><xsl:apply-templates/></body>
</xsl:template>
<xsl:template match="shoppingcart/customer">
<div style="background-color:teal; font-weight:bold;">
<xsl:value-of select="name"/>
</div>
<div>
<xsl:value-of select="email"/>
</div>
<div>
<xsl:value-of select="address"/>
</div>
<div>
<xsl:value-of select="zipcode"/>
</div>
</xsl:template>
<xsl:template match="shoppingcart/shoppingItem">
<table border="1">
<thead>
<td><b>编 号</b></td>
<td<b>书 名</b> </td>
<td><b>价 格</b></td>
<td><b>出 版 社</b></td>
</thead>
<xsl:for-each select="./item" order-by="itemNo">
<tr>
<td><b><xsl:value-of
select="itemNo"/></b></td>
<td><xsl:value-of select="itemName"/></td>
<td><xsl:value-of select="price"/></td>
<td><xsl:value-of select="publisher"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>

在上面的例子中,一共设计有 4 个模板。
(1) 根结点模板:<xsl:template match="/">。
(2) cart 结点模板:<xsl:template match="shoppingcart">。

·182·
第8章 XSL 转换 ·183·

(3) 顾客联系信息结点模板:<xsl:template match="shoppingcart/ customer">。


(4) 购物清单信息结点模板:<xsl:template
match="shoppingcart/shoppingItem">。
在 XML 文档加入<?xml-stylesheet type="text/xsl" href="code8_7.xsl"?>,建立
XML 文档与 XSL 文档的关联。当浏览器装载样式表之后,XSL 解析器装
载源文档。然后,从源文档的根到叶子结点进行遍历,在每一步都试图将
当前结点与模板进行匹配。解析器首先查找根结点,与根结点相对应的有
根模板:

<xsl:template match="/">
<html>
<head>
<title>书籍订单——E-shop</title>
<style> .title{font-size:15pt; font-weight:bold;
color:blue } .name {color:red} </style>
</head>
<xsl:apply-templates/>
</html>
</xsl:template>

这个模板与 XML 文档的根匹配,用于创建输出文档的根元素: html 和 head。


在遇到 apply-templates 时,解析器移到当前结点的子结点并重复这个过程,
即试图将子结点和其他模板匹配。因为当前结点是根,它只有一个子结点
shoppingcart,所以解析器找到与 shoppingcart 结点相匹配的模板进行匹配:

<xsl:template match="shoppingcart">
<body>
<xsl:apply-templates/>
</body>
</xsl:template>

根据模板,解析器创建输出文档的 body 结点。此时又遇到 apply-templates,


因此解析器又查找 shoppingcart 的子结点进行模板匹配。shoppingcart 有两
个子结点:customer 和 shoppingItem。先找到 customer 结点相匹配的模板,
进行转换处理:

<xsl:template match="shoppingcart/customer">
<div style="background-color:teal;
font-weight:bold;"><xsl:value-of select="name"/> </div>
<div><xsl:value-of select="email"/></div>
<div ><xsl:value-of select="address"/></div>
<div ><xsl:value-of select="zipcode"/></div>
</xsl:template>

由此在输出文档中,生成顾客的联系信息。这个模板里不包含
apply-templates,因为已经处理了 customer 的所有子结点,无须再向下遍历。
解析器处理完 customer 结点后,退回到它的上级结点 shoppingcart,然后再
查找 shoppingcart 结点的其他子结点,发现 shoppingItem 结点及相匹配的模
板:

<xsl:template match="shoppingcart/shoppingItem">

·183·
·184· XML 实用教程
<table border="1">
<thead>
<td><B>编 号</B></td>
<td><B>书 名</B></td>
<td><B>价 格</B></td>
<td><B>出 版 社</B></td>
</thead>
<xsl:for-each select="./item" order-by="itemNo">
<tr>
<td><b><xsl:value-of select="itemNo"/></b></td>
<td><xsl:value-of select="itemName"/></td>
<td><xsl:value-of select="price"/></td>
<td><xsl:value-of select="publisher"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>

这个模板在输出文档中列出顾客订购的书籍清单。至此,完成整个 XML 文
档的转换。可以看出,apply-templates 是对样式表的递归调用,类似于对树
进行优先搜索。上例转换出来的效果如图 8.4 所示。

图 8.4 购物车 XML 文档经过转换后的结果


8.5 使用 XML Spy 建立 XSLT 文档
可以利用 XML Spy 创建 XSLT 文档。但 XSLT 文档相对来说,类似于编程,因
此大部分代码还是要进行编写。下面针对开始时的简单转换来讲解建立的过程。
选择菜单 File | New 弹出 Create new document 对话框,选择里面最后一项 XSLT,
建立的新 XSLT 文件如图 8.5 所示。此时 XML Spy 会将 Grid 视图自动转到 Text
视图区,因为直接编辑 XSLT 文档更为方便一些。将其编码方式改为 gb2312。

·184·
第8章 XSL 转换 ·185·

图 8.5 在 XML Spy 中新建一个 XSLT 文件


其余的代码可以通过 Elements 面板方便地添加到编辑区中。添加
完毕,设置相应的结点为各元素的属性值即可完成 XSLT 文档的
编写,也可以直接进行编写。完成后如图 8.6 所示,并保存起来。

图 8.6 编写后的 XSLT 文档


保存后,首先可以指定该文档的 XSLT 文档,通过菜单 XSL | Assign
XSL 指定。然后,选择 XSLT | XSL Transformation 直接在 XML Spy
中查看转换后的最终显示效果。
8.6 小 结
XSLT 是一种功能强大的语言,XSLT 可以说是 XML 最好的发展,它使得将 XML
文档转换为多种格式成为可能。可以将文档转换成另一个 XML 文档,或是 HTML
页面,甚至语音、乃至视频/多媒体表示格式。还可以将它转换为 PDF 或 RTF
格式,从而可以用文字处理程序读取。但 XSLT 只是一种说明性的计算机语言,
需要其他工具来实现转换。

·185·
·186· XML 实用教程

XSL 由两部分组成:第一部分是 XSLT,可以把 XML 文档从一种格式转换为另


一种格式。它使用 XPath 匹配结点,把一个 XML 文档转换为另一个不同的文档。
得到的文档可以是 XML、HTML、无格式文本或任何其他基于文本的文档。第
二部分是 XSL 格式化对象(Formatting Object)。格式化对象提供了 CSS 的另一种
方式来格式化 XML 文档,并把样式应用到 XML 文档上。因此,XSL 在转换
XML 文档时分为明显的两个过程,首先转换文档结构,其次将文档格式化输出。
为了用 XSL 来处理一个 XML 文档,需要一个带有 XSL 引擎的 XML 解析器。
MSXML 2.0 是 IE 5.0 所携带的 XML 解析器,Windows XP 所用的是 MSXML 4.0。
通常用 XSL 作为模板,将 XML 文档输入,由转换引擎(如 MSXML 解析器)按
模板规定输出需要的文档格式。这就是一个 XSL 转换的基本过程。
XSL 文档也采用 XML 语言进行编写,主要用来定义转换的模板,模板是 XSLT
中最重要的概念之一,即用模板将同样的格式应用于一个 XML 文档的重复元
素。在某些元素下,模板就是要应用的规则。可以将模板看成一个模块,不同
的模块完成不同的文档格式转换。为了与模板匹配,必须能够描述应该在怎样
的条件下与怎样的结点相匹配。用于指示匹配的元素的语言就是 XPath。使用
XPath 来从 XML 文档中选取出要进行操作的结点,接着就需要使用 XSL 定义的
元素来转换这些结点。包括 xsl:for-each 允许循环处理被选择的结点,xsl:for-each
用于选取文档的结点,xsl:value-of 用来选择源文档中元素的值写入输出文档。
xsl:choose、xsl:when 和 xsl:otherwise 元素组成了程序设计语言中的 switch 语句。
xsl:if 类似常规程序语言的 if 条件语句,允许设定结点满足某个条件时,被模板
处理。它没有 else 属性,要实现多分支只能用上面所介绍的 xsl:choose。xsl:element
是在输出文档中创建一个元素,而 xsl:atrribute 则是创建一个属性。
实现 XSLT 的方式主要有两种:一种是在服务器端实现文档的转换,XML 文档
在发布之前被转换为 HTML。这是比较安全的转换,不必考虑用户使用浏览器
的种类,保证了与全部使用者兼容。第二种情况下,XML 文档和样式表等文档
被发送给浏览器,由浏览器使用自己的 XSL 解析器来处理样式表并显示结果。
8.7 习 题
1. XSL 有什么用途?为什么要使用 XSL?它主要由哪几部分组成?
2. XSLT 与 CSS 的区别有哪些?
3. XSLT 的解析器有哪些?解析器的用途是什么?
4. 简述 XSLT 的执行过程。
5. 简述 template 和 apply-templates 元素的用途和两者之间的关系。
6. XPath 有什么用途?
7. 如何建立 XML 文档与 XSLT 的关联。
8. 下面是有关学生的 students.xml 文档,请编写出相应的 XSLT 文档将其转换成
的 HTML 格式,以表格的方式显示数据。

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


<student>
<info name="Zhang San">
<number>A1001</number>
<address>HeBei</address>
<study_year>2</study_year>
</info>
<info name="Xiao Ming">
<number>A1002</number>
<address>HuBei</address>

·186·
第8章 XSL 转换 ·187·

<study_year>2</study_year>
</info>
<info name="ChenKai">
<number>A1003</number>
<address>XingJiang</address>
<study_year>2</study_year>
</info>
</student>

9. 下面是有关个人简历的 XML 文档,请编写出相应的 XSLT 文档将其转换成的


HTML 页面,以表格的方式显示数据。转换的结果如本题附图 8.7 所示。

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


<resume>
<objective>
<position>Software Project Manager</position>
<company>Inter Co.</company>
</objective>
<PersonalInformation>
<name>Zhang San</name>
<sex>male</sex>
<age>25</age>
<major>Software Engineering</major>
<school>MIT</school>
<tel>123456</tel>
<cell>654321</cell>
<degree>Master Degree</degree>
</PersonalInformation>
<EducationBackground>
<background>
<time>2000-2002</time>
<major>Software Engineering</major>
<Department>Department of Computer Science and
Technology</Department>
<school>MIT</school>
</background>
<background>
<time>1996-2000</time>
<majore>English Literature</majore>
<department>Department of English Literature</department>
<school>CIT</school>
</background>
</EducationBackground>
</resume>

·187·
·188· XML 实用教程

图 8.7 结果图

·188·
第 9 章 XML 文档对象模型

教学提示:HTML 和 XML 都属于层状数据结构的文档,要求以编程方式读取、操作


和修改这种文档,这就需要 DOM 技术。DOM 把 XML 文档看成是在内存中的结构树,它
定义了一组标准指令集,通过程序存取“树上”的 HTML 或 XML 的内容,然后通过程序
中的对象集合将其显示出来。本章介绍文档对象模型的概念和基本知识,以实例说明客户
端和服务器端加载 XML 的方法和出错处理,解析 XML 的结点接口。
教学目标:理解文档对象模型的概念,熟悉文档对象模型的基本知识,掌握客户端和
服务器端加载 XML 的方法,学会用 DOM 编制 ASP 程序。

9.1 DOM 基础知识

利用 DOM,程序开发人员可以动态地创建文档,遍历文档结构,添加、修改、删除文
档内容,改变文档的显示方式等。

9.1.1 DOM 的概念和组成

DOM 全称为 Document Object Model,是一个文件对象所组成的模型。对于 XML 应用


和开发来说,DOM 就是一个对象化的 XML 数据接口,一个与语言无关、与平台无关的标
准接口规范。它定义了 HTML 和 XML 文档的逻辑结构,给出了一种访问和处理 HTML、
XML 文档的方法。
作为 W3C 的标准接口规范,目前 DOM 由 3 部分组成,包括:核心(core)、HTML 和
XML。核心部分是结构化文档比较底层对象的集合,所定义的对象已经完全可以表达出任
何 HTML 和 XML 文档中的数据了。HTML 和 XML 接口两部分则是专为操作具体的 HTML
和 XML 文档所提供的高级接口,使对这两类文件的操作更加方便。
XML DOM 包含 4 个主要对象:XML DOM Document,XML DOM Node,XML DOM
NodeList 和 XML DOM NamedNodeMap。与任何其他对象模型一样,每个 XML DOM 对象
都有其自己的特性和方法。

9.1.2 DOM 结构模型

DOM 对象映射了 XML 文档的树状结构,为用户提供的访问 XML 文档信息的媒介是


一种分层对象模型,而这个树状结构,则是一棵根据 XML 文档生成的结点树。
一个 XML 分析器,在对 XML 文档进行分析之后,不管这个文档简单或复杂,其中的
信息都会被转化成一棵对象结点树。在这棵结点树中,有一个根结点——document 结点,
所有其他的结点都是根结点的后代结点。结点树生成之后,则可以通过 DOM 接口访问、
·190· XML 实用教程

修改、添加、删除、创建树中的结点和内容。
将第 1 章如图 1.4 所示的 XML 层次模型实例补全 book 结点的 5 个属性成为如图 9.1
所示 DOM 树状结构实例,这就是文档 code1_2.xml 的 DOM 结构树,只是内用有些变动。
图中矩形框表示结点,椭圆形框表示属性。显然,这棵结点树是可以依照规律遍历或访问
的。

图 9.1 DOM 树状结构实例

在 DOM 中,将代表 XML 文档的程序设计对象,称为结点(nodes)。当 IE 处理被链接


的 XML 文件并存储于 DOM 中时,它会为 XML 文档的每一个基本组件建立一个结点。这
些基本组件包括了元素、属性与处理指令。DOM 会使用不同类型的结点来代表不同类型的
XML 组件。例如,元素存储在 element 结点中,而属性则存储在 attribute 结点中。这些结
点类型最重要的部分见表 9-1。
DOM 本质上是结点的集合。由于一个文档中可能包含不同类型的信息,因此要定义
不同类型的结点。表 9-1 用来表示不同 XML 文档组件的基本结点形态。这些类型的每一
个结点都是一个程序设计对象,提供了存取相关组件的属性与方法。
元素和结点是不同的概念。元素只是结点的一种类型,它们甚至不表示要揭示的内容。
元素结点是信息的容器。该信息可能是其他元素结点、文本结点、属性结点或其他类型的
信息。当一个结点包含在另一个结点之内时,它就被认为是子结点。
每个结点的名称(详列表 9-1 中的第三栏)可以从结点中的 nodeName 属性获得。每个
结点的结点值(列于表 9-1 中最后一栏)可以从结点的 nodeValue 属性取得。如果 XML 组件
拥有一个相关的值(例如属性),该值将会被存储于结点的结点值中。如果 XML 组件并没有
结点值(例如元素),则 DOM 将会把结点值设成 null。

·190·
第9章 XML 文档对象模型 ·191·

表 9-1 XML 文档组成和 DOM 结点类型、结点名称、结点值的对应关系

XML 组成 结点类型 结点名称(nodeName 对象属性) 结点的值(nodeValue 对象属性)


文档 document #document null
元素 element 元素实际名称(如 book) null(元素中的任何数据在文字结点中)
文字 text #text 父 XML 组件的文字
属性 attribute 属性名称(如 amount) 属性值(例如 hardcover)
Processing 除了处理指令的内容(例如 version =
处理指令 处理指令的目标(如 xml)
Instruction “1.0”)
批注 comment #comment 在批注符号中的文字
CDATA 节 CDATA section #cdata-section CDATA 节中的内容
文档类型 Document Type DTD 声明中的根元素名称 null
实体 entity 实体名称(如 image) null,实体值是位在子文字结点中
符号 notation 符号实际名称(如 BMP) Null,在 system 的 Attribute 子结点中

DOM 会将 XML 文档的结点建构成树状的层次结构,反映出 XML 文档本身的层次结


构。DOM 将建立一个单一文档结点来表示整个 XML 文档,并将其视为层次结构的根结点。
注意,XML 元素的逻辑层次结构包含了整个 XML 文档,结构中的根结点,只是 DOM 结
点的层次结构的一个分支。
每个结点就像可程序化的对象,提供了属性和方法,以便存取、显示、管理和取得对
应到 XML 组件上的信息。
各种类型的结点分享一组公共的属性与方法。这些共有属性见表 9-2。

表 9-2 DOM 结点的共有属性

属 性 描 述 范 例
该结点的所有非属性的子结点的 AttributeNode=Element.attributes.getName
attributes
NamedNodeMap 集合 dItem (“amount”);
该结点的所有非属性的子结点的 NodeList
childNodes FirstNode =Element.childNodes(0);
集合
该结点的数据类型(只适用于某些类型
dataType AttributeType =Attribute.dataType;
Attribute 结点)
firstChild 该结点的第一个非属性的子结点 FirstChildNode =Element.firstChild;
lastChild 该结点的最后一个非属性的子结点 LastChildNode =Element.lastChild;
nextSibling 与本结点位于同一层级的后继前一结点 NextElement =Element.nextSibling;
nodeName 结点的名称 ElementName =Element.nodeName;
nodeType 表示该结点类型的数值码 NodeTypeCode =Node.nodeType;
包含该结点类型的字符串,以小写字母撰写
nodeTypeString NodeTypeString=Node.nodeTypeString;
(例如,element 或 attribute)

·191·
·192· XML 实用教程

续表
属 性 描 述 范 例
nodeValue 该结点的值(如果不含值则为 null) AttributeValue =Attribute.nodeValue;
ownerDocument 包含本结点的文档的根 document 结点 Document =Node.ownerDocument;
parentNode 该结点的父结点(并不适用于 attribute 结点) ParentElement =Element.parentNode;
previousSibling 与本结点位于同一层级的先前结点 PreviousElement =Element.previousSibling;
text 该结点与其后裔结点的全部文字内容 AllCharacterData =Element.text;
xml 该结点与其后裔结点的全部 XML 内容 XMLContent =Element.xml;

除了共同的属性和方法外,每种类型的结点都提供了附加的属性和方法,来处理该结
点类型所代表的特殊 XML 组件。例如,文档结点(document)提供了 parseError 属性,内含
任何处理文档时所产生错误的相关信息。只有文档结点拥有这种属性。
如果某个属性不适用于特定结点,则该属性将包含 null 值。例如,如果某结点代表一
个不包含任何属性的 XML 文档(如 document 或 commentNode)时,其 attributes 属性将被设
为 null。如果某结点代表某个不含有任何数据类型(只有某些属性拥有数据类型)的 XML 组
件时,该结点的 dataType 属性将被设为 null。如果结点并没有任何非属性的子结点,其
firstChild 属性将被设为 null。而如果结点为不含值的类型(如 document 或 elementNode),其
nodeValue 属性将被设为 null。
表 9-2 中每个结点拥有一组属性,可以浏览结点的层次架构,来从目前结点存取其他
结点的资料。例如,在表 9-1 中的文档,如变量 document 包含了文档的 document 根结点,
后续的程序代码将会显示最接近文档起始部分批注的内容,而 DOM 会将批注内容存储在
document 结点的第二个子结点中。

9.1.3 创建 document 对象

通过上面的介绍,大家已经对 DOM 结点的属性和方法有了部分了解,现在来研究如


何运用 DOM 技术。首先,创建 document 对象,这是一切操作的基础。通过创建 document
对象,应用程序或者脚本就得到了对 XML 文档进行操作的入口。下面给出了使用不同的
编程语言创建 document 对象的方法。
对于 JavaScript:
var xmlDom = new ActiveXObject("MSXML2.DOMDocument.4.0")

对于 VBScript:
set xmlDom = CreateObject("MSXML2.DOMDocument.4.0")

对于 VB:
Dim xmlDom As ObjectSet
xmlDom = CreateObject("MSXML2.DOMDocument.4.0")

或者
Dim xmlDom As DOMDocument
Set xmlDom = New DOMDocument

·192·
第9章 XML 文档对象模型 ·193·

对于 ASP(VBScript):
set xmlDom = Server.CreateObject("MSXML2.DOMDocument.4.0")

建立 XML DOM 以后,就可以用 load 方法加载 XML 文件,如:


xmlDom.load("code9_1.xml")

载入的文件可以视为一个树状结构的结点,其具有的属性见表 9-3。

表 9-3 DOM 对象结点属性

DOM 对象 说 明

document 树状结构的根结点
node 结点对象,新增、删除和修改结点对象
nodelist 结点列表对象,就是制定结点子结点的整个树状结构
element XML 元素对象,也就是元素结点
text XML 元素内容对象,也就是内容结点
parseerror 解析器错误处理对象,如有错误,返回加载时的错误信息

9.2 客户端加载 XML

客户端加载的 XML 有 3 种来源,包括外部 XML 文件、XML 文档字符串和带有 XSLT


脚本的外部 XML 文件。分别予以讨论。

9.2.1 加载外部 XML 文件

在 document 对象创建之后,就得到了对文档进行操作的入口,这个文档对象可以与实
际的 XML 文档关联在一起。在 W3C 的 DOM 接口规范中,没有任何一个地方定义了 DOM
中的接口对象同实际文档相关联的方法。因此,不同的 XML 分析器所提供的加载 XML 文
档的方法也不尽相同。在 Microsoft 公司的 MSXML 解析器中,提供了一个 load 方法来加
载 XML 文档,建立 DOM 树同 XML 文档之间的关联。
以图书信息表的 XML 文档 code9_1.xml 为例,VBScript 可通过下述方式来加载文档:
Dim xmlDom
' 建立 XML DOM 对象
Set xmlDom = CreateObject("MSXML2.DOMDocument.4.0")
' 设置 xmlDom 的 async 为 false,即异步为假,保证 XML 解析器暂停执行,直到 XML 文件加
载完成
xmlDom.async = false
' 加载 XML 文件
xmlDom.load("code9_1.xml")

XML 文档被加载后,就在内存中形成了一棵如图 9.1 所示的 DOM 树。


与之对应的 JavaScript 加载外部 XML 文件的代码如下:

·193·
·194· XML 实用教程

// 建立 XML DOM 对象
var xmlDom = new ActiveXObject("MSXML2.DOMDocument.4.0")
xmlDom.async = "false"
// 加载 XML 文件的字符串
xmlDom.load("code9_1.xml")

【例 9.1】 显示加载的外部 XML 文件的所有元素值,代码如源程序 code9_1.htm 所示。


<html>
<head><title>显示 XML 文档所有元素值</title><body>
<center><b>显示加载的外部 XML 文件所有元素值</b></center>
<hr>
<table border=1>
<tr><td>结点</td>
<td>内容</td>
</tr>
<script language="VBScript">
' 建立 XML DOM 对象
set xmlDom = CreateObject("MSXML2.DOMDocument.4.0")
' 设置 xmlDom 的 async 为 false,即异步为假,保证 XML 解析器暂停执行,直到 XML 文件加
载完成
xmlDom.async = "false"
'加载 XML 文件
xmlDom.load("code9_1.xml")
' 显示所有的 XML 结点
for each objNode in xmlDom.documentElement.childNodes
document.write("<tr><td>" & objNode.nodename & "</td>")
document.write("<td>" & objNode.text & "</td></tr>")
next
</script>
</table>
</body>
</html>
被例 9.1 加载的 XML 文件为 code9_1.xml。
<?xml version="1.0" encoding="gb2312"?>
<books>
<book id="0001" bookcategory="文艺" amount="150" remain="80"
discount="8.5">
<title>三国演义</title>
<author>罗贯中</author>
<publisher>文艺出版社</publisher>
<ISBN>0-764-58007-8</ISBN>
<price>80</price>
</book>
<book id="0002" bookcategory="文艺" amount="300" remain="180"
discount="8.7">
<title>红楼梦</title>
<author>曹雪芹</author>
<publisher>三秦出版社</publisher>
<ISBN>7805468397</ISBN>
<price>22</price>

·194·
第9章 XML 文档对象模型 ·195·

</book>
<book id="0003" bookcategory="文艺" amount="200" remain="175"
discount="8.5">
<title>西游记(上下册)</title>
<author>吴承恩</author>
<publisher>人民文学出版社</publisher>
<ISBN>7020008739</ISBN>
<price>40.12</price>
</book>
<book id="0004" bookcategory="文艺" amount="300" remain="192"
discount="8.7">
<title>水浒传(上下册)</title>
<author>吴承恩</author>
<publisher>时代文艺出版社</publisher>
<ISBN>7538714014</ISBN>
<price>40.85</price>
</book>
<book id="0065" bookcategory="文学" amount="120" remain="86"
discount="8.0">
<title>外国文学史(亚非卷)</title>
<author>朱维之</author>
<publisher>南开大学出版社</publisher>
<ISBN>7-310-01122-8</ISBN>
<price>20</price>
</book>
<book id="0076" bookcategory="文学" amount="130" remain="84"
discount="8.0">
<title>二十世纪欧美文学简史</title>
<author>李明滨</author>
<publisher>北京大学出版社</publisher>
<ISBN>7-301-04616-2</ISBN>
<price>21.8</price>
</book>
<book id="0098" bookcategory="文学" amount="140" remain="76"
discount="7.0">
<title>西方文艺理论名著教程(上)</title>
<author>胡经之</author>
<publisher>北京大学出版社</publisher>
<ISBN>7-301-00649-7</ISBN>
<price>24</price>
</book>
<book id="0012" bookcategory="文学" amount="210" remain="60"
discount="8.5">
<title>西方文艺理论名著教程(下)</title>
<author>胡经之</author>
<publisher>北京大学出版社</publisher>
<ISBN>7-301-00179-7</ISBN>
<price>23</price>
</book>
<book id="0036" bookcategory="文学" amount="100" remain="80"
discount="8.3">

·195·
·196· XML 实用教程

<title>中国文学理论批评史教程</title>
<author>张少康</author>
<publisher>北京大学出版社</publisher>
<ISBN>7-301-04091-1</ISBN>
<price>25</price>
</book>
<book id="0018" bookcategory="计算机" amount="200" remain="100"
discount="8.2">
<title>计算机导论</title>
<author>丁跃潮等</author>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<price>19.7</price>
</book>
<book id="0218" bookcategory="计算机" amount="400" remain="300"
discount="8.5">
<title>程序设计基础</title>
<author>张杰敏主编</author>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-012652-4</ISBN>
<price>17.6</price>
</book>
<book id="0318" bookcategory="计算机" amount="100" remain="60"
discount="8.0">
<title>数据结构与算法</title>
<author>王晓东编</author>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-013204-4</ISBN>
<price>21.8</price>
</book>
<book id="0181" bookcategory="计算机" amount="250" remain="156"
discount="8.0">
<title>XML Web Service 开发</title>
<author>微软公司著</author>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-015825-6</ISBN>
<price>65.00</price>
</book>
<book id="0189" bookcategory="计算机" amount="230" remain="160"
discount="8.0">
<title>VB.NET 程序设计语言</title>
<author>微软公司著</author>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-013188-9</ISBN>
<price>86.00</price>
</book>
<book id="0028" bookcategory="计算机" amount="100" remain="90"
discount="7.5">
<title>JavaScript 速成教程</title>
<author>Michael Moncur 著</author>
<publisher>机械工业出版社</publisher>

·196·
第9章 XML 文档对象模型 ·197·

<ISBN>7-111-09070-5</ISBN>
<price>28.00</price>
</book>
<book id="0074" bookcategory="计算机" amount="130" remain="78"
discount="7.8">
<title>软件工程 Java 语言实现</title>
<author>Stephen R. Schach</author>
<publisher>机械工业出版社</publisher>
<ISBN>7-111-06714-2</ISBN>
<price>51.00</price>
</book>
<book id="0109" bookcategory="计算机" amount="210" remain="160"
discount="8.0">
<title>人工智能</title>
<author>Nils J. Nilsson 著</author>
<publisher>机械工业出版社</publisher>
<ISBN>7-111-04738-6</ISBN>
<price>45.00</price>
</book>
<book id="0305" bookcategory="计算机" amount="115" remain="26"
discount="7.5">
<title>ASP 开发实例</title>
<author>清汉计算机工作室编著</author>
<publisher>机械工业出版社</publisher>
<ISBN>7-980039-74-2</ISBN>
<price>53.00</price>
</book>
</books>

例 9.1 的显示结果如图 9.2 所示。

图 9.2 显示加载的外部 XML 文件的所有元素值

程序 code9_1.htm 的代码是通用的,
对于加载的任何 XML 文件,
都能把与根结点(document
Element)直接相连的每个子结点(objNode)列出来,并把这些子结点下的各层次结点文本值

·197·
·198· XML 实用教程

显示出来。根结点下直接相连的子结点为 documentElement.childNodes。每个循环不需要循
环控制变量,它循环的次数由所涉及的结点集下的结点数决定,这给编程带来了极大的
方便。
注意,XML DOM 技术的运用需要 XML 解析器,因此本章实例在 Windows 系统中运
行需要安装有 MSXML 解析器才能正确显示。常用的 MSXML 解析器是 2003 年 4 月的
MSXML 4.0 sp2 版本。如果已安装有 2001 年 4 月的 MSXML 4.0 试用版,可能导致某些结
果不能正确显示,需要先卸载,命令提示符下的命令为:
regsvr32/u msxml4.dll

虽然微软公司在 2005 年 11 月推出了 MSXML 6.0,但它还不是广泛使用并被证明成熟


的解析器。

9.2.2 加载 XML 文档字符串

XML DOM 对于代表 XML 文档的字符串也能进行加载,效果与加载外部 XML 文件一


样,只是要事先构造这种体现 XML 元素和结点的字符串。加载 XML 字符串的脚本语言与
加载外部 XML 文件类似,
只需要把 xmlDom.load(“code9_1.xml”)一句改为 xmlDom.loadXML
(xmlStr),其中 xmlStr 就是所构成的 XML 文档字符串。
VBScript 可通过下述方式来加载 XML 字符串 xmlStr:
dim xmlDom
' 建立 XML DOM 对象
set xmlDom = CreateObject("MSXML2.DOMDocument.4.0")
' 设置 xmlDom 的 async 为 false,即异步为假,保证 XML 解析器暂停执行,直到 XML 字符串
加载完成
xmlDom.async = false
' 加载 XML 字符串
xmlDom.loadXML(xmlStr)

XML 文档被加载后,就在内存中形成一棵与图 9.1 类似的 DOM 树。


与之对应的 JavaScript 加载 XML 字符串的代码如下:
// 建立 XML DOM 对象
var xmlDom = new ActiveXObject("MSXML2.DOMDocument.4.0")
xmlDom.async = "false"
// 加载 XML 文件的字符串
xmlDom.loadXML(xmlStr)

【例 9.2】 显示加载的 XML 字符串的所有元素,代码如源程序 code9_2.htm 所示。


<html>
<head>
<title>显示 XML 字符串中所有元素值</title>
<body>
<center><b>显示加载的 XML 字符串所有元素值</b></center>
<hr>

·198·
第9章 XML 文档对象模型 ·199·

<table border=1>
<tr><td>结点</td>
<td>内容</td>
</tr>
<script language="JavaScript">
// 建立 XML 元素的字符串
var xmlStr = "<books>"
xmlStr = xmlStr + "<book>"
xmlStr = xmlStr + "<title>三国演义</title>"
xmlStr = xmlStr + "<author>罗贯中</author>"
xmlStr = xmlStr + "<publisher>文艺出版社</publisher>"
xmlStr = xmlStr + "<ISBN>0-764-58007-8</ISBN>"
xmlStr = xmlStr + "<price>80</price>"
xmlStr = xmlStr + "</book>"
xmlStr = xmlStr + "<book>"
xmlStr = xmlStr + "<title>红楼梦</title>"
xmlStr = xmlStr + "<author>曹雪芹</author>"
xmlStr = xmlStr + "<publisher>三秦出版社</publisher>"
xmlStr = xmlStr + "<ISBN>7805468397</ISBN>"
xmlStr = xmlStr + "<price>22</price>"
xmlStr = xmlStr + "</book>"
xmlStr = xmlStr + "<book>"
xmlStr = xmlStr + "<title>西游记(上下册)</title>"
xmlStr = xmlStr + "<author>吴承恩</author>"
xmlStr = xmlStr + "<publisher>人民文学出版社</publisher>"
xmlStr = xmlStr + "<ISBN>7020008739</ISBN>"
xmlStr = xmlStr + "<price>40.12</price>"
xmlStr = xmlStr + "</book>"
xmlStr = xmlStr + "</books>"
var xmlDom = new ActiveXObject("MSXML2.DOMDocument.4.0")
//设置 xmlDom 的 async 为 false,即异步为假,保证 XML 解析器暂停执行,直到 XML 字符串
加载完成
xmlDom.async = "false"
// 加载 XML 文件的字符串
xmlDom.loadXML(xmlStr)
var objNode = xmlDom.documentElement.childNodes
// 显示所有的 XML 结点
for (i=0; i< objNode.length; i++){
document.write("<tr><td>" + objNode.item(i).nodeName + "</td>")
document.write("<td>" + objNode.item(i).text + "</td></tr>")
}
</script>
</table>
</body>
</html>
其显示结果如图 9.3 所示。

·199·
·200· XML 实用教程

图 9.3 显示加载的 XML 字符串中的所有元素值

本例用了很多代码“编造”XML 字符串 xmlStr,这个构造的字符串就相当于一个 XML


文档。代码其余的部分与例 9.1 类似,只是采用了 JavaScript。

9.2.3 加载 XML 文件及其转换文件

对于已指定转换文件的 XML 文件,可以用在 HTML 文档中将两者都予以加载,然后


用 XML DOM 的 transformNode 方法实现转换,转换的结果可以通过支持 DSO 的 HTML
元素的 innerHTML 属性将 XML 文档结点的信息正确地显示。
【例 9.3】 同时加载 XML 文件及其转换文件,显示图书信息,代码如源程序 code9_3.htm
所示,XML 文件为 code9_1.xml,转换文件为 code9_1.xslt。
<html>
<head>
<title>XML DOM 加载 XML 文件及其转换文件</title>
</head>
<script for="window" event="onload" language="JavaScript">
// 建立 XML DOM 对象
var xmlDom = new ActiveXObject("MSXML2.DOMDocument.4.0")
xmlDom.async = "false"
// 加载 XML 文件
xmlDom.load("code9_1.xml")
// 建立 XML DOM 对象
var xslDom = new ActiveXObject("MSXML2.DOMDocument.4.0")
xslDom.async = "False"
// 加载 XSLT Script
xslDom.load("code9_1.xslt")
xml_target.innerHTML = xmlDom.transformNode(xslDom)
</script>
<body>
<div id="xml_target"></div>
</body>
</html>
其显示结果如图 9.4 所示。

·200·
第9章 XML 文档对象模型 ·201·

图 9.4 同时加载 XML 文件及其转换文件并显示图书信息

程序 code9_3.htm 中的<html>、<body>、<head>、<title>几个标记的语句可以去掉,不
影响转换显示的效果。

9.3 服务器端加载 XML

在服务器端加载 XML 与在客户端加载 XML 类似,区别在于创建 XML DOM 时用


Server.CreateObject 方法;加载 XML 文件、XSLT 转换文件等的路径要用 Server.MapPath
方法确定。在服务器上创建了 DOM 对象之后,既可以自己构造新的 XML 文档,也可以装
载一个现有的文档。如果是装载现有文档,还可以选择是读取 XML 文档字符串,还是打
开 XML 文档并装载其内容。在装载 XML 文档之前,应该把 DOM 对象的 async 属性设置
成 false,这是告诉 DOM 对象装载 XML 文档不是异步进行的。这一点非常重要,因为读
入 XML 文档之后将立即开始使用它,如果此时文档还没有全部装载完毕,试图访问它就
会引发错误。

9.3.1 服务器端加载 XML 文件并显示所有元素

在 DOM 对象中已经有了一个格式良好的、合法的文档后,就可以用这个文档来进行
结点元素及其属性的处理了。DOM 提供了许多精确分析文档内容的方法。由于 DOM 将文
档内容描述成一棵嵌套结点所组成的树(每个结点由一个元素及其所有子元素构成),所以
处理 XML 数据实际上归结为处理一系列的结点对象。可以用 getElementsByTagName 方法
从文档中获得元素(或结点)。
【例 9.4】 加载 XML 文件并显示所有元素,代码如源程序 code9_4.asp 所示,加载的 XML
文件为 code9_1.xml。

·201·
·202· XML 实用教程

<%@ language="VBScript"%>
<html>
<head>
<title>从服务端加载 XML 文件并显示其所有元素值</title>
<body>
<center><b>服务器端加载的 XML 文件所有元素</b></center>
<hr>
<%
' 建立 XML DOM 对象
set xmlDom = Server.CreateObject("MSXML2.DOMDocument.4.0")
xmlDom.async = "false"
' 加载 XML 文件
xmlDom.load(Server.MapPath("code9_1.xml"))
if xmlDom.parseError.errorCode <> 0 then
Response.Write("加载 XML 文件错误<P>")
else
set objRootNode = xmlDom.documentElement
set objNode = objRootNode.firstChild.childNodes.Item(1)
Response.Write("<TABLE border=1>")
set objListNode = objRootNode.childNodes
' 显示所有的 XML 结点
for i = 0 To objListNode.length - 1
Response.Write("<tr><td>" & objListNode.Item(i).nodeName &
"</td>")
Response.Write("<td>" & objListNode.Item(i).text & "</td></tr>")
next
Response.Write("<table>")
end if
%>
</body>
</html>

其显示结果如图 9.5 所示。

图 9.5 服务器端加载的 XML 文件所有元素

·202·
第9章 XML 文档对象模型 ·203·

9.3.2 服务器端加载 XML 文件及其转换文件并显示所有元素

利用 ASP 文件也可以在服务器端加载 XML 文件及其转换文件,把文件 code9_3.htm


改名为 code9_5.asp,并对创建对象的语句、加载文件的路径等做一些改动就可实现与图 9.4
相同的效果。注意,服务器端向浏览器显示信息时使用 Response.Write 方法。建立 XML 文档
对象 xmlDom 和 XSLT 文档对象 xslDom,且将 XML 文件及其转换文件加载后,只需要写一句:
Response.Write(xmlDom.transformNode(xslDom))

即可实现在服务器端的处理和向客户端的显示。
【例 9.5】 服务器端同时加载 XML 文件及其转换文件,显示图书信息,代码如源程序
code9_5.asp 所示,XML 文件为 code9_1.xml,转换文件为 code9_1.xslt。显示结果与例 9.3 相
同,如图 9.4 所示。
<meta http-equiv="Content-Type" content="text/html;charset=GB2312">
<%
' 加载 XML 文件
set xmlDom=Server.CreateObject("MSXML2.DOMDocument.4.0")
xmlDom.async="false"
xmlDom.load(Server.MapPath("code9_1.xml"))
' 加载 XSLT 文件
set xslDom=Server.CreateObject("MSXML2.DOMDocument.4.0")
xslDom.async="false"
xslDom.load(Server.MapPath("code9_1.xslt"))
' 转换输出 HTML 文件
Response.Write(xmlDom.transformNode(xslDom))
%>

9.4 parseError 对象

打开 XML 文档时,如果文档有错误,XML Parser 将产生错误代码,并保存在 parseError


对象中,其中包括错误代码、错误文本和错误行号等信息。
9.4.1 parseError 属性

parseError 对象提供了有关错误的完整信息(属性),见表 9-4。


表 9-4 parseError 属性

属性名称 说 明
errorCode 返回长整型错误代码
reason 返回字符串型错误原因
line 返回长整型错误行号
linePos 返回长整型错误行号位置
srcText 返回字符串型产生错误原因
url 返回 URL 装载文档指针
filePos 返回长整型错误文件位置

·203·
·204· XML 实用教程

DOM 模型的 parseError 对象包含了最后出现的解析错误信息,这个错误对象对于 ASP


页面调试和错误控制是很有用的。文档装载完成后,在继续其他操作之前应检查 parseError
对象是否存在错误,代码格式如下:
<%
if xmlDom.parseError.errorCode <> 0 then
处理错误语句
end if
%>

9.4.2 出现错误时的处理

要试图装载一个不存在或有错误的 XML 文件,将会产生相应的错误信息。显示错误


信息的代码如下:
var xmlDom = new ActiveXObject("MSXML2.DOMDocument.4.0")
xmlDom.async="false"
xmlDom.load("notexist_or_err.xml")
<%
if xmlDom.parseError.errorCode <> 0 then
document.write("<br>错误代码: ")
document.write(xmlDom.parseError.errorCode)
document.write("<br>错误原因: ")
document.write(xmlDom.parseError.reason)
document.write("<br>错误行号: ")
document.write(xmlDom.parseError.line)
end if
%>

9.5 DOM 的结点接口

XML Parser 用来装载 XML 文档到缓存中,文档装载时,可以使用 DOM 进行检索和


处理。DOM 采用树状结构表示 XML 文档,文档元素是树的最高阶层,该元素有一个或多
个子结点用来表示树的分支。
结点接口程序通常用来读和写 XML 结点树中的个别元素,文档元素的子结点属性可
以用来构造个别元素结点。XML Parser 用来证明 Web 中的 DOM 支持遍历结点树的所有函
数,并可通过它们访问结点及其属性、插入删除结点、转换结点树到 XML 中。
所有的 Microsoft XML Parser 函数都得到了 W3C XML DOM 的正式推荐,除了 load
和 loadXML 函数(正式的 DOM 不包括标准函数 loading XML 文档)外,有 13 个结点类型为
Microsoft XML Parser 所支持,常用结点类型已在表 9-1 中列出,在此不作赘述。

9.5.1 新增 XML 结点

根据不同类型的结点,XML DOM 采用了不同的方法,见表 9-5。

·204·
第9章 XML 文档对象模型 ·205·

表 9-5 建立各类结点的方法

方 法 描 述
CreateElement(elemname) 使用指定名称 elemname 创建元素结点
CreateAttribute(attrname) 创建新属性结点,参数属性名称
CreateCDATASection(text) 创建 CDATA 块,参数 text 为文字内容
CreateComment(text) 创建注释文字结点,参数 text 为注释内容
CreateTextNode(text) 创建文本结点,参数为文字内容
CreateEntityReference(entityref) 创建实体参考对象,参数 entityref 为实体参考名称
CreateProcessingInstruction(target,text) 创建 PI 结点,参数 target 为 PI 名称,text 为值

新增 XML 结点按照建立新结点、将结点插入到位、给元素赋值和添加元素属性的步
骤进行。假设要建立如下的 XML 文档:
<books>
<book id="0001" discount="8.7">
<title>三国演义</title>
<author>罗贯中</author>
<publish>
<publisher>文艺出版社</publisher>
<ISBN>0-764-58007-8</ISBN>
<pubdate>1998.10</pubdate>
</publish>
<price>80</price>
</book>
<books>

可以按下列步骤进行。
1. 建立新结点
XML DOM 对象创建元素的方法为 CreateElement。当使用 CreateElement 方法时,只
需要提供元素名称,如创建元素 books:
set xmlDom=Server.CreateObject("MSXML2.DOMDovument.4.0")’建立文档对象
set objRoot = xmlDom.CreateElement("books")

2. 将结点插入到位
创建了结点,并不意味着它属于哪棵树,必须把它添加进 XML 文档的适当位置上才
行。这就要用 AppendChild 方法,例如,对于上面的例子,可以写出:
xmlDom.AppendChild(objRoot)

该语句创建了 XML 根结点 books。


除了 AppendChild 方法外,XMLDOMNode 对象也具有其他 3 个控制 XML 结点的方法:
ReplaceChild、RemoveChild 和 InsertBefore。

·205·
·206· XML 实用教程

下面的语句是在根结点 books 上再建立子结点 book:


set objbook= xmlDom.CreateElement("book")
objroot.AppendChild(objbook)

3. 给元素赋值
下面的语句是在结点 book 上再建立子结点 title、author,并分别赋予结点文本值:
set newNode= xmlDom.CreateElement("title")
newNode.text="三国演义"
objbook.AppendChild(newNode)
set newNode= xmlDom.CreateElement("author")
newNode.text="罗贯中"
objbook.AppendChild(newNode)

结点 publish 和 price 可以如法炮制,但是 publish 还含有子结点,可以将 publish 作为


树的一棵分支,生成以后再往树干 xmlDom 上添加:
set objpublish= xmlDom.CreateElement("publish")
set newNode= xmlDom.CreateElement("publisher")
newNode.text=" 文艺出版社"
objpublish.AppendChild(newNode)
set newNode= xmlDom.CreateElement("ISBN")
newNode.text=" 0-764-58007-8"
objpublish.AppendChild(newNode)
set newNode= xmlDom.CreateElement("pubdate")
newNode.text=" 1998.10"
objpublish.AppendChild(newNode)
'将 publish 分支树添加到 book 结点中
objbook.AppendChild(objpublish)
'给 book 增加 price 结点
set newNode= xmlDom.CreateElement("price")
newNode.text="80"
objbook.AppendChild(newNode)

上述代码的后面加上简单的显示语句:
response.write("<xmp>"+xmlDom.xml+"</xmp>")

就能将 XML 文档显示在一行上。


【例 9.6】 增加新结点,将上述代码汇集成 code9_6.asp,显示结果如图 9.6 所示。
<html>
<head>
<title>新增 XML 元素</title>
<body bgcolor="#eaeaea">
<%
set xmlDom=Server.CreateObject("MSXML2.DOMDocument.4.0")
'生成结点 books
set objRoot = xmlDom.CreateElement("books")
'将 books 挂到 DOM 树上
xmlDom.AppendChild(objRoot)
'以下 8 句生成 book 及其子结点 title 和 author,并赋值,把子结点添加到 book 结点中

·206·
第9章 XML 文档对象模型 ·207·

set objbook= xmlDom.CreateElement("book")


objroot.AppendChild(objbook)
Set newNode= xmlDom.CreateElement("title")
newNode.text="三国演义"
objbook.AppendChild(newNode)
set newNode= xmlDom.CreateElement("author")
newNode.text="罗贯中"
objbook.AppendChild(newNode)
'以下 11 句生成 publish 子树及其下属结点,并赋予文本值,子树添加到 book 结点中
set objpublish= xmlDom.CreateElement("publish")
set newNode= xmlDom.CreateElement("publisher")
newNode.text=" 文艺出版社"
objpublish.AppendChild(newNode)
set newNode= xmlDom.CreateElement("ISBN")
newNode.text=" 0-764-58007-8"
objpublish.AppendChild(newNode)
set newNode= xmlDom.CreateElement("pubdate")
newNode.text=" 1998.10"
objpublish.AppendChild(newNode)
objbook.AppendChild(objpublish)
'以下 3 句生成 price 结点,赋文本值,添加到 book 结点中
set newNode= xmlDom.CreateElement("price")
newNode.text="80"
objbook.AppendChild(newNode)
'显示整个 XML 文档
response.write("<xmp>"+xmlDom.xml+"</xmp>")
%>
</body>
</html>

图 9.6 建立新结点的效果

4. 添加元素属性
创建结点之后,还要对其属性赋值。这些属性用来描述结点的标识符或者一些特性值。
创建新属性最直接的办法就是使用 element 对象中的 setAttribute 方法,也可以先用 document
对象中的 createAttribute 方法设置属性值,然后使用 element 对象中的 setAttributeNode 方法
把新结点添加到 DOM 树中。
SetAttribute 方法用来给结点赋属性值,要求属性名和属性值两个参数。在上述代码中
增加几行,可以为 book 元素增加属性:

·207·
·208· XML 实用教程

'给 book 结点添加属性


call objbook.setAttribute("ID","0001")
call objbook.setAttribute("discount","8.7")

【例 9.7】 添加的属性,增加上述 3 行后的文件另存为 code9_7.asp,显示结果如图 9.7


所示。

图 9.7 例 9.6 增加属性后的效果

9.5.2 删除 XML 元素和属性

对于元素结点的删除和替换操作,首先都要对操作对象进行定位,然后相应地执行对
象结点所属父结点的 removeChild 方法,如在例 9.7 中删除 book 结点:
set objDeleteNode=xmlDom.documentElement.firstchild
objRoot.removeChild(objDeleteNode)

在构造 XML 文档时,代表结点 book 的变量名为 objbook,因此也可直接写成:


objRoot.removeChild(objbook)

可以用 getElementsByTagName 方法,找出要删除的结点名称进行删除,如要删除 book


结点下的 title 结点,可以先得到 book 结点,再根据名称删除 title,代码为
set objDeleteNode=xmlDom.documentElement.firstchild
objDeleteNode.removeChild(objDeleteNode.getElementsByTagName("title").
item(0))

删除属性最直接的方法是调用 element 对象中的 removeAttribute 方法。删除 book 的 ID


属性,可以写为
set objDeleteNode=xmlDom.documentElement.firstchild
objDeleteNode.removeAttribute("ID")

另外一种方法是先用 getAttributeNode 方法对操作对象进行定位,然后执行 remove


AttributeNode 方法。上面的代码又可写成:
set objDeleteNode=xmlDom.documentElement.firstchild
set DeleteAttrbuteNode=xmlDom.documentElement.
firstchild.getattributeNode("ID")
objDeleteNode.removeAttributeNode(DeleteAttrbuteNode)

【例 9.8】 删除例 9.7 的 XML 文档中的 title 结点和 book 的 ID 属性,代码如源程序


code9_8.asp 所示。只需在 code9_7.asp 中显示 XML 文档的代码之后加上以下代码:

·208·
第9章 XML 文档对象模型 ·209·

'定位到 book 结点
set objDeleteNode=xmlDom.documentElement.firstchild
'删除 book 下的 title 结点
objDeleteNode.removeChild(objDeleteNode.getElementsByTagName("title").
item(0))
'得到要删除的属性结点
set DeleteAttrbuteNode=objDeleteNode.getattributeNode("ID")
'删除属性结点 ID
objDeleteNode.removeAttributeNode(DeleteAttrbuteNode)
'再次显示整个 XML 文档
response.write("<br>删除 tilte 结点和 ID 属性之后<br>")
response.write("<xmp>"+xmlDom.xml+"</xmp>")

显示结果如图 9.8 所示。

图 9.8 例 9.7 删除部分结点和属性后的效果

9.5.3 访问和修改 XML DOM 结点

1. 访问和修改 XML DOM 元素


对于元素结点的访问和修改操作,首先也是要对操作对象进行定位,读取元素值。相
应的修改操作,执行对象结点所属父结点的 replaceChild 方法即可。结点文本值的修改也只
需要重新赋值。
【例 9.9】 把例 9.8 中的 title 结点改成 book_name 结点、“三国演义”改成“红楼梦”、
作者罗贯中改成曹雪芹,代码如源程序 code9_9.asp 所示。
只需在程序 code9_7.asp 的基础上,在显示源 XML 文档的代码后面加上以下代码:
set newname= xmlDom.CreateElement("book_name")
newname.text="红楼梦"
call objbook.replaceChild(newname,objbook.firstChild)
objbook.childNodes(1).text="曹雪芹"
Response.Write("修改结点名、书名和作者后的 XML 文档为:<br>")
Response.Write("<xmp>"+xmlDom.xml+"</xmp>")

·209·
·210· XML 实用教程

其显示结果如图 9.9 所示。

图 9.9 例 9.7 修改结点及其文本值后的效果

2. 访问和修改 XML DOM 属性

attribute 结点的各种操作在原理上与 element 结点相同。attribute 对象同样继承了 node


对象中的各种方法和属性,并且 MSXML 中还提供了 name 属性和 value 属性,能够更直接
地访问属性的信息。还可以通过属性所属元素的相关方法访问属性,如通过 getAttribute 和
setAttribute 方法读取属性值或修改属性值,或者用 getAttributeNode 方法直接返回 attribute
对象。另外,用 removeAttribute 方法删除某个属性后,采用 setAttribute 方法设置新的属性,
也能很方便地修改原来的属性。
【 例 9.10 】 把 例 9.9 中 的 book 结 点 的 discount 属 性改 成 off_percent , 其 值换 成
100-discount*10,代码如源程序 code9_10.asp 所示。
只需在例 code9_7.asp 的基础上,在显示源 XML 文档的代码后面加上以下代码。
'把原来的按几成价(discount)销售值改为减免值(off_percent)
newvalue=100-10*objbook.attributes(1).nodeValue
'删除 book 结点的属性 discount
objbook.removeAttribute("discount")
'设置 book 的属性 off_percent 及其文本值
call objbook.setattribute("off_percent",newvalue)
'再次显示整个 XML 文档
Response.Write("修改属性结点后的 XML 文档为:<br>")
Response.Write("<xmp>"+xmlDom.xml+"</xmp>")

显示结果如图 9.10 所示。


从以上的介绍中可以看出,由于结点间的继承关系以及各种类型结点本身提供的丰富
的接口,用户可以很容易地找到一套适合自己需要的对象操作方案。

·210·
第9章 XML 文档对象模型 ·211·

图 9.10 例 9.7 修改结点属性后的效果

9.6 小 结

XML DOM 包含 4 个主要对象:XML DOM Document、XML DOM Node、XML DOM


NodeList 和 XML DOM NamedNodeMap。同任何其他对象模型一样,每个 XML DOM 对象
有其自己的特性和方法。
XML DOM Document 对象代表 XML DOM 层次中的顶层结点,它是建立和操纵 XML
结构的基础。
只要对 XML 文档的结构有一定的了解,再利用 DOM 的强大功能,就可以方便地在
ASP 应用服务器端解析 XML 文档,从解析结果中选择合适的内容发送给客户端。这是一
种与浏览器无关的方法,适用于几乎所有的 Web 浏览器。

9.7 习 题

1. 试列出 XML 的组成部分和包括的主要对象。


2. 画出第 1 章习题 6 文档的树状结构图,形如图 9.1 所示。
3. 将例 9.2 的 code9_2.htm 中嵌入的 JavaScript 脚本语言部分用 VBScript 脚本语言改写。
4. 将例 9.3 的 code9_3.htm 中嵌入的 JavaScript 脚本语言部分用 VBScript 脚本语言改写。
5. 有如下 XML 文档,请仿照例 9.6 的方法将文档生成,并予以显示。
<?xml version="1.0" encoding="gb2312" ?>
<!-- 这个文档包含网上书店中关于客户的描述,文件名 code9_11.xml -->
<customers>
<customer ID="0505001XX" >
<username>Jerry</username>
<password>12345678</password>
<registerdate>200505</registerdate>

·211·
·212· XML 实用教程

<address>
<zipcode>123456</zipcode>
<city>厦门市</city>
<street>中山路 2 号</street>
</address>
</customer>
</customers>

6. 在上题的基础上完成以下操作。
(1) 在 registerdate 和 address 元素之间加入 email 元素并赋值 great_sell@163.com。
(2) 在 zipcode 和 city 元素之间加入 province 元素并赋值福建省。
(3) 在 street 元素之后加入 phonenumber 元素并赋值 0592-6688688。
(4) 显示最后结果。
7. 在上题的基础上增加 customer 的 discount 属性,赋值 0.2,并显示结果。
8. 在上题的基础上删除元素 registerdate 和 phonenumber,并显示结果。

·212·
第 10 章 XML 与 Java

教学提示:一个单独的 XML 文件不能做任何工作,它需要与应用程序结合来实现各


种功能,应用程序通过 XML 解析器和 XML 应用程序接口处理 XML 文件。本章介绍 Java
程序如何使用 DOM 解析 XML 文件。JAXP 提供的类和方法,可以让 Java 应用程序使用
DOM 解析或转换 XML 文件。
教学要求:了解 Java 的特点,熟悉 Java 的开发环境 JDK 的安装和配置,掌握 Java 使
用 DOM 加载 XML 的方法,掌握访问 XML 元素和属性的方法,掌握使用 DOM 创建 XML
文件的方法,学会转换 XML 文件为 HTML 的方法。

10.1 Java 简介

10.1.1 Java 的诞生

Java 来自于 Sun 公司的一个叫 Green 的项目,其原本的目的是为家用消费电子产品开


发一个分布式代码系统,这样可以把 E-mail 发给电冰箱、电视机等家用电器,对它们进行
控制,和它们进行信息交流。开始,准备采用 C++,但 C++太复杂,安全性差。1991 年,
Sun 公司的 Jame Gosling、Bill Joe 等人开发了一种新的语言 Oak(Java 的前身),Oak 是一种
用于网络的精巧而安全的语言,Sun 公司曾以此投标一个交互式电视项目,但结果是被 SGI
打败。可怜的 Oak 几乎无家可归,恰巧这时 Mark Andersen 开发的 Mosaic 和 Netscape 启发
了 Oak 项目组成员,他们用 Java 编制了 HotJava 浏览器,得到了 Sun 公司首席执行官 Scott
McNealy 的支持,触发了 Java 进军 Internet。
Java 的取名也有一趣闻。有一天,几位 Java 成员组的会员正在讨论这个新的语言取什
么名字,当时他们正在咖啡馆喝着 Java(爪哇)咖啡,有一个人灵机一动说不如就叫 Java,
得到了其他人的赞赏,于是,Java 这个名字就这样传开了。

10.1.2 Java 的特点

根据 Sun 公司的《Java 白皮书》中对 Java 的定义,Java 是一种简单、面向对象、分布


式、解释性、稳健、安全、结构中立、可移植、高性能、多线程、动态的语言。
1. 简单性
Java 是一种面向对象的语言,它通过提供最基本的方法来完成指定的任务,只需理解
一些基本的概念,就可以用它编写出适合于各种情况的应用程序。Java 是一种类似 C++的
面向对象的语言,因此,C++程序员可以很快就掌握 Java 编程技术。Java 摒弃了 C++中容
·214· XML 实用教程

易引发程序错误的地方,如指针的内存管理。Java 提供了丰富的类库,使编程比较容易。
2. 面向对象
Java 的设计集中于对象及其接口,对象中封装了它的状态变量以及相应的方法,实现
了模块化和信息隐藏。而类则提供了一类对象的原型,并且通过继承机制,子类可以使用
父类所提供的方法,实现了代码的复用。它提供了简单的类机制及动态的接口模型,由属
性(状态变量)、方法(函数)和事件(触发机制封装而成),是纯面向对象的编程语言,它不支
持类似 C 语言那样的面向过程的程序设计技术。Java 支持静态和动态风格的代码继承及复
用。
3. 分布式
Java 包括支持 HTTP 和 FTP 等基于 TCP/IP 协议簇的子库。因此,Java 应用程序可凭
借 URL 打开并访问网络上的对象,其访问方式与访问本地文件系统几乎完全相同。为分布
式环境尤其是 Internet 提供动态内容无疑是一项非常困难的任务,但 Java 的语法特性却使
用户很容易实现这项目标。
4. 解释性
Java 解释器(运行系统)能直接运行目标代码指令。链接程序通常比编译程序所需资源
少,因此程序员可以在创建源程序上投入更多的时间。
5. 稳健性
Java 在编译和运行程序时,都要对可能出现的问题进行检查,以消除错误的产生。它
提供自动垃圾收集来进行内存管理,防止程序员在管理内存时容易产生的错误。通过集成
的面向对象的例外处理机制,在编译时,Java 提示可能出现但未被处理的例外,帮助程序
员正确地进行选择以防止系统崩溃。另外,Java 在编译时还可捕获类型声明中的许多常见
错误,防止动态运行时不匹配问题的出现。
6. 安全性
Java 的安全性可从两个方面得到保证。一方面,Java 语言不支持指针和释放内存等 C++
的功能,这样就避免了非法内存操作;另一方面,类装载通过将本机类与网络资源类的名
称分开,来保持安全性。因此调入类时总要经过检查,这样避免了“特洛伊木马”现象的
出现。
7. 结构中立
为了使 Java 作为网络的一个整体,Java 程序将它的程序编译成一种结构中立的中间文
件格式。只要有 Java 运行系统的计算机都能执行这种中间代码。
8. 可移植性
与平台无关的特性使 Java 程序可以方便地被移植到网络上的不同计算机中。同时 Java
的类库中也实现了与不同平台的接口,使这些类库可以移植。另外 Java 编译器是由 Java
语言实现的,Java 运行时系统由标准 C 语言实现,这使得 Java 系统本身也具有可移植性。

·214·
第 10 章 XML 与 Java ·215·

9. 高性能
如果解析器速度不慢,Java 可以在运行时直接将目标代码翻译成机器指令。从而得到
较高的性能。
10. 多线程
Java 提供多线程功能使得在一个程序里可同时执行多个小任务,而且同步机制保证了
对共享数据的正确操作。通过使用多线程可以很容易地实现网络上的实时交互行为。
11. 动态性
Java 的动态特性是其面向对象设计方法的扩展。它允许程序动态地装入运行过程中所
需要的类,这是 C++进行面向对象程序设计所无法实现的。而且 Java 通过接口来支持多继
承,使其比严格的类继承具有更灵活的方式和扩展性。

10.1.3 Java 带来的影响

Java 虽出现的时间不长,但已被业界接受,IBM、Apple、DEC、Adobe、SiliconGraphics、
HP、Oracle、Toshiba、NetScape 和 Microsoft 等大公司已经购买了 Java 的许可证。Microsoft
公司还在其 Web 浏览器 IE3.0 版中增加了对 Java 的支持。
另外,众多的软件开发商也开发了许多支持 Java 的软件产品。如 Borland 公司的基于
Java 的快速应用程序开发环境 Latte;Metrowerks 公司和 Natural Intelligence 公司分别开发
的基于 Machintosh 的 Java 开发工具;Sun 公司的 Java 开发环境 Java Workshop;Microsoft
公司也开发出系列 Java 产品。数据库厂商如 Illustra、Sybase、Versant、Oracle 都在开发支
持 HTML 和 Java 的 CGI(Common Gateway Interface)。在以网络为中心的计算机时代,不支
持 HTML 和 Java,就意味着应用程序的应用范围只能限于同质的环境。
Internet 正在成为企业信息系统最佳的解决方案。它的优点表现在:便宜、易于使用和
管理。用户不管使用何种类型的计算机和操作系统,界面是统一的 Web 浏览器,而数据库、
Web 页面、应用程序(用 Java 编的 applet)则存在 WWW 服务器上。开发人员只需维护一个
软件版本,管理人员省去了为用户安装、升级、培训之苦,用户则只需一个操作系统和一
个 Internet Explorer 足矣。
大家可以设想未来的计算方式,每个 HomePage 的实质是一个多媒体应用程序,这些
程序用 Java 来开发。Java 应用程序运行在异质的计算机、异质的操作系统之上,甚至于电
冰箱、烤面包箱、防盗电子设备之中,用 Internet 把所有的电子设备连接起来,通过 TCP/IP
协议簇进行信息的交流。Java 应用程序之间既可以交换消息,也可以交换程序(一个 Java
的小应用程序 applet)。或许有一天,人们可以在 Netscape 浏览器里查看电冰箱的温度,向
烤面包箱发一个电子邮件。
Java 的出现是计算机信息交换的一个重要里程碑。在单机时代,程序进程之间靠共享
存储进行变量交换;在网络时代,运行在不同主机上的程序按网络协议进行无格式的消息
(二进制字符流)交换,消息的语义由交换程序双方维护;在 Java 时代,运行在网络上的程
序进程,交换的是小应用程序(applet)。小应用程序是什么?它是一个对象,由一组属性和方
法构成,是一个可执行的实体,不仅有数据的状态,而且有定义在数据上的操作。未来可
能进行代理(Agent)交换,代理有一定的智能性,那便是信息交换的更高级阶段。

·215·
·216· XML 实用教程

随着 Internet 的崛起、Java 的诞生,巨型的、臃肿的应用软件开始向小型化发展,由众


多“生活”在 Internet 上的小应用程序(applet)相互协作完成信息的处理与传递。Java 会加
速应用软件小型化、网络化的趋势。随着 Internet 的发展,软件必然是面向“大众”的,而
不是“少数人”的奢侈品,“薄利多销”将是网络应用软件的重要特点。分布式对象技术
保证了用多少,下载多少。
Java 连同 Internet、WWW 正在改变应用软件的开发和使用方式,一切都要围绕着网络,
围绕着与平台无关。很多人认为,Word、Excel 等传统的信息处理工具都必将走向萎缩,
因为它们是单机时代的产物。信息的价值在于使用和共享,Internet 和 Web 是使用和共享
信息最快捷、最便宜的方式,Word 将演化成为 Web 的写作工具,Excel 则将演化成 Web
上的电子表格。

10.2 Java 的开发环境

Java 程序的开发环境需要安装 Sun 公司的 JDK,然后配合 Windows 的记事本或其他编


辑工具建立 Java 应用程序。

10.2.1 JDK 的安装

Java 的开发工具 Java Development Kit(JDK)拥有很多版本,本章使用 JDK 1.4 版,这个


版本内含 JAXP API 1.1 版。读者可以从 http://java.sun.com 免费下载此开发工具。
虽然 Java 是跨平台的,但在各种平台时的安装方式却各不相同,下载时要选择支持的
操作系统和语言下载。下载好后即可运行安装了。这里主要介绍 Windows 操作系统下
J2sdk1.4.2_07-win.exe 的安装过程。
JDK 的安装比较简单,和安装其他的软件没有什么区别,安装过程介绍如下:
(1) 双击下载后的 J2sdk1.4.2_07-win.exe,先出现欢迎安装的向导界面,然后出现版权
协议说明界面,如图 10.1 所示,接受版权协议后,单击 Next 按钮。

图 10.1 版权协议界面

·216·
第 10 章 XML 与 Java ·217·

(2) 出现选择安装组件的界面和安装路径,默认路径是 C:\j2sdk1.4.2_07,如图 10.2 所


示,单击 Next 按钮。

图 10.2 选择安装组件和安装路径的界面

(3) 选择浏览器,如图 10.3 所示,然后单击 Install 按钮继续安装。

图 10.3 选择浏览器界面

(4) 对 JDK 进行安装,如图 10.4 所示,安装完毕后,单击 Finish 按钮结束安装。

·217·
·218· XML 实用教程

图 10.4 复制文件进行安装的界面

10.2.2 JDK 的配置

安装好 JDK 需要更新 Path 变量,假设 JDK 安装在 C:\j2sdk1.4.2_07 目录下。下面以


Windows 2000、Windows XP 操作系统为例来进行配置。
右击【我的电脑】,从弹出的快捷菜单中选择【属性】命令,出现【属性】对话框,
选择【高级】选项卡,如图 10.5 所示。单击【环境变量】按钮后,出现【环境变量】对话
框,如图 10.6 所示。

图 10.5 【属性】对话框

·218·
第 10 章 XML 与 Java ·219·

图 10.6 【环境变量】对话框

找到系统变量 Path,编辑 Path 变量的值,在 Path 值域的文本框后面加上 C:\j2sdk1.4.2


_07\bin。
在系统变量中新建 classpath 变量,将其值设置为 C:\j2sdk1.4.2_07\lib,一般情况下这个
路径下的 Java 包已经够用。有些特殊用途的 Java 程序需要特定的包支持,可以将需要的包
复制到这个路径下。用户开发的类或包也需要把其所在路径追加到 classpath 中,用分号与
前面的已有路径隔开。
如果要用到 JSP 服务或者 J2EE 架构,还需要设置 JAVA_HOME 等环境变量。

10.3 Java 程序加载 XML 文件

为了简化编写处理 XML 的 Java 程序,已经建立了多种编程接口。这些接口或者由公


司定义,或者由标准体、用户组定义,以满足 XML 程序员的需要。以下列出了 4 种接口。
z (1) DOM,Level 2;
z (2) SAX(Simple API for XML),Version 2.0;
z (3) JDOM,Jason Hunter 和 Brett McLaughlin 创立的一种简单 Java API;
z (4) Sun 公司推出 JAXB(Java Architecture for XML Binding)。
这 4 种接口中 DOM 是 W3C 的正式推荐,本章主要介绍 Java 应用程序如何使用 DOM
解析或转换 XML 文件。要创建 DOM 或 SAX 解析器,需要使用 JAXP(Java API for XML
Processing)。

·219·
·220· XML 实用教程

10.3.1 JAXP 简介

JAXP 使得用 Java 开发处理 XML 数据的应用程序非常容易,JAXP 包括语法分析器、


标准 SAX 与 DOM,可以选择以事件流或建立对象表示来解析数据。JAXP 1.1 版本还支持
XSLT 标准,可以控制数据的表示,并可以将数据转换成其他的 XML 文件或格式,如 HTML。
JAXP 还提供对名称空间的支持,可以在没有命名冲突的情况下使用 DTD。
JAXP 提供的类和方法,可以让 Java 应用程序使用 DOM 解析或转换 XML 文件,在
JDK 1.4 支持的 JAXP API 1.1 版支持 XML,建议规格有 DOM Level 2、XSLT 1.0 和 SAX 2.0。
其解析文档对象模型的相关套件,见表 10-1。

表 10-1 JAXP API 1.1 解析文档对象模型的相关套件

套 件 说 明
Javax.xml.parsers 提供处理 XML 文件的类
Javax.xml.transform 提供处理 XSLT 文件的类
org.xml.sax 这是 SAX 解析器,提供以事件驱动方式解析 XML 文件的 API
org.xml.saxhelpers 提供解析错误处理的相关类,可以帮助程序设计者使用 SAX API
org.w3c.dom 提供支持 DOM 建议规格的套件

10.3.2 常用的 DOM 接口

DOM 定义了一套标准的接口以便按照程序的设计显示 XML 文档。当然,DOM 不能


实现定义的接口,而支持 DOM 的 XML 解析器必须实现 DOM 所定义的接口。最常用的几
个 DOM 接口对象可见第 9 章的表 9-3,这里不再赘述。

10.3.3 加载 XML 文档文件

在 Java 程序中加载 XML 文档文件,步骤如下。


(1) 首先需要导入相关的套件。
import javax.xml.parsers.*;
import org.xml.sax.*;
import org.w3c.dom.*;
import java.io.*;

其中 org.xml.sax.*套件是解析错误处理的相关套件,此外因为 XML 文件属于文本文件,


所以导入文件处理的套件用 import java.io.*。
(2) 在 JAXP 中,DOM 解析器称为 DocumentBulider,可以通过工厂类 DocumentBulider
Factory 获得,而 document 对象则可以通过类 DocumentBulider 获得,使用 try catch 指令建
立解析的错误处理。在建立 DocumentBulider 对象后,可使用 parser 方法解析加载 XML 文
件,file 对象加载后就可以处理 XML 文件的结点内容。其程序块的架构如下所示。

·220·
第 10 章 XML 与 Java ·221·

//获得一个 XML 文件的解析器


DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
try{
//解析 XML 文件生成 DOM 文档的接口类,以便访问 DOM
DocumentBuilder db=dbf.newDocumentBuilder();
document=db.parser(new File(args[0]));

}catch(SAXException se){
//解析过程错误
Exception e=se;
if(se.getException()!=null)
e=se.getException();
e.printStackTrace();
}catch(ParserConfigurationExcepion pe){
//解析器设定错误
pe.printStackTrace();
}catch(IOException ie){
//文件处理错误
ie.printStackTrack();
}

(3) 获得接口类 document 实例后,就可以对 DOM 的文档树进行访问。如要遍历 DOM


文档,首先要获得根结点,然后获得根结点的子结点列表。
//获得根结点
Element element=document.getDocumentElement();
//获得根结点的子结点列表
NodeList=element.getChildNodes();

【例 10.1】 显示加载的外部 XML 文件所有结点的名称和值,代码如源程序 code10_1.java


所示。这里通过递归方法实现遍历的目的。
import javax.xml.parsers.*;
import org.xml.sax.*;
import java.io.*;
import org.w3c.dom.*;
public class code10_1{
static Document document;
public static void main(String[] args){
if(args.length!=1){
System.out.println("加载 xml file");
return;
}
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
try{
DocumentBuilder db=dbf.newDocumentBuilder();
//读入 XML 文档
document=db.parse(new File(args[0]));
//遍历 XML 文档
walkNode(document.getDocumentElement());

}catch(SAXException se){

·221·
·222· XML 实用教程

//解析过程错误
exception e=se;
if(se.getException()!=null)
e=se.getException();
e.printStackTrace();
}catch(ParserConfigurationException pe){
//解析器设定错误
pe.printStackTrace();
}catch(IOException ie){
//文件处理错误
ie.printStackTrace();
}
}
private static void walkNode(Node anode){
NodeList child=anode.getChildNodes();
printNode(anode);
for(int i=0;i<child.getLength();i++){
Node node=child.item(i);
if(node.hasChildNodes())
walkNode(node);
else
printNode(node);
}
}
private static void printNode(Node anode){
system.out.println(anode.getNodeName()+","+anode.getNodeValue());
}
}

被引用的 XML 文件为 code10_1.xml。


<?xml version="1.0" encoding="gb2312" ?>
<customers>
<customer ID="c0500103" >
<username>cheaperget</username>
<password>12345678</password>
<email>notknown@yahoo.com</email>
<registerdate>200508</registerdate>
<address>
<zipcode>361021</zipcode>
<phone>0592-6888888</phone>
<street>XX 省 XX 市银江路 108 号</street>
</address>
</customer>
<customer ID="c0500208" >
<username>dreamingboy</username>
<password>22345678</password>
<email>greatman@lycos.com</email>
<registerdate>200505</registerdate>
<address>
<zipcode>215006</zipcode>

·222·
第 10 章 XML 与 Java ·223·

<phone>0512-61666666</phone>
<street>XX 省 XX 市人民路 616 号</street>
</address>
</customer>
</customers>

其显示结果如图 10.7 所示。

图 10.7 例 10.1 运行结果

本例中遍历了 XML 文档的所有结点,并显示出所有结点的名称和值。从结果中可以


看出有许多#text 结点,其中一些表示文本结点,如#text,cheaperget 和#text,12345678;还有
的表示 XML 文件中行与行之间的换行符和空格符,如 customers,null 后的#text 就是 XML
文件中第二行与第三行之间的换行符和空格符。
如何去掉这些多余的#text 结点呢?可以把 XML 文档中的换行符和空格符去掉,再重
新运行程序,将会发现这些多余的#text 结点全都没有了。
可是把 XML 文档中的换行符和空格符去掉后,XML 可读性就非常差,怎样解决这个
问题呢?在加载文件时并设定参数即可。

10.3.4 设定加载 XML 文件的参数

DocumentBuilderFactory 类提供相关的方法可以设定解析器解析 XML 文件的方式,例


如,是否忽略文字或 whitespace 内容的元素等,见表 10-2。

·223·
·224· XML 实用教程

表 10-2 加载 XML 文件的参数

方 法 说 明
设置解析器 CDATA 结点转换成 TEXT 文字结点和新增在其相
setCoalesing(boolen)
邻文字结点之后(如果有的话),默认值为 false,true 表示转换
设置解析器展开实体参考的结点,默认值为 true 表示展开,false
setExpandEntityReferencedes(boolen)
表示不展开
setIgnoringComments(boolen) 设置解析器忽略注释文字,默认值为 false,true 表示不忽略
SetIgnoringElementContentWhitespace 设置解析器忽略元素内容为 whitespace 空白字节的结点,默认
(boolen) 值为 false,true 表示忽略

【例 10.2】 加载外部 code10_2.xml 文件(此 XML 文档拥有 DTD 文件),并设定解析器参


数,然后显示所有结点的名称和值,代码如源程序 code10_2.java 所示。
import javax.xml.parsers.*;
import org.xml.sax.*;
import java.io.*;
import org.w3c.dom.*;
public class code10_2{
static Document document;
public static void main(String[] args){
if(args.length!=1){
System.out.println("加载 xml file");
return;
}
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
try{
//设定解析参数
dbf.setIgnoringElementContentWhitespace(true);
DocumentBuilder db=dbf.newDocumentBuilder();
//读入 XML 文档
document=db.parse(new File(args[0]));
//遍历 XML 文档
walkNode(document.getDocumentElement());

}catch(SAXException se){
//解析过程错误
exception e=se;
if(se.getException()!=null)
e=se.getException();
e.printStackTrace();
}catch(ParserConfigurationException pe){
//解析器设定错误
pe.printStackTrace();
}catch(IOException ie){
//文件处理错误
ie.printStackTrace();

·224·
第 10 章 XML 与 Java ·225·

}
}
private static void walkNode(Node anode){
NodeList child=anode.getChildNodes();
printNode(anode);
for(int i=0;i<child.getLength();i++){
Node node=child.item(i);
if(node.hasChildNodes())
walkNode(node);
else
printNode(node);
}
}
private static void printNode(Node anode){
system.out.println(anode.getNodeName()+","+anode.getNodeValue());
}
}

其显示结果如图 10.8 所示。

图 10.8 例 10.2 的运行结果

被引用的 XML 文件为 code10_2.xml。


<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE customers SYSTEM "code10_2.dtd">
<customers>
<customer ID="c0500103">
<username>cheaperget</username>
<password>12345678</password>

·225·
·226· XML 实用教程

<email>notknown@yahoo.com</email>
<registerdate>200508</registerdate>
<address>
<zipcode>361021</zipcode>
<phone>0592-6888888</phone>
<street>XX 省 XX 市银江路 108 号</street>
</address>
</customer>
<customer ID="c0500208">
<username>dreamingboy</username>
<password>22345678</password>
<email>greatman@lycos.com</email>
<registerdate>200505</registerdate>
<address>
<zipcode>215006</zipcode>
<phone>0512-61666666</phone>
<street>XX 省 XX 市人民路 616 号</street>
</address>
</customer>
</customers>

10.4 Java 程序中访问 XML 元素和属性

如果仔细分析例 10.2 的运行结果,会发现元素的属性没有显示出来,如何显示出元素


的属性呢?
从第 9 章的学习可以知道 DOM 是由 W3C 制定的用于处理 XML 和 HTML 文件的 API。
在应用程序中,基于 DOM 的 XML 解析器将一个 XML 文档转换成一个类似于树的对象模
型集合,通常称为 DOM 树。在这棵树中,包含了 XML 文档的所有内容,并都用结点表示。
首先来看一下 XML 文档中常见的结点种类,见表 10-3。

表 10-3 XML 文档的结点

结点类型 说 明
NODE_DOCUMENT_TYPE <!DOCTYPE node SYSTEM “code10_2.dtd”>
NODE_PROCESSING_INSTRUCTION <?xml vertion=“1.0”>
NODE_ELEMENT <username>cheaperget</username>
NODE_ATTRIBUTE ID=“c0500103”
NODE_TEXT cheaperget

表中列出了结点类型的常数名称,当 DOM 加载 XML 文件后,Java 程序代码看到的


XML 文件内容就是表中各种结点组成的树状结构,而结点本身还可能包含一些信息,例如
结点的名字、结点值、结点的类型等,因此 DOM 树中的结点是对象,对象包含方法与属
性。下面介绍如何使用结点的方法来访问结点的属性。

·226·
第 10 章 XML 与 Java ·227·

10.4.1 访问 XML 元素和属性

在 DOM 接口规范中,有 4 个基本接口:Document、Node、NodeList、Element。在这


4 个基本接口中,Document 接口是对文档进行操作的入口,它是从 Node 接口继承过来的。
Node 接口是其他大多数接口的父类,像 Document、Element、Text、Comment 等接口都是
从 Node 接口继承过来的。NodeList 接口是一个结点的集合,它包含了某个结点中的所有子
结点。下面对这几个接口分别做一些简单的介绍。
1. Document 接口
Document 接口代表了整个 XML 文档,因此,它是整个文档树的根,提供了对文档中
数据进行访问和操作的入口。通过 Document 结点,可以访问到文档中的其他结点,如处
理指令、批注、文字等。
方法描述:
(1) getDocumentElement(),Document 文件对象使用该方法可获取 XML 文件的根结点;
(2) getElementsByTagName(),Document 使用标记名获取子结点,取出的结点是一个
NodeList 对象。
2. Node 接口
Node 接口在整个 DOM 树中具有举足轻重的地位,DOM 接口中很大一部分接口是从
Node 接口继承过来的,例如 Document、Element、Text、Comment 等接口。在 DOM 树中,
Node 接口代表了树中的一个结点。
方法描述:
(1) getChildNodes(),获取子结点的 NodeList 结点对象列表,即子结点数;
(2) getNodeName(),返回结点名称,不同类型结点的值不同;
(3) getNodeType(),返回结点类型的代码;
(4) getNodeValue(),返回结点的值;
(5) getFirstChild(),获取第一个子结点;
(6) getNextSibling(),获取此结点的兄弟结点,即同级的下一个结点;
(7) getLastChild(),获取最后一个子结点;
(8) getParentNode(),获取父结点;
(9) hasChildNodes(),Node 结点对象检查是否拥有子结点,是返回 true,否则为 false。
3. NodeList 接口
NodeList 接口提供了对结点集合的抽象定义,它并不包含如何实现这个结点集的定义。
NodeList 接口用于表示有顺序关系的一组结点,比如某个结点的子结点序列。其中的每个
item 都可以通过一个索引来访问,该索引值从 0 开始。另外,它还出现在一些方法的返回
值中,例如 GetNodeByName。
方法描述:
(1) getLength(),可获取 NodeList 对象共有多少结点,即结点的个数;
(2) item(int),返回参数制定的结点对象,参数是结点对象的索引值。

·227·
·228· XML 实用教程

4. Element 接口
Element 接口是从 Node 接口继承过来的,它代表了 XML 文档中的元素。Element 接口
提供了访问 DOM 树中元素内容与信息的途径,并给出了对 DOM 树中的元素进行遍历的
支持。
方法描述:
(1) getElementsByTagName(string),通过标记名称获取元素;
(2) getTagName(),获取元素的标记的名称;
(3) getAttributes(string),获取元素的属性,是属性对象列表,属于 NamedNodeMap;
(4) getAttributeNode(string),通过属性的名字得到一个属性类型结点。
5. NamedNodeMap 属性列表对象
NamedNodeMap 对象可以获取元素的属性列表,因为一个元素可能拥有多个属性。可
以使用 getAttributes 获取属性列表。
下面通过一个实例来说明如何使用上述对象和方法来解析 XML 文档。
【例 10.3】 使用 DOM 对象和方法访问 XML 文档的元素与属性,代码如源程序 code10
_3.java 所示,XML 文件为 code10_1.xml。
import javax.xml.parsers.*;
import org.xml.sax.*;
import java.io.*;
import org.w3c.dom.*;
public class code10_3{
static Document document;
public static void main(String[] args){
if(args.length!=1){
system.out.println("加载 XML 文档");
return;
}
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
try{
DocumentBuilder db=dbf.newDocumentBuilder();
//读入 XML 文档
document=db.parse(new File(args[0]));
//获得根元素
Node root=document.getDocumentElement();
//获得根元素的子结点列表
NodeList childs=root.getChildNodes();
getElement(childs);
}catch(SAXException se){
//解析过程错误
Exception e=se;
if(se.getException()!=null)
e=se.getException();
e.printStackTrace();
}catch(ParserConfigurationException pe){
//解析器设定错误

·228·
第 10 章 XML 与 Java ·229·

pe.printStackTrace();
}catch(IOException ie){
//文件处理错误
ie.printStackTrace();
}
}
public static void getElement(NodeList childs){
int i=0;
if(childs.getLength()==0)
{//该结点没有子结点
System.out.println("该结点没有子结点!");
}
for(i=0;i<childs.getLength();i++){
//获取第 i 个子结点
Node node=childs.item(i);
//获取结点的类型,可以是 ElementNode,TextNode,DocumentNode 等
short nodetype=node.getNodeType();
/*ElementNode 类型的结点可包含子结点和属性等*/
if(nodetype==Node.ELEMENT_NODE)
{
//得到结点名称
String name=node.getNodeName();
String attrValue="",attrName="";
system.out.println("this is element! name is:"+name);
if(node.hasAttributes())
{
/*取出一个元素的属性,得到的是一个属性对象列表(NameNodeMap),在此因
为 XML 文档中元素只有一个属性,所以只取 NameNodeMap 中的第 0 个值*/
Node attrNode=node.getAttributes().item(0);
/*取出该属性结点的 Name 和 Value,即是一个 ElementNode 的属性名称和属
性值*/
attrName=attrNode.getNodeName();
attrValue=attrNode.getNodeValue();
System.out.println("this element attr
is:"+attrValue+";attrnameis:"+attrName);
}
//如有子结点,递归调用 GetElement()
if(node.hasChildNodes())
{getElement(node.getChildNodes());}
}
/*Text 类型结点没有子结点,结点名为#text,结点的值为 XML 文档中元素的值*/
if(nodetype==Node.TEXT_NODE)
{
//该结点的 name 是"#text"
String txtName=node.getNodeName();
//取出 Text 类型结点的值
Node thisparent=node.getParentNode();
Node txtNode=thisparent.getChildNodes().item(0);
String txtValue=txtNode.getNodeValue();
if(txtValue.trim().length()>0)
{

·229·
·230· XML 实用教程

system.out.println("txtName="+txtName+";
txtValue="+txtValue.trim());
}
}
}
}
}

其显示结果如图 10.9 所示。

图 10.9 例 10.3 的运行结果

例 10.3 使用循环显示了所有的子结点,如果需要访问特定的元素或属性,可以使用
Document 对象的 getElementByTagName 方法获取指定的 XML 元素。如获得 password 标记
的第二个 password 标记,NodeList 结点列表,如下所示:
//获得 password 标记的 NodeList 结点列表
NodeList passwords=Document.getElementByTagName("password");
//item 方法指出为第二个 password 标记
system.out.println("元素名称:"+passwords.item(1).getNodeName());

·230·
第 10 章 XML 与 Java ·231·

使用 Node 结点对象的 getChildNodes 方法可以在树状结构的结点中获取所需的子结点。


//获取根结点 root 下一层的第二个结点的第二个子结点
system.out.println(root.getChildNodes().item(1).
getChildNodes().item(1).getNodeName());

此外 Node 结点对象的 getFirstChild()、


getLastChild()、
getNextSibiling()和 getParentNode()
等方法可获取指定的结点。

10.4.2 使用 DOM 创建 XML 文档

前面讲述了如何使用 DOM 访问 XML 文档,DOM 还允许用户创建自己的 XML 文档。


1) 创建 XML 文档
可以使用 newDecument 方法建立 XML 文档。
Document=db.newDecument();
2) 建立新的结点
使用 Document 对象的方法建立所需结点对象,见表 10-4。

表 10-4 建立新结点的方法

方 法 说 明

createElement(string) 建立 XML 元素的结点,参数为标记名称

createAttribute(string) 建立属性名称的属性结点,参数是属性名称

createCDATASection(string) 建立 CDATA 块,参数是文字内容

createComment(string) 建立注释文字结点,参数为注释文字内容

createTextNode(string) 建立文字结点,参数为内容

createEntityReference(string) 建立实体参考,参数为实体参考名称

createProcessingInstring(string,string) 建立 PI 结点,第一个参数是 PI 名称,第二个为值

3) 指定插入的位置
在建立好 XML 元素的对象后,可以使用 Node 结点对象的方法添加到 DOM 树中:
z appendChild(newnode),新添加一个 newnode 结点;
z insertBefore(newnode,befnode),将 newnode 结点插到 befnode 结点前。
4) 新增元素内容
使用 createTextNode 方法建立文字结点后,再使用 appendChild 方法将它添加到元素结
点中。
5) 新增元素的属性
可以使用 setAttribute 方法给 Element 元素对象增加属性。
6) 删除元素或属性
如要删除结点可使用 Node 结点的 removeChild 方法删除指定的结点,如要删除属性可
使用 Element 元素对象的 removeAttribute 方法删除。

·231·
·232· XML 实用教程

//删除第一个 customer 结点
root.removeChild(Element)root.getElementsBytagName("customer").item(0)
;
//删除属性
Element node=(Element)root.getFirstChild();
Node.removeAttribute("ID")

【例 10.4】 使用 DOM 对象创建 XML 文件,代码如源程序 code10_4.java 所示。


import javax.xml.parsers.*;
import org.xml.sax.*;
import java.io.*;
import org.w3c.dom.*;
public class code10_4{
static Document document;
public static void main(String[] args) throws Exception{
DocumentBuilderFactory dbf=DocumentBuilderFactory.newInstance();
DocumentBuilder db=dbf.newDocumentBuilder();
//建立新的 XML 文件
document=db.newDocument();
//建立根元素
Element root=(Element)document.createElement("customer");
document.appendChild(root);
//新增子元素 customerID
Element newnode=(Element)document.createElement("customerID");
root.appendChild(newnode);
//增加元素的内容
newnode.appendChild(document.createTextNode("ID"));
// 增加元素的属性
newnode=(Element)root.getFirstChild();
newnode.setAttribute("ID","c050013");
//新增子元素 username
newnode=(Element)document.createElement("username");
root.appendChild(newnode);
//增加元素的内容
newnode.appendChild(document.createTextNode("cheaperget"));
//新增子元素 password
newnode=(Element)document.createElement("password");
//新增元素插入在根元素的最后一个孩子前面
root.insertBefore(newnode,root.getLastChild());
//新建文字结点
Node text=document.createTextNode("12345678");
//插入文字结点到根结点第一个子结点的兄弟结点,即第二子结点
Node temp=root.getFirstChild();
temp.getNextSibling().appendChild(text);
//显示 XML 文件
system.out.println("根元素:"+root.getNodeName());
//获取根元素的所有子结点
NodeList childs=root.getChildNodes();
for(int i=0;i<childs.getLength();i++)

·232·
第 10 章 XML 与 Java ·233·

{
//显示元素的名字和元素的内容(文字结点)
system.out.print("元素:"+childs.item(i).getNodeName());
system.out.println("/"+childs.item(i).getFirstChild().
getNodeValue());
//显示元素的的属性值
if(childs.item(i).hasAttributes())
{
//取属性列表
NamedNodeMap atts=childs.item(i).getAttributes();
//使用 for 循环获取各属性名称和值
for(int j=0;j<atts.getLength();j++)
{
Node att=atts.item(j);
System.out.print("--"+att.getNodeName());
System.out.println("/"+att.getNodeValue());
}
}
}
}
}

其显示结果如图 10.10 所示。

图 10.10 例 10.4 的运行结果

10.5 Java 程序中 XML 文件的转换

到目前为止,本书重点在于介绍使用 Java 对 XML 文档中的数据进行处理,而没有过


多考虑如何在用户面前展示 XML 文档中的数据。本节将讨论如何使用 Java 将 XML 文档
转换成 HTML 文件,这样就可以通过浏览器来显示 XML 文档的数据了。
【例 10.5】以 XSLT Script 转换 XML 文档为一个 HTML 文件。
以第 9 章的程序 code9_1.xml
为例进行转换,转换结果为 code10_5.html,代码如源程序 code10_5.java 所示。

·233·
·234· XML 实用教程

import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import java.io.*;
public class code10_5{
public static void main(String[] args) throws Exception{
//建立 TransformerFactory 对象
TransformerFactory factory=TransformerFactory.newInstance();
//以 XSLT Script 文件作为输入建立 Transformer 对象
Transformer transformer=factory.newTransformer(new
StreamSource("code9_1.xslt"));
//使用 StreamSource 加载 XML 文件
StreamSource xmlsource=new StreamSource("code9_1.xml");
//使用 StreamResult 创建与输出文档 HTML 文件的关联
StreamResult output=new StreamResult(new
FileOutputStream("code10_5.html"));
//转换 XML 文档
transformer.transform(xmlsource,output);
}
}

使用 IE 加载输出 HTML 文件,可以看到 XML 和 XSLT Script 的转换结果,如图 10.11


所示。

图 10.11 输出结果

·234·
第 10 章 XML 与 Java ·235·

从例题可以看出转换 XML 文件步骤为


(1) 引入套件。
import javax.xml.transform.*;
import javax.xml.transform.stream.*;
import java.io.*;

(2) 建立 TransformerFactory 对象和以 XSLT Script 作为输入建立 Transformer 对象。


(3) 输入 XML 文件创建 StreamSource 对象。
(4) 输出 StreamResult 创建与输出文档 HTML 文件的关联。
(5) 调用 Transformer 对象的 transform 方法生成 HTML 文件。

10.6 小 结

本章主要介绍 Java 应用程序如何使用 DOM 处理 XML 文件。要创建 DOM 需要使用


JAXP,JAXP 使得用 Java 开发处理 XML 文件的应用程序非常容易,只要在 Java 程序中导入
相关的套件,如 import javax.xml.parsers.*、import org.xml.sax.*、import org.w3c.dom.*、import
java.io.*,就可以使用它所提供的类和方法,让 Java 应用程序使用 DOM 加载 XML 文件,
访问、增加和删除 XML 元素和属性,转换 XML 文件了。

10.7 习 题

1. 在 Windows XP 系统的计算机上下载并安装 JDK。


2. 试列出 JAXP API 1.1 解析文档对象模型的相关套件。
3. 对于例 10.1,不设定加载参数,如何去掉多余的#text?
4. 改写例 10.3,使显示 DOM 树中所有元素时,同层元素在同一列上,下一层元素比
上层元素缩进两个空格。
5. 改写例 10.4,增加元素 address,其属性为 zipcode=215006,元素内容为“XX 省 XX
市人民路 616 号”,删除元素 customerID 及其属性。

·235·
第 11 章 XML 与 ASP

教学提示:ASP(Active Server Page)是 Microsoft 公司为了推广网络应用程序开发及数


据库链接而推出的一项技术。这项技术最早在 IIS(Internet Information Server)3.0 上开始使
用。由于 Windows、IIS 日益普及,ASP 凭借其简单而且功能强大的特点逐渐成为重要的
Web 应用开发技术。ADO(ActiveX Data Objects)是 Microsoft 公司众多数据存取技术中的一
种,用以包装复杂的数据存取动作,并提供简单易写的对象接口,ADO 已逐渐成为数据存
取的标准接口。XML 的可扩展性和灵活性,使其容易结合不同来源的结构化数据,能够描
述各种类型的应用程序中包含的数据,将查看数据的用户界面和数据本身分离,使设计功
能强大的应用程序成为可能。
教学目标:理解 ASP 的概念,掌握 ASP 的内建对象,了解 ADO 的基本功能,掌握如
何利用 ASP、ADO 与 XML 结合的方法,对数据库进行操作。

11.1 ASP 简介

在第 9 章中,使用 DOM 编写的脚本都是嵌套在客户端的 HTML 页面中的,基于安全


的因素,DOM 的许多功能受到限制,如不能动态修改 XML 文档的内容。而使用 ASP,可
以利用脚本来创建动态的文档,即使用 ASP 来动态生成和修改 XML 文档。在 ASP 中,可
以使用多种脚本语言,如 VBScript、JavaScript,为开发人员提供广阔的选择空间,利用
ADO 组件轻松存取数据库。ASP 简单易学,目前使用非常广泛,很多大型站点都是用 ASP
开发的。

11.1.1 ASP 的功能

ASP 是 Web 服务器端的开发环境,利用它可以产生和执行动态的、互动的、高性能的


Web 服务应用程序。ASP 允许采用脚本语言 VBScript 和 JavaScript 作为自己的开发语言,
默认为 VBScript,采用微软的 IIS 作为其服务器。
ASP 能够将代码直接嵌入 HTML 中,使得设计 Web 页面变得更简单、更强大,并且
通过内置的组件能够实现强大功能,最明显的就是 ADO(ActiveX Data Objects),它使得建
立一个动态页面十分简单。
ASP 与 ADO 的结合使开发者很容易在一个数据库中建立和打开一个记录集,这很快
就被大众所接受,因为开发者现在能使用这些脚本建立和打开一个记录集,并可以任何顺
序处理和输出任何数据,几乎只要能想到的,它就能完成。
ASP 实际上是将标准的 HTML 文件拓展了一些附加特征,并像标准的 HTML 文件一
样包含 HTML 对象,然后在一个浏览器上解释并显示出来。任何可以放在 HTML 中的东
第 11 章 XML 与 ASP ·237·

西,如 Java 小程序、闪烁字符串、客户端脚本和客户端 ActiveX 控件等,都可以放在 ASP


中。因此,一个 ASP 有如下 4 个重要特征来使之具备很强的通用性。
(1) ASP 可以包括服务端脚本;
(2) ASP 提供了一些内建对象;
(3) ASP 可以用另外的元素来扩展;
(4) ASP 可以和数据库、XML 等外部数据源进行挂接。

11.1.2 ASP 内建对象

ASP 的功能是十分强大的,这首先要来源于它内建的 6 个基本对象,这 6 个内建对象


提供了大量的基本功能,让编程变得更加容易。
1. Application 对象
Application 对象被用来存储一个应用中所有用户共享的信息。它实际上由在硬盘上的
一组主页以及 ASP 文件组成,当一个 ASP 加入了一个 Application,那么它就拥有了作为单
独主页所无法拥有的属性,通过这些属性,可以存储所有用户的共同信息。例如,可以利
用 Application 对象在站点的不同用户间传递信息。
Application 对象还有两个事件 Application_OnStart 和 Application_OnEnd,第一个事件
在 Application 开始时触发,第二个事件在 Application 结束时触发。
2. Request 对象
Request 对象可以被用来访问所有从浏览器到服务器间的信息。通过使用 Request 对象,
可以得出许多来自于客户端的信息,例如,可以从 HTML 的表单中接收信息,或者通过
URL 地址后面用问号带着的 Query 字段来查询特定信息。
3. Response 对象
Response 对象用来将信息发送给浏览器。Response 是和 Request 相对的一个对象,它
们一个负责服务器端的响应,一个负责浏览器端的请求,使浏览器端可以和服务器端很好
地完成交互。
最常用的 Response 对象的功能就是显示服务器端发回的信息,此外,还可以使用它来
产生页面的重定向。
4. Server 对象
Server 对象提供了大量服务器端的应用函数。通过 Server 对象,可以创建其他外部对
象的实例,使 ASP 的功能大大的增强了。此外,还可以用 Server 对象来控制网页页面的超
时时间。
5. Session 对象
Session 对象被用来存储一些普通用户滞留期间的信息。Session 实际上指的就是访问
者从到达某个特定主页至离开为止的那段时间,每个访问者都会单独获得一个 Session 对象。
Session 对象是十分常用的,可以用来跟踪访问者的习惯,如访问者是喜好绿色背景还
是蓝色?访问者是否喜欢浮动菜单?这些信息都可以依据 Session 来跟踪。

·237·
·238· XML 实用教程

Session 还可以创建虚拟购物篮。无论什么时候当用户在网站中选择了一种产品,那么
这种产品就会进入购物篮,当他(她)准备离开时,就可以立即进行以上所有选择产品的订
购,这些购物信息可以被保存在 Session 中。

11.2 ADO 的内部对象

ADO 是 Microsoft 公司众多数据存取技术中的一种,用以包装复杂的数据存取动作,


并提供简单易写的对象接口。ADO 就是要达到一个简单的目的:只需要使用一种方式来存
取各种数据、提供与任何形式的数据源连接的机制。最常见的数据源就是关系数据库,但
是在 ADO 中,数据源不只局限于关系数据库,甚至连电子邮件系统都可以是数据源,这
是与以往的 ODBC 数据库技术不同的地方。
ADO 目前已成为数据存取的标准接口,其主要功能是让应用程序存取、操纵来自数据
库服务器的数据。
ADO 包括很多对象和子对象,有大量的属性和方法。如果系统掌握了这些属性和方法,
就能够完成更多、更高级的功能。
ADO 的主要对象有 3 个,分别为 Connection、Command 和 Recordset,3 个对象的主
要功能见表 11-1。

表 11-1 ADO 对象及其主要功能

对 象 说 明

Connection 用来建立与数据库的连接

Command 用来对数据库执行命令,如查询、删除、修改记录等

Recordset 用来得到从数据库返回的记录集

Connection 对象又称连接对象,主要用来建立与数据库的连接。只有建立连接后,才
能利用 Command 和 Recordset 对象对数据库进行各种操作。
Command 对象又称命令对象,是对数据库执行命令的对象,它可以执行对数据库查询、
添加、删除、修改等记录操作。当然,也可利用 Connection 对象的 Execute 方法进行查询、
添加、删除、修改记录等操作,这是一种常用方法。
Recordset 对象又称记录集对象,是最主要的对象。当用 Command 或 Connection 对象
执行查询命令后,就会得到一个记录集对象,该记录集包含满足条件的所有记录。利用
Recordset 对象也可以添加、删除或修改记录。
这 3 个对象看起来逻辑关系还是比较简单的,利用 Connection 对象和数据库建立连接,
然后用 Command 对象执行命令,最后在得到的 Recordset 对象中具体操作。

11.2.1 Connection 对象

Connection 对象是用来连接数据库的。关于该对象,需要注意以下几点。

·238·
第 11 章 XML 与 ASP ·239·

一般需要明确建立 Connection 对象,但也可以不明确建立,而是利用 Command 或


Recordset 对象直接连接数据库,这样将建立一个隐含的 Connection 对象,只是无法利用
Connection 对象的许多功能,也就无法发挥 Connection 对象的巨大作用了。
Connection 对象一般用来建立与数据库的连接,也可以用它来查询、添加、删除、修
改记录。这是一种常用的方法,但是与利用 Command 和 Recordset 对象相比有一定的局限
性,比如无法实现分页显示记录功能。
学习 Connection 对象有几个比较重要的内容。
首先是如何建立 Connection 对象,本章主要介绍建立与 Access 数据库的各种连接方法。
其次一定要注意 Connection 对象的 Execute 方法,尽管利用该方法查询记录有一定的
局限性,但它确实是一个非常简单、好用和常用的方法。
1. 建立 Connection 对象
使用 Connection 对象之前,首先要建立该对象。在 ADO 中建立对象一般需要利用 Server
对象的 CreatObject 方法,语法格式如下:
set Connection 对象=Server.CreateObject(“ADODB.Connection”)
建立对象后,可以利用 Connection 对象的 Open 方法来打开数据库并与之建立连接,
语法格式如下:
Connection 对象.Open“参数 1=参数 1 的值;参数 2=参数 2 的值;…”
其中参数的意义见表 11-2。

表 11-2 Connection 对象的 Open 方法的参数

参 数 说 明

Dsn ODBC 数据源名称

User 数据库登录账号

Password 数据库登录密码

Driver 数据库的类型(驱动程序)

Dbq 数据库的物理路径

Provider 数据提供者

2. Connection 对象的属性
Connection 对象有很多属性,常用的属性见表 11-3。

表 11-3 Connection 对象的常用属性

属 性 说 明

Attributes 设置 Connection 对象控制事务处理时的行为

CommandTimeout Execute 方法的最长执行时间

ConnectionString 指定 Connection 对象的数据库连接信息

·239·
·240· XML 实用教程

续表

属 性 说 明

ConnectionTimeout Open 方法与数据库链接的执行最长时间

CursorLocation 控制光标的类型

DefaultDatabase 指定 Connection 对象的默认数据库名称

IsolationLevel 指定 Connection 对象事务处理的时机

Mode 设置连接数据库的权根

Provider 设置 Connection 对象内定的数据库管理程序名称

Version 显示 ADO 对象的版本信息

比较常用的有以下几个。
1) ConnectionString
该属性用于指定 Connection 对象的数据库连接信息。下面的例子也可以建立与数据库
的连接:
<%
dim db
dim strSql
set db=Server.CreateObject("ADODB.Connection")'创建数据库连接对象
StrCon="Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" &
Server.Mappath("address.mdb")
db.Open StrCon'建立与数据库的连接
%>

2) ConnectionTimeout
该属性用于指定 Connection 对象的 Open 方法与数据库连接的执行最长时间。当时间
到了数据库还没有正确连接上,就停止执行。
该属性的默认值为 15s,如果设定为 0,则表示无限期等候直到 Open 方法完成为止。
下面例子将默认值设置为 30s:
<%db.ConnectionTimeout=30%>

同 CommandTimeout 一样,如果服务器比较慢,可以设置连接时间长些。
3) DefaultDatabase
一般的数据提供者只能提供一个数据库,有的数据提供者却能提供多个数据库,用该
属性可以在多个数据库中指定默认的数据库。
3. Connection 对象的方法
Connection 对象有很多方法,都比较有用,其中 Open 方法和 Execute 方法是最常用的
方法。更多的常用方法见表 11-4。

·240·
第 11 章 XML 与 ASP ·241·

表 11-4 Connection 对象的常用方法

方 法 说 明
Open 建立与数据库的连接
Close 关闭与数据库的连接
Execute 执行数据库查询(可以执行各种操作)
BeginTrans 开始事务处理
CommitTrans 提交事务处理结果
RollbackTrans 取消事务处理结果

下面详细介绍。
1) Open
该方法用来建立与数据库的连接。只有用 Open 方法和数据库建立连接后,才可以继
续进行各种操作。
2) Close
该方法用来关闭一个已打开的 Connection 对象及其相关的各种对象。它的作用主要是
用以切断与数据库之间的连接通道。当该通道被关闭后,所有依赖该 Connection 对象的
Command 或 Recordset 对象也将立即被切断关系,方法如下:
<%
db.Close '关闭与数据库的连接
set db=nothing '从内存中彻底清除 Connection 对象 db,也可以省略
%>

说明:其实也可以不用该方法关闭对象,因为当一个页面关闭后,Connection 对象会
自动关闭。不过养成使用完主动关闭的习惯还是很好的,有时可以节省内存资源。
3) Execute
该方法用来执行数据库查询,可以完成几乎所有的功能。它的语法格式有两种:
set Recordset 对象=Connection 对象.Execute(SQL 字符串)
或 Connection 对象.Execute(SQL 字符串)

11.2.2 Recordset 对象

Recordset 对象又称记录集对象,ADO 中是最主要的对象。当用 Command 或 Connection


对象执行查询命令后,就会得到一个记录集对象,该记录集包含满足条件的所有记录,然
后就可以利用 ASP 语句将记录集的数据显示在页面上。
以前已经多次建立 Recordset 对象,主要是利用 Connection 或 Command 对象的 Execute
方法。其标准的语法格式如下:
set Recordset 对象=Server.CreateObject(“ADODB.Recordset”)

然后,就可以用 Open 方法打开一个数据库,语法格式如下:


Recordset 对象.Open[Source],[ActiveConnection],[CursorType],[LockType],
[Options]

该方法的参数意义见表 11-5~表 11-8。

·241·
·242· XML 实用教程

表 11-5 Recordset 对象的 Open 方法的参数意义

参 数 说 明

Soruce Command 对象名或 SQL 语句或数据表名

ActiveConncetion Connection 对象名或包含数据库连接信息的字符串

CursorType Recordset 对象记录集中的指针类型,可省略

LockType Recordset 对象的使用类型,可省略

Options Source 类型,可省略

表 11-6 CursorType 参数取值

默 认 数 值 描 述

向前指针,只能利用 MoveNext 或 GetRows 向前移动检索数据,


AdOpenForwardOnly 0
默认值
键盘指针,在记录集中可以向前或向后移动,当某客户做了修
AdOpenKeyset 1
改后(除了增加新数据),其他用户都可以立即显示
动态指针,记录集中可以向前或向后移动,所有修改都会立即
AdOpenDynamic 2
在其他客户端显示
静态指针,在记录集中可以向前或向后移动,所有更新的数据
AdOpenStatic 3
都不会显示在其他客户端

表 11-7 LockType 参数取值

LockType 参数 数 值 描 述

AdLockReadOnly 1 只读,不许修改记录集,默认值

AdLockPessimistic 2 只能同时被一个客户修改,修改时锁定,修改完毕释放

AdLockOptimistic 3 可以同时被多个客户修改

AdLockBatchOptimistic 4 数据可以修改,但不锁定其他客户

表 11-8 Options 参数取值

Options 参数 值 说 明

adCmdUnknown -1 CommandText 参数类型无法确定,是系统的默认值

AdCmdText 1 CommandText 参数是命令类型

AdCmdTable 2 CommandText 参数是一个表名称

adCmdStoreProc 3 CommandText 参数是一个存储过程名称

·242·
第 11 章 XML 与 ASP ·243·

总的来说,Source 是数据库查询信息,ActiveConnection 是数据库连接信息,CursorType


是指针类型(也称游标类型),LockType 是锁定信息,Options 是数据库查询信息类型。
大部分情况下可以省略后 3 个参数,但有些情况下必须使用。例如,如不设置 CursorType
类型,在记录集中就只能向前移动指针,而不能向后移动指针。
如果要省略中间的参数,则必须用逗号给中间的参数留出位置,也就是说,每一个参
数必须对应相应的位置。例如:
<% set rs.Open "Select * From users",cmd,,2 %>

在这个例子中,省略了第 3 个和第 5 个参数,但必须用逗号给第 3 个参数留出位置,


当然,第 5 个在最后,就不用管了。

11.2.3 Recordset 对象的方法

以前几乎只用到 Recordset 对象的两个方法:Open 和 MoveNext,更多的方法见


表 11-9。

表 11-9 Recordset 对象的常用方法

方 法 说 明
Open 打开记录集
Close 关闭当前的 Recordset 对象
Requery 重新打开记录集
MoveFirst 移动到第一条记录
MoveProvious 移动到上一条记录(向后移动)
MoveNext 移动到下一条记录(向前移动)
MoveLast 移动到最后一条记录
Move 移动到指定记录
AddNew 添加新记录
Delete 删除当前记录
Update 更新数据库数据
CancelUpdate 取消数据更新
GetRows 从记录集中取得多行数据
Resync 与数据库服务器同步更新

Recordset 对象的方法也可以按照功能分为几组,第一组主要是关于 Recordset 对象


本身。
(1) Open 方法用来打开记录集,语法格式如下:
Recordset 对象.Open[Source],[ActiveConnection],[CursorType],[LockType],
[Options]

(2) Close 方法用于关闭 Recordset 对象。与 Connection 对象的关闭方法一样,不用时就

·243·
·244· XML 实用教程

关闭,语法格式如下:
Recordset 对象.Close

(3) MoveFirst 方法用于记录指针移动到第一条记录,语法格式如下:


Recordset 对象.MoveFirst

(4) MovePrevious 方法用于将记录指针移动到上一条记录,也就是向前移动一条,语法


格式如下:
Recordset 对象.MovePrevious

(5) MoveNext 方法用于将记录指针移动到下一条记录,也就是向后移动一条,语法


格式如下:
Recordset 对象.MoveNext

(6) MoveLast 方法用于将指针移动到最后一条记录,语法格式如下:


Recordset 对象.MoveLast

(7) Move 方法用于将指针移动到指定的记录,语法格式如下:


Recordset 对象.Move number,start

(8) AddNew 方法用于向数据库添加记录,语法格式如下:


Recordset 对象.AddNew 字段名数组,字段值数组

若只有一个字段,则语法格式如下:
Recordset 对象.AddNew 字段名,字段值

(9) Delete 方法用于删除当前记录,语法格式如下:


Recordset 对象.Delete

(10) Update 方法用于更新数据库数据,语法格式如下:


Recordset 对象. Update

执行完 AddNew 或 Delete 方法后,必须执行 Update 方法,才能真正更新数据库(如果


更新后,又移动了记录指针,也将自动更新数据库),例如:
<%
rs.AddNew Fields,Values
rs.Update
%>

11.2.4 利用 Connection、Recordset 对象存取数据表数据

利用 Connection 对象存取数据库的主要内容是利用 Connection 对象的 Execute 方法对


数据库记录进行查询操作。
【例 11.1】 利用 Connection 对象存取数据库的基本操作,代码如源程序 code11_1.asp
所示。

·244·
第 11 章 XML 与 ASP ·245·

<html>
<head>
<title>数据库的基本操作</title>
<head>
<body>
<%
'连接数据库,建立 Connection 对象,address.mdb 下面将建立
dim db
dim strSq1,rs '定义变量
set db=Server.CreateObject("ADODB.Connection")
strCon="Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" &
Server.Mappath("address.mdb")
Db.Open StrCon
StrSq1="Select * From users"
'查询记录
'以下建立 Recordset 对象实例 rs
set rs=db.Execute(strSq1)
do while not rs.Eof
Response.Write rs("name") & " " & rs("tel") & " " & rs("age") &
"<br>"
Rs.MoveNext
Loop
%>
</body>
</html>

其显示结果如图 11.1 所示。

图 11.1 使用 ASP 对数据库表数据查询显示

程序说明:本例主要是为了加深大家对数据库基本操作语法的理解,同时也是强调这
几种方法的重要性。

11.3 XML 在 ASP 中的应用

要使用一个数据库,必须安装和支持一个分离的服务器处理进程,它常要求有安装和
支持它的管理员。必须学习 SQL 语句,并用 SQL 语句写查询,然后转换数据,再返回。
而如果用 XML 文件存储数据,将可以减少额外的服务器负荷。此外还有一个编辑数据的
简单方法。只需使用文本编辑器,而不必使用复杂的数据库工具。XML 文件很容易备份和
下载到客户端。

·245·
·246· XML 实用教程

XML 还有一个更抽象的优点,即作为层次型的格式比关系型的更好。它可以用一种很
直接的方式来设计数据结构以符合需要。不需要使用实体—关系编辑器,也不需要使图表
标准化。如果一个元素包含了另一个元素,可以直接在格式中表示它,而不需要使用表的
关联。
ADO 定义一个完整的功能接口,允许把 Recordset 作为 XML 文件来存取。除了自己编
写 ASP 程序代码浏览 Recordset 然后将各条记录存储为 XML 标记数据之外,还可以通过
Recordset 对象的 save 方法直接将 Recordset 内的记录存储成 XML 格式(文件或网页)。

11.3.1 使用 ASP 创建 XML DOM 对象

要想在 ASP 中对 XML 文件进行操作,必须在脚本中创建 DOMDocument 对象实例,


DOMDocument 对象代表了 XML 文档,即 XML 文档的 DOM 模型中的文档根结点。使用
DOM 方法对 XML 进行处理的基本步骤如下。
1. 创建一个 DOM 对象的实例
首先,要在服务器端创建一个 XML DOM 对象的实例。这时,就要用到前面所说的
Server 内建对象了。Server 对象有一个 CreatObject 方法,可以用来创建外部对象的实例,
如程序代码:
<%@Language="VBScript"%>
<%
objDom=Server.CreateObject("MicroSoft.XMLDom")
%>

在这个例子中,创建了一个 IE 集成的 XML DOM 对象的实例,当然,也可以创建其


他 XML DOM 对象,只要对象在系统中注册过即可。
2. 为对象导入特定的 XML 文件
已经有了 XML DOM 对象的实例,就可以为实例指定一个特定的 XML 文件了,如程
序代码:
<%@Language="VBScript"%>
<%
objDom.load(Server.MapPath("book.xml"))
%>

这里,使用 load 方法导入了 XML 文件,需要注意的是,XML 的路径可以使用 URL


地址,也可以使用相对地址,但使用相对地址时必须将地址通过 Server 对象的 MapPath 方
法转换为 URL 地址,否则服务器将无法找到 XML 文件。
3. 执行具体的工作
有了与 XML 文件关联的 DOM 对象后,就可以执行各种具体的工作了,至于是什么工
作,就由程序所需要达到的目的决定。

11.3.2 使用 ASP 遍历 XMLDOM 对象

下面创建一个 ASP 文档,其作用是遍历 XML 文档,获得 XML 文档的结点信息和结

·246·
第 11 章 XML 与 ASP ·247·

点值。为 ASP 准备的 XML 文档——book.xml。


<?xml version="1.0" encoding="gb2312"?>
<books>
<book id="001" bookcategory="文艺" amount="100" remain="80"
discount="8.7">
<bookinfo>
<title>三国演义</title>
<author>罗贯中</author>
<publish>
<publisher>文艺出版社</publisher>
<ISBN>0-764-58007-8</ISBN>
<pubdate>1998.10</pubdate>
</publish>
<price>80</price>
</bookinfo>
<resume>
滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。白发渔樵江
渚上,惯看秋月春风。一壶浊酒喜相逢。古今多少事,都付笑谈中。</resume>
<recommendation>经典好书</recommendation>
<chapter>
<title>宴桃园豪杰三结义 斩黄巾英雄首立功</title>
<para> 话说天下大势,分久必合,合久必分。</para>
</chapter>
<chapter>
<title>张翼德怒鞭督邮 何国舅谋诛宦竖</title>
<para>且说董卓字仲颖,陇西临洮人也,官拜河东太守,自来骄傲。</para>
</chapter>
</book>
<book id="018" bookcategory="计算机" amount="560" remain="200"
discount="8.2">
<bookinfo>
<title>计算机导论</title>
<author>丁跃潮等</author>
<publish>
<publisher>高等教育出版社</publisher>
<ISBN>7-04-014768-8</ISBN>
<pubdate>2004.6</pubdate>
</publish>
<price>19.7</price>
</bookinfo>
<resume>本书是学习计算机专业知识的入门教材,体现计算机专业主干课程的经典教学内
容。全书注重在较低计算机知识背景下系统了解和认识计算机科学的全貌,理解基本原理,掌握
关键概念。</resume>
<recommendation>推广教材</recommendation>
<chapter>
<title>第 1 章 计算机基础知识</title>
<para>计算机是一种能快速而高效地完成信息处理的数字化电子设备。…</para>
</chapter>
<chapter>
<title>第 2 章 计算机硬件基础</title>

·247·
·248· XML 实用教程

<para>硬件就是构成计算机各部件的实体,是计算机中看得见、摸得到的部分。硬件是
计算机工作的前提。…</para>
</chapter>
</book>
</books>

ASP 文档用于遍历 book.xml,使用程序 code11_2.asp 可以得到 XML 文档的全部内容。


【例 11.2】 遍历 XML 文档的 ASP 程序,代码如源程序 code11_2.asp 所示。
<%@ Language=VBScript %>
<%
set xmlDoc=Server.createObject("Microsoft.XMLDom")
dim MyNode,namedNodeMap
xmlDoc.load(Server.MapPath("book.xml"))
'获取结点为信息
getallnodes(xmlDoc)
'子程序,用于获得结点信息
sub getallnodes(node)
dim I
'当前结点信息
Response.write("<br><b>结点名称:")
Response.write(node.nodeName)
Response.write("</b><br>结点类型:")
Response.write(node.nodeTypeString)
Response.write("<br>结点值:")
Response.write(node.nodeValue)
'获得子结点信息
if node.childNodes.length<>0 then
for i=0 to node.childNodes.length-1
getallnodes(node.childNodes(i))
next
end if
end sub
%>

执行 code11_2.asp,结果如图 11.2 所示。

图 11.2 使用 ASP 遍历 XML 文档

·248·
第 11 章 XML 与 ASP ·249·

在该文档中,直接使用 Response.write 方法将结果返回。


在程序 code11_2.asp 中,首先使用了 Server.CreateObject 方法创建 XML 文档的 DOMD
ocument 对象实例,如下所示。
set xmlDoc=Server.createObject("Microsoft.XMLDom")

这是 VBScript 中的语法。set 命令将 xmlDoc 实例化为 DOMDocument 对象实例。


在将 XML 文档加载到 xmlDoc 对象中时,使用了 load 方法,如下所示:
xmlDoc.load(Server.MapPath("xmldata.xml")

load 方法的参数使用了 Server.MapPath 方法来指定,表示加载的 XML 文档在 Web 服


务器上。load 方法可以使用 loadXML 方法替换,两者作用相同。
在获得结点信息时,定义了一个子程序 getallnodes()。在 getallnodes()中首先输出了当
前结点的信息,如下所示:
'当前结点信息
Response.write("<br><b>结点名称:")
Response.write(node.nodeName)
Response.write("</b><br>结点类型:")
Response.write(node.nodeTypeString)
Response.write("<br>结点值:")
Response.write(node.nodeValue)

输出当前结点之后,通过递归调用 getallnodes()来获得当前结点子结点的信息,如下
所示:
'获得子结点信息
if node.childNodes.length<>0 then
for i=0 to node.childNodes.length-1
getnodes(node.childNodes(i)
next
end if

11.3.3 使用 ASP 显示 XML 文件

本实例采用 ASP+XMLDOM 的编程框架,目的在于让读者了解如何在 ASP 中使用


xmlDoc 格式化显示 XML 文件。
【例 11.3】 使用 ASP 程序格式化显示 XML 文档,代码如源程序 code11_3.asp 所示。
<%@Language="JavaScript"%>
<html>
<head>
<title>图书信息列表</title>
<meta http-equiv="Content-Type"content="text/html; charset=gb2312">
</head>
<body>
<p align="center"><font size="7">图书列表</font></p>

·249·
·250· XML 实用教程

<table width="100%" border="1">


<tr>
<td><div align="center">书名</div></td>
<td><div align="center">简介</div></td>
<td><div align="center">评论</div></td>
<td><div align="center">章节</div></td>
<td><div align="center">章节</div></td>
<tr>
<%
//创建 XML DOM 对象
var objDom=Server.CreateObject("MicroSoft.XMLDom");
//导入 XML 文件
objDom.load(Server.Mappath("book.xml"));
//选取 book 结点集合
var bookitems=objDom.selectNodes("books/book");
var bookitem=bookitems.nextNode();
//利用两重循环输出每个 book 结点的内容
//第一重循环
for(var i=0;i<bookitems.length;i++,bookitem=bookitems.nextNode())
{
%>
<tr>
<%
var childitems=bookitem.childNodes;
//第二重循环
for(item=childitems.nextNode();item;item=item.nextSibling)
{
%>
<td><div align="center"><%=item.text%></div></td>
<%
}
%>
</tr>
<%
}
%>
</table>
</body>
</html>

在 IE 中运行 code11_3.asp 程序,结果如图 11.3 所示。

11.3.4 使用 ASP 创建 XML 文档

如果要将信息保存为 XML 格式,首先便需要在 ASP 中创建 XML 文档。例 11.4 中 ASP


文档用于在服务器中创建一个 XML 文档。

·250·
第 11 章 XML 与 ASP ·251·

图 11.3 使用 ASP 格式化显示 XML 文档

【例 11.4】 使用 ASP 创建 XML 文档,代码如源程序 code11_4.asp 所示。


<%
set doc=Server.createObject("Microsoft.XMLDom")
doc.loadXML("<?xml version='1.0' ?><root>在 ASP 中创建的 XML 文档</root>")
doc.save(Server.MapPath("sample.xml"))
Response.write("XML 文档创建成功")
%>

文档使用了 Server.CreateObject 方法来创建 DOM 对象文档。第 2 条语句使用了 loadXML


方法(也可使用 load 方法)将需要创建的 XML 文档内容存入缓冲区,当然也可以使用该方法
将其他的 XML 文档存入缓冲区备用。第 3 条语句使用了 save 方法将缓冲区中的内容存入
XML 文档,在指定保存对象时,使用了 Server.MapPath(“sample.xml”)。Server.MapPath 表
示服务器的当前目录之下,并命名为 sample.xml。第 4 条语句使用 Response 的 write 方法
输出一条信息,如果在创建文档的过程中没有出现错误,则该语句被执行。在浏览器中便
可以看到输出的信息。如果出错,那么看到的将是相应的错误信息。
在 IE 中运行程序 code11_4.asp,创建的 XML 文档结构如下:
<?xml version="1.0"?>
<root>在 ASP 中创建的 XML 文档</root>

11.3.5 使用 ASP 转换 XML 文档成 HTML 文档

并不是所有的浏览器都可以支持 XML,为了保证能够通过浏览器查看到 XML 文档的


内容,可以在服务器端使用 ASP 将 XML 文档转换为标准的 HTML 文档。使用 ASP 转换
XML 文档时,需要为 XML 文档设计好 XSL 样式表,然后利用 DOMDocument 对象的

·251·
·252· XML 实用教程

TransFormNode 方法使用样式表将 XML 文档转换为 HTML 文档。


下面将创建用于转换 XML 文档的 ASP 脚本。例 11.5 列出了等待转换的 XML 文档,
例 11.6 列出了转换 XML 文档使用的 XSL 样式表,例 11.7 列出了用于完成转换的 ASP 文档。
【例 11.5】 待转换的 XML 源文档 code11_5.xml。
<?xml version="1.0" encoding="gb2312"?>
<网上书屋>
<书籍>
<书名>Red Hat Linux 系统管理大全</书名>
<作者>Thomas Schenk</作者>
<出版社>机械工业出版社</出版社>
</书籍>
<书籍>
<书名>中文版 Windows NT 技术支持培训教程</书名>
<作者>Microsoft Press</作者>
<出版社>人民出版社</出版社>
</书籍>
<书籍>
<书名>Red Hat Linux 宝典</书名>
<作者>Christopher Negus</作者>
<出版社>电子工业出版社</出版社>
</书籍>
</网上书屋>

【例 11.6】 转换 XML 文档的 XSL 样式表 code11_6.xsl。


<?xml version='1.0' encoding="gb2312" ?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/TR/WD-xsl"
xmlns="http://www.w3.org/TR/REC-html40" >
<xsl:template match="/">
<html><head><title>图书信息列表</title></head>
<body>
<xsl:apply-templates/>
</body></html>
</xsl:template>
<xsl:template match="网上书屋">
<center><h1>图书信息列表</h1>
<table border="1">
<th>书名</th><th>作者</th><th>出版社</th>
<xsl:apply-templates/>
</table>
</center>
</xsl:template>
<xsl:template match="分类">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="书籍">
<tr>
<td><xsl:value-of select="书名"/></td>
<td><xsl:value-of select="作者"/></td>

·252·
第 11 章 XML 与 ASP ·253·

<td><xsl:value-of select="出版社"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>

【例 11.7】 完成转换的 ASP 脚本程序 code11_7.asp。


<%@ Language="VBScript" %>
<%
'定义使用的变量
dim xmldoc,xsldoc,result
'创建 DOMDocument 对象实例 xmldoc
'将使用 xmldoc 来加载需要转换的 XML 文档
set xmldoc=Server.createObject("Microsoft.XMLDOM")
'设置并不同步加载 XML 文档
xmldoc.async=false
'加载 XML 文档
xmldoc.load(Server.MapPath("code11_5.xml"))
'判断加载的 XML 文档是否有错,有则输出错误原因
if (xmldoc.parseError.errorCode<>0) then
Response.write("发生错误:"+xmldoc.parseError.reason)
Response.End
end if
'创建 DOMDocument 对象实例 xsldoc
'将使用 xsldoc 来加载转换 XML 文档使用的样式单
set xsldoc=Server.createObject("Microsoft.XMLDOM")
xsldoc.async=false
'加载样式单
xsldoc.load(Server.MapPath("code11_6.xsl"))
'判断样式单中是否有错,有则输出出错原因
if(xsldoc.parseError.errorCode<>0) then
Response.write("发生错误:"+xsldoc.parseError.reason)
Response.End
end if
'使用样式单转换 XML 文档
result=xmldoc.transformNode(xsldoc)
'输出转换结果
Response.write(result)
%>

执行程序 code11_7.asp。在 IE 中查看的结果如图 11.4 所示。


从程序 code11_7.asp 中可以看出,使用 ASP 转换 XML 文档需要 4 个步骤:
(1) 创建 DOMDocument 实例对象 xmldoc,并将 XML 文档 xmlsrc.xml 装入对象。
(2) 创建 DOMDocument 实例对象 xsldoc,并将转换 XML 文档使用的样式单 xslsrc.xsl
装入对象。
(3) 使用 xmldoc 对象的 TransFormNode 方法按照样式表将 XML 文档转换成标准的
HTML 文档。
(4) 使用 Response.write 方法将转换得到的结果(标准 HTML 格式)输出到客户浏览器中
显示。

·253·
·254· XML 实用教程

在浏览器中查看结果时,选择【查看】|【源文件】来查看使用 ASP 转换得到的 HTML


源代码,如图 11.4 所示。

图 11.4 使用 ASP 转换 XML 文档成 HTML 文档

在浏览器中可看到 HTML 源代码如下:


<html>
<head><title>网上书屋</title></head>
<body>
<center><h1>阿当网上书屋</h1>
<table border="1">
<th>书名</th><th>作者</th><th>出版社</th>
<tr>
<td>Red Hat Linux 系统管理大全</td>
<td>Thomas Schenk</td>
<td>机械工业出版社</td>
</tr>
<tr>
<td>中文版 Windows NT 技术支持培训教程</td>
<td>Microsoft Press</td>
<td>人民出版社</td>
</tr>
<tr>
<td>Red Hat Linux 宝典</td>
<td>Christopher Negus</td>
<td>电子工业出版社</td>
</tr>
</table>
</center>
</body>
</html>

11.3.6 数据库记录转换成 XML 文档

XML 文档在很多方面与传统的关系数据库相似,在 ASP 中,可以通过一定的处理方

·254·
第 11 章 XML 与 ASP ·255·

式,可以轻松而且正确地将数据库的记录导入到 XML 文件中。语法格式:


Recordset 对象变量.Save 目标数据流,存储格式
(1) 目标数据流:路径名称,用来指定 Recordset 要存储的位置。
(2) 存储格式:用来指定 Recordset 的存储形式,共有 3 种,见表 11-10。而这里所要
用的是 adPersistXML。

表 11-10 ADO Recordset save 方法的参数列表

存储格式参数 对应的参数值 格式叙述

AdPersistADTG 0 表格格式(Advanced Data TableGram)

AdPersistXML 1 XML 格式

AdPersistProviderSpecific 2 Provider 所提供的格式

使 ActiveX 数据对象(ADO)的 Recordset 能够存储为 XML。这对于将 Recordset 保存在


客户计算机上用于脱机使用很有用处。
要将 Recordset 作为 XML 来保存,就要调用 save 方法,并将目标文件及 adPersistXML
标志进行传递。
【例 11.8】 通过 Recordset 生成 XML 实例,代码如源程序 code11_8.asp 所示。
<html>
<head>
<title>数据库的基本操作</title>
<head>
<body>
<%
'连接数据库,建立 Connection 对象,连接 address.mdb 数据库
dim db
dim strSq1,rs '定义变量
set db=Server.CreateObject("ADODB.Connection")
StrCon="Provider=Microsoft.Jet.OLEDB.4.0;" & "Data Source=" & _
Server.Mappath("address.mdb")
Db.Open StrCon
StrSq1="Select * From users"
'查询记录
'以下建立 Recordset 对象实例 rs
set rs=db.Execute(strSq1)
'在当前目录下生成 XML 文件
rs.Save "recordset.xml",1
%>
</body>
</html>

在浏览器中查看结果时,如图 11.5 所示。

·255·
·256· XML 实用教程

图 11.5 数据库记录转换成 XML 文档

11.4 综 合 实 例

留言簿在 Internet 中很常见,通常,保存留言需要使用数据库,这就要求创作人员必须懂


得一门数据库的基本知识。对于 SQL Server 数据库,要通过 ASP 或其他脚本程序来访问,
就要建立 SQL 数据库服务器。其他的一些数据库也通过使用 ODBC 来访问。客户通过浏
览器访问基于数据库的留言簿流程如下。
首先,客户通过浏览器向 Web 服务器发出访问请求,Web 服务器在收到请求之后,将客
户的数据请求发送给数据库服务器,数据库服务器根据请求访问特定的数据库获得数据,
然后将数据返回给 Web 服务器,Web 服务器再将数据返回到客户端的浏览器中。
如果使用 XML 文档来保存客户的留言,因为 XML 文档本身是一个文本文件,从而可
以直接放在 Web 服务器中。访问 XML 文档比访问数据库简单许多,客户从浏览器发出请
求,Web 服务器收到请求之后,就在服务器的 XML 文档中提取出客户需要的数据,然后
返回给客户。使用 XML 文档来保存数据,减少了访问流程,提高了响应速度,也不需要
Web 创作人员其他的数据库知识,降低了 Web 创作的任务难度,也降低了建立 Web 站点
的开销。

·256·
第 11 章 XML 与 ASP ·257·

结合 ASP 和 XML 技术,在 Windows 2000 下使用 ASP,实现一个基于 XML 的留言簿。


要实现的留言簿主要具有留言列表、查看留言信息和删除留言信息 3 个基本功能。实现这
3 个基本功能,将使用到 ASP 遍历 XML 文档(查看留言)、为 XML 文档添加元素(保存留言)、
删除 XML 文档元素(删除留言)。
要实现的留言簿包括首页、留言、删除留言 3 个主要部分。留言簿首页如图 11.6 所示。
在首页中单击“留言”链接,可以打开书写留言的页面;单击“删除”链接,打开删除留
言的页面。单击首页中显示的留言主题,可以打开显示相应留言主要内容的页面。

图 11.6 留言簿首页列表信息

留言簿页面如图 11.7 所示。

图 11.7 留言信息

·257·
·258· XML 实用教程

下面,逐步实现留言簿的各个组成部分。
在实现的留言簿中,客户的所有留言保存在一个 XML 文档(messagebase.xml)中。
【例 11.9】 列表显示 XML 文档信息,代码如源程序 index.asp 所示。
<html><head><title>ASP 访问 xml 文件</title>
<meta http-equiv=Content-Type content="text/html; charset=gb2312">
<table width=680 align=center>
<tbody>
<tr>
<td align=middle><br>
<h2><font color=#0f3ccd>使用 ASP 访问 xml 文件 </font></H2>
<hr width=660 color=#f46240 size=1>
</td></tr></tbody></table>
<!--使用 VBScript 语言编写脚本-->
<%@ Language=VBScript %>
<%
'创建用于访问 XML 文档的 DOM 对象 xmldoc
set xmldoc=Server.createObject("Microsoft.XMLDOM")
'使用 load 方法将访问的 XML 文档装入 xmldoc 对象中
xmldoc.load(Server.MapPath("messagebase.xml"))
'使用 selectNodes 方法获得所有'留言'元素的集合 nodes
set nodes=xmldoc.selectNodes("//留言")
'通过判断 nodes 集合中元素的个数(nodes.length)来决定输出
'输出结果使用 response.write 方法返回到客户浏览器中
'输出没有留言的信息
if nodes.length=0 then
Response.write("<center><h1>")
Response.write("***没有留言***")
Response.write("</h1></center>")
Response.end
end if
'在有留言时,输出留言的主题、留言人姓名、E-mail、日期等信息
'以表格的形式输出结果
Response.write("<table border=0 align=center cellpadding=5>")
Response.write("<thead>")
Response.write("<th>主题</th><th>留言人</th><th>E-mail</th><th>日期
</th>")
Response.write("</thead>")
for i=0 to nodes.length-1
Response.write("<tr>")
'取得"主题"
str1=nodes(i).childNodes(0).text
'取得"姓名"
str2=nodes(i).childNodes(1).text
'取得"E-mail"
str3=nodes(i).childNodes(2).text
'取得"日期"
str4=nodes(i).childNodes(4).text
'设置单击主题时执行 getcontent.asp 来获得留言内容
'将留言日期作为查询参数 datatag

·258·
第 11 章 XML 与 ASP ·259·

url="getcontent.asp?datatag="+str4
'输出主题,并将其设置为超文本链接
Response.write("<td>")
Response.write("<a href="+url+" target='_parent'>")
Response.write(str1)
Response.write("</a>")
Response.write("</td>")
'输出留言人姓名
Response.write("<td>"+str2+"</td>")
'输出留言人 email
Response.write("<td>"+str3+"</td>")
'输出留言日期
Response.write("<td>"+str4+"</td>")
next
%>

<br>
<table width=680 align=center>
<tbody>
<tr>
<td colspan="3">
<!--使用 VBScript 语言编写脚本-->
<hr width=660 color=#f46240 size=1>
</td></tr>
<tr>
<td>
<p align="right"><a href="leavedata.htm">留言</a>
</td>
<td>
</td>
<td>
<a href="deletedata.asp">
删除</a>
</td></tr></tbody></table>
</html>

其中,messagebase.xml 内容在例 11.10 中,它是已经有留言的 XML 文档。“日期”


子元素的内容是保存留言时的日期和时间,它具有惟一性,因此它的一个重要作用是用于
标识各个不同的留言。在查询留言时,使用“日期”子元素的内容作为关键字。
【例 11.10】 XML 文档信息清单。
<?xml version="1.0" encoding="gb2312"?>
<留言广场>
<留言>
<主题>什么是 XML 文档的架构? </主题>
<姓名>小鱼儿</姓名>
<email>fish@263.net</email>
<内容>架构是 XML 文档规则的正式规格,即元素名称。架构表示文档中允许哪些元素以
及允许哪些组合。许多架构是可以扩展的,所以开发人员可用附加的信息来扩展它们,这使得这
些新的架构语言在功能上比 DTD 强大得多。
</内容>

·259·
·260· XML 实用教程

<日期>2005-10-10//2:42:56</日期>
</留言>
<留言>
<主题>XML 可以标注哪些对像? </主题>
<姓名>小鱼儿</姓名>
<email>fish@263.net</email>
<内容>可以标注普通文档、诸如约会记录或采购定单之类的结构记录、具有数据和方法
的对象、数据记录、有关 Web 站点的元内容、图形表示、标准架构实体和类型、Web 上的信息
与用户之间的所有链接等对像。
</内容>
<日期>2004-1-10//2:44:43</日期>
</留言>
<留言>
<主题>XML 和 C、C++语言有何异同?</主题>
<姓名>秦红</姓名>
<email>hong@mail.net</email>
<内容>C 语言、C++以及类似的如 FORTRAN、Pascal、BASIC、Java 等称为程序语言。
XML 则是用来描述文本和数据等信息的标注语言。XML 可用于存储、传输,也可以用于编程以处
理事件。对 XML 而言,没有具体数据对像处理它就毫用处,但有时具体的数据对像是以隐蔽形式
出现的,但这不能说明 XML 可以不针对具体数据对像使用。这样你就可以明白,XML、HTML、
SGML 用于程序其实不起实质性的作用,它们是一种标志,一种标明了数据类型的标志,当程序
用到这些数据类型时,XML 的作用就体现了出来。
</内容>
<日期>2001-11-10//12:48:22</日期>
</留言>
</留言广场>

留言簿页面由文件 leavedata.htm 实现,如例 11.11 所示,它显示了首页标题和链接,


并显示留言的主题、留言人姓名、留言人 E-mail、留言日期等信息。客户输入了完整的留
言信息之后,单击“保存留言”按钮,调用页面中的 sendinfo 脚本函数来发送信息。因为
在 sendinfo 脚本函数中,首先检验客户是否输入了留言内容,如果没有,则显示相应的提
示信息;如果客户输入了完整的信息,则以 XML 格式将消息发送给服务器。
发送消息时使用了 XML HTTP 对象,使用该对象的 send 方法将信息以 XML 格式传送
给服务器,同时可以使用 responseXML 或 responseText 属性接收服务器的返回信息。
【例 11.11】 实现留言簿页面,如图 11.8 所示,代码如源程序 leavedata.htm 所示。
<html>
<head>
<meta contentType="text/html;charset=gb2312">
<title>留言广场</title>
</head>
<body>
<center>
<h3>欢迎光 XML 技术留言广场,感谢你留下建议或问题</h3>
<hr color="#ff0000">
<table width="686" border="0" cellpadding="0">
<tr>
<td align="right" width="126">姓名<b>:</b></td>
<td align="left" width="152">

·260·
第 11 章 XML 与 ASP ·261·

<input type="text" name="cname" size="20" >


</td>
<td align="right" width="193">E-mail 地址: </td>
<td align="left" width="228">
<input type="text" name="email" size="29" >
</td>
</tr>
<tr>
<td align="right" width="126">主题<b>:</b></td><td colspan="3"
width="581">
<input type="text" name="topic" size="79" >
</td>
</tr>
<tr>
<td align="right" width="126">留言:</td><td colspan="3"
width="581">
<textarea name="content" rows="10" cols="77"></textarea>
</td>
</tr>
<tr>
<td colspan="4" align="center" width="711">
</td>
</tr>
<tr>
<td colspan="4" align="center" width="711">
</td>
</tr>
</table>
<!--按钮用于调用发送信息的程序-->
<button onclick=sendinfo()>保存留言</button>
</center>
<!--创建用于将留言信息发送到服务器的脚本-->
<!--编写脚本使用的是 JavaScript 语言-->
<script language="JavaScript">
function sendinfo()
{
//首先判断客户是否输入留言内容,避免保存空白的留言信息
//在获得留言信息之后,将信息以 XML 文档格式封装
//将客户输入的留言以 XML 格式发送给服务器
if (cname.value=="")
{ alert("请输入姓名");return;}
else{ var namestr="<姓名>"+cname.value+"</姓名>" }
if (email.value=="")
{ alert("请输入电子邮件地址");return;}
else{ var emailstr="<email>"+email.value+"</email>" }
if (topic.value=="")
{ alert("请输入主题");return; }
else{var topicstr="<主题>"+topic.value+"</主题>"}
if (content.value=="")

·261·
·262· XML 实用教程

{ alert("请输入留言内容");return; }
else{var contentstr="<内容>"+content.value+"</内容>"}
var sendstr=topicstr+namestr+emailstr+contentstr

//创建用于发送信息的 XMLHTTP 对象的实例


var xhttp=new ActiveXObject("Microsoft.XMLHTTP");
//创建 HTTP 链接
var url="save.asp?"
xhttp.open("POST",url,false);
//发送消息
xhttp.send("<留言>"+sendstr+"</留言>");
//判断消息发送是否发生错误,出错则输出错误信息
if (xhttp.status!=200)
{
document.write("发生错误:"+xhttp.statusText);
document.write("<br>出错原因:"+xhttp.responseText);
}
//接收服务器返回的信息
var root=xhttp.responseXML;
//从接收的返回信息中提取消息
//返回的消息被封装在 DOM 对象中,所以使用 DOM 对象的方法来提取消息
var str=root.selectSingleNode("//response").text;
//利用警告框显示成功保存留言后的确认信息
alert(str);
}
</script>
<br><br><hr color="#ff0000">
<center><a href="index.asp" title="返回首页">返回</a></center>
</body>
</html>

图 11.8 留言簿页面

·262·
第 11 章 XML 与 ASP ·263·

保存留言使用 save.asp 来完成,服务器将从客户端接收到的消息保存在 Request 对象


中,因为客户端发送的消息是以 XML 文档格式发送的,所以可以使用 DOM 对象的方法从
Request 对象中获得留言信息。客户的留言信息保存在 Request 对象的“留言”元素中。在
save.asp 中,还需要为接收到的“留言”元素加入“日期”子元素,然后将“留言”元素添
加到保存留言簿信息的 messagebase.xml 文档中。使用 DOM 对象的 appendChild 方法添加
结点,而 save.asp 实现了为 XML 文档添加元素,如例 11.12。
【例 11.12】 保存留言的 ASP 程序,代码如源程序 save.asp 所示。
<%@ Language=VBScript %>
<%
'设置返回信息的格式,text/xml 表示以 XML 格式返回信息
'因为在客户端的 sendinfo 函数中使用了 responseXML 接收返回信息
'所以以 XML 格式发送返回信息
Response.contentType="text/xml"
'创建用于访问 XML 文档的 DOM 对象 xmldoc
set xmldoc=Server.createObject("Microsoft.XMLDOM")
'创建用于访问 request 对象的 DOM 对象 xmlrequest
set xmlrequest=Server.createObject("Microsoft.XMLDOM")
'使用 load 方法将访问的 XML 文档装入 xmldoc 对象中
xmldoc.load(Server.MapPath("messagebase.xml"))
'使用 load 方法将 request 对象装入 xmlrequest 对象中
xmlrequest.load(Request)
'创建一个新元素"日期"
set subnode=xmlrequest.createElement("日期")
'为新建的"日期"元素设置内容
'去掉日期和时间函数返回值的首尾空格
'去掉空格是为了使用"日期"元素作为关键字来标识不同的留言
subnode.text=Trim(date)+"//"+Trim(time)
'选择 Request 对象中的"留言"元素
set node=xmlrequest.selectSingleNode("//留言")
'将新建的"日期"元素设置为从 Request 对象中获得的"留言"元素的子元素
node.appendChild(subnode)
'将保存新的留言信息的"留言"元素添加到 messagebase.xml 根元素中
xmldoc.documentElement.appendChild(node)
'保存 messagebase.xml
xmldoc.save(Server.MapPath("messagebase.xml"))
'发送返回信息
str="<?xml version='1.0' encoding='gb2312'?><response>已经成功保存留言
</response>"
Response.write(str)
%>

删除留言的页面和留言簿首页类似,只是在每一条留言信息后多了一个用于调用删除
留言程序的超文本链接,如图 11.9 所示。

·263·
·264· XML 实用教程

图 11.9 删除留言页面

图中所示的页面是由程序 deletedata.asp 动态产生的,在创建图中的“删除”链接时,


使用的方法与 getdata.asp 中将“主题”创建为超文本链接的方法相同。
【例 11.13】 删除留言页面的 ASP,代码如源程序 deletedata.asp 所示。
<!--使用 VBScript 语言编写脚本-->
<%@ Language=VBScript %>
<%
'创建用于访问 XML 文档的 DOM 对象 xmldoc
set xmldoc=Server.createObject("Microsoft.XMLDOM")
'使用 load 方法将访问的 XML 文档装入 xmldoc 对象中
xmldoc.load(Server.MapPath("messagebase.xml"))
'使用 selectNodes 方法获得所有"留言"元素的集合 nodes
set nodes=xmldoc.selectNodes("//留言")
'通过判断 nodes 集合中元素的个数(nodes.length)来决定输出
'输出结果使用 response.write 方法返回到客户浏览器中
'输出没有留言的信息
'nodes.length 为留言条数
noteNum=nodes.length
if nodes.length=0 then
Response.write("<center><h1>")
Response.write("***没有留言***")
Response.write("</h1></center>")
Response.end
end if
'输出页面标题和转移到其他页面的链接
Response.write("<center>")
Response.write("<a href='messageboard.htm'>返回首页</a>")
Response.write("&nbsp;&nbsp;<---->&nbsp;&nbsp;")
Response.write("<a href='leavedata.htm'>我要留言</a>")
Response.write("</center><hr><br><br>")
'在有留言时,输出留言的主题、留言人姓名、E-mail、日期等信息
'以表格的形式输出结果

·264·
第 11 章 XML 与 ASP ·265·

Response.write("<table border=0 align=center cellpadding=5>")


Response.write("<thead>")
Response.write("<th>主题</th><th>留言人</th><th>E_mail</th>")
Response.write("<th>日期</th><th>&nbsp;</th>")
Response.write("</thead>")
for i=0 to noteNum-1
Response.write("<tr>")
'依次获得主题、留言人姓名、E-mail、日期等信息
str1=nodes(i).childNodes(0).text
str2=nodes(i).childNodes(1).text
str3=nodes(i).childNodes(2).text
str4=nodes(i).childNodes(4).text
Response.write("<td>"+str1+"</td>")
Response.write("<td>"+str2+"</td>")
Response.write("<td>"+str3+"</td>")
Response.write("<td>"+str4+"</td>")
'url 设置为"删除"链接的 URL,用于调用 suredelete.asp 来删除留言
'将调用 suredelete.asp 的查询参数设置为 datatag,其值为"日期"元素值
url="suredelete.asp?datatag="+str4
Response.write("<td><a href="+url+" target='_self'>删除</a></td>")
next
%>

11.5 小 结

XML 是一种新型的标记语言,为数据共享提供了通用标准格式;ASP 是当今开发服务


器端动态网页的主流技术。XML 与 ASP 技术的结合,必将促进新一代 Web 站点开发和电
子商务应用系统更加成熟和完善。本章首先详细介绍 ASP 的基础知识,讲解 ADO 数据绑
定和数据处理等高级应用编程,通过实例方式介绍 ASP 使用 XML 技术和使用规范。最后,
通过案例的详细分析,引导读者将 XML 与 ASP 技术运用于实际应用中。
在本章创建的留言簿并不完善,例如可在没有验证身份的情况下删除留言。如果将该
留言簿升级为一个讨论区,则可以增加一个 XML 文档来保存注册用户的信息,从而实现
身份验证。不过,从该例也可以看出使用 XML 文档保存数据的优越性。事实上,越来越
多的应用中将使用 XML 作为数据库来提高工程效率。至此,大家对 ASP、ADO 和 XML
的结合使用已经有了大致的了解。有了这个基础,就可以设计出功能更强大的应用程序。

11.6 习 题

1. 什么是 ASP?ASP 的常用对象有哪些?


2. 什么是 ADO?ADO 的主要对象有哪些,用途是什么?
3. 试述 Recordset 对象的常用方法和意义。
4. 使用 Access 数据库建立全班同学通讯录数据表,模仿实例程序,编制连接数据库的

·265·
·266· XML 实用教程

ASP 程序,并列表显示全班同学的信息。
5. 编写 ASP 程序把 Access 中的同学通讯录信息生成 XML 文件。
6. 论述为什么要采用 XML 存放数据,其有何优点。
7. 模仿实例程序,编写存放全班同学信息的 XML 文件,并制作全班同学通讯录程序,
编写代码使之能够列表查阅全班同学通讯录、添加同学信息和删除同学信息。

·266·
第 12 章 ebXML 简介

教学提示:ebXML 是一个基于 XML 的规范集,这些规范共同实现了模块化的电子商


务框架。ebXML 的构想是实现一个全球电子市场,不同规模和不同地区的企业都可以通过
交换基于 XML 的消息来进行商业活动。本章简单介绍 ebXML 的概念、设计目标、任务、
技术体系结构、应用过程以及对 ebXML 的展望。
教学目标:理解 ebXML 的概念、任务,掌握 ebXML 的技术体系结构。

12.1 ebXML

12.1.1 ebXML 的设计目标

从 1980 年至今电子数据交换 EDI 为商务办公描绘了一个美丽的前景:通过电子表格


的形式交换商务文档,实现无纸办公、降低成本和提高效率。理想的情况下公司无论大小
都可以通过一种特殊的形式实现电子商务,而不需要任何事先约定。但 EDI 并没有使这
成为现实。因为它费用昂贵,只有那些大公司才能用得起,在世界前 1000 强的企业当中,
有 98%运用了 EDI,而在前 1000 强之外的公司中,使用 EDI 的比例却只有 5%。而且大部
分的 EDI 电子商务模式都是支配权集中在一个大企业,其贸易伙伴为了得到业务不得不
采用这种贸易方式。
近一段时间以来,人们一直在寻找 EDI 的替代方案,希望能够找到一种使全球不同规
模的公司都能受益的简单、便宜的交换标准商务文档的方法。在这样的背景下 ebXML
(electronic business using eXtensible Markup Language)应运而生了。
最近几年中,XML 得到了快速的发展,已经成为 Internet 上电子商务应用程序之间定
义数据交换格式的首选方案。因此许多人认为 XML 的崛起已经证明 EDI 完全过时了。但
实际上这种观点无论是从技术角度还是商业角度都过于天真。EDI 实际上是对商务处理中
的实际经验进行封装,而那些对 EDI 集成投入了大量资金的公司如果看不到真正的好处是
决不会轻易放弃 EDI 的。比起 EDI 而言 XML 可能更开放、更具有松散耦合性、更面向对
象或组件,它的“电子市场”概念可能更灵活、更有新意。但设计满足商务处理需求的消
息及语义标准化和这些消息采用什么语法完全是两回事。
因此 ebXML 规范提出一种技术框架,既可以利用 XML 技术上的新特性,又能保留
EDI 在商务处理中的原有投资。
·268· XML 实用教程

12.1.2 ebXML 的概念

ebXML 是由 UN/CEFACT(联合国简化贸易手续和电子商务中心)和 OASIS(促进结构化


信息标准组织)于 1999 年提出的。ebXML 被定义为:它是国际技术达成一致的专门集合,它
由普通的 XML 语义和相关文档结构组成,目的是使全球贸易便利。
ebXML 是一个基于 XML 的规范集,这些规范共同实现了模块化的电子商务框架,其
中 eb 代表电子商务。它的支持者包括大量工业、航运、银行业以及其他综合业务的公司。
许多标准团体也参与其中,包括 NIST(国家标准和技术学会)和 W3C。
ebXML 的目的是为了便于不同规模的团体之间开展电子贸易,也可以说它通过允许商
家以不同的方式进行商业活动,尽可能将商家的商业行为越来越多地合并到规范中,从而
成功地成为通用协议。至少 ebXML 的发起人明确抱有一种“接纳现有标准和方法”的态度。

12.1.3 ebXML 的任务

由于 XML 本身不具备使其适应商务世界需求的所有工具,所以希望通过 ebXML 实现:


(1) 使电子商务简单、容易,并且无所不在;
(2) 最大限度地使用 XML;
(3) 为 B2B 和 B2C 提供一个同样的开放标准以进行跨行业的商务交易;
(4) 将各种 XML 商务词汇的结构和内容一起放进一个单一的规范中;
(5) 提供一条从当前 EDI 标准和 XML 词汇表移植的途径;
(6) 鼓励行业在一个共同的长期目标下致力于直接的或短期的目标;
(7) 用 ebXML 进行电子商务活动,避免要求最终用户投资于专有软件或强制使用专有
系统;
(8) 保持最低成本;
(9) 支持多种书面语言并容纳国内、国际贸易的通用规则。

12.2 ebXML 的技术体系结构

ebXML 的技术体系结构尽可能使用了现存的标准,建立在 EDI 经验之上,并利用了


XML 的灵活性和 Internet 的普及性,整个体系结构是模块式的。

12.2.1 消息传送

ebXML 消息服务机制提供了一种标准的方法,能够在 ebXML 贸易伙伴之间交换商务


消息,而不需要依靠特定的技术和解决方案。一个 ebXML 消息包括一个消息头(用于路由
与发送)和一个负载部分(传输的内容)。ebXML 消息服务从概念上分为 3 部分:
(1) 抽象的服务接口;
(2) 消息服务层;
(3) 到底层传输服务的映射。
ebXML 消息收发服务规范的设计目标在于定义支持小、中和大型企业之间基于 XML

·268·
第 12 章 ebXML 简介 ·269·

的电子商务的消息收发服务。该规范旨在实现低成本解决方案,同时使厂商能够通过增强
可靠性和性能提高运营质量。
1. ebXML 消息收发服务规范的主要功能
ebXML 消息收发规范规定:通过数据通信装置传输 ebXML 消息使用的 ebXML 消息
报头和组装要求。它主要定义使用现有的通信协议,在两种 ebXML 消息服务之间传送消
息所需要的基本功能。它将规定 ebXML 以能够实现的可靠性、持久性、安全性和扩展性
的方式,执行消息收发服务。因此,规范将为开发组装、交换和处理 ebXML 消息的软件
提供细则。
2. ebXML 消息收发服务规范的组成要素
ebXML 消息收发服务规范由以下 5 个部分组成:
(1) 消息组装。提供组装一条 ebXML 消息和相关部件的方法,其中包括各种结构和容
器规范。消息组装规范是由 XML 消息报头和消息内容这两部分组成的多方相关标准结构。
消息内容可能是任意一种类型的数据。基于 XML 的消息报头要素及其结构可以根据目前
的专用和通用传送协议进行筛选,以保证报头元素的适用性。
(2) 消息报头。信息结构与合成的一种规范,是 ebXML 消息收发服务成功地产生和处
理 ebXML 的消息所必需的。
(3) 可靠的消息收发。这一功能定义可操作的协议,使任意两种消息实施办法能够交
换通过“可靠的消息收发”语义发送的消息。
(4) 差错控制。这一功能为检测 ebXML 收发服务提供一种报告差错的方法。
(5) 安全性。这一功能在消息内容规范中能够支持有限的安全业务,可以采用适合消
息内容形式的密码技术,给多方相关的消息内容加密。
3. ebXML 消息结构
一条 ebXML 消息由两部分组成,即外部通信协议封装和内部通信协议封装。前者封
装诸如 HTTP 或 SMTP 等协议;后者包括消息的两个主要组成部分,即封装一个 ebXML
报头文件使用的 ebXML 报头内容和封装消息的实际内容(传送的数据)必须使用的单个
ebXML 消息内容容器。
一条 ebXML 消息内容包含 3 种属性:类型属性,使用 MIME 类型属性将按照 ebXML
依从结构识别 ebXML 消息封装,确认 XML 媒体类型;边界属性,用于识别消息中所包含
的每个实体部分起点和终点的分隔符;版本属性,用于识别所使用的 ebXML 消息封装的
特殊版本。

12.2.2 商务处理流程和信息建模

元模型提供了一种机制,它有助于贸易伙伴在指定的商务情节下通过统一的建模理论
来抓住细节。商务处理流程描述了贸易伙伴如何担当角色、表述关系和承担责任,以及如
何与同一个商务处理流程中的其他贸易伙伴进行联系和交互。不同角色之间的交互可以看
成是一连串设计好的商务交易。每次商务交易都可以表示为电子商务文档的一次交换。交
换顺序由商务处理流程、消息传输和安全因素所决定。商务文档则由可重用的商务信息组

·269·
·270· XML 实用教程

件组成。从更低的层次上看,商务处理流程可以理解为可重用的核心处理过程,而商务信
息对象可以理解为可重用的核心组件。
商务处理流程和信息元模型从需求、 分析和设计 3 个角度出发,
分别提供了一组语义(词
汇表),从而形成了推动商务处理流程和信息集成与互操作发展的基本规范。
从元模型的另外一个方面,规范模式也被用来直接实现规范,它可以使用一组元素来
规划进行 ebXML 商务交易的实时系统。通过从其他几个视图中提取建模元素,规范模式
形成商务处理流程和信息元模型的一个语义子集。它可以采用两种独立的表示方法:UML
描述和 DTD。
规范模式支持商务交易的规范以及从商务交易到商务合作的转换。每个商务交易都可
以用众多可用的标准模式来实现。这些模式决定了贸易伙伴之间实际进行的消息和信号交
换。为了有助于阐述这些模式,规范模式总是伴随着一组标准模式及其相关的一组通用建
模元素。因此一个商务处理流程的全部规范包括一个规范模式指定的商务处理流程和信息
元模型及一个所需模式的标志。这些信息成为形成合作协议描述(CPP)和合作方案协议
(CPA)的主要来源。
当构造一个新的商务处理流程时,并不一定要使用建模语言,但如果要用到某种建模
语言,那么应该是统一建模语言 UML。这种强制目的保证在创建商务处理流程时能采用统
一的建模方法。使用统一的建模方法的好处之一是可以比较模型,以避免现有商务处理流
程的重复。
为了保证创建统一的商务处理流程和信息模型,ebXML 将定义一组与核心库对应的通
用核心商务处理流程。ebXML 用户可以扩展这组核心商务处理流程或使用自己的流程。
阐述商务处理流程文档时应当采用一种人和应用程序都能读懂的形式。必须要经过一
个渐进的过渡才能达到商务交互的完全自动处理。
商务处理流程应该通过 Registry 机制发现和获取。为了方便发现和获取,商务处理流
程可以在 Registry 中注册登记。
为了能够被应用程序“理解”,商务处理流程应该用 XML 表示。商务处理流程应该
构造成一个商务处理流程和信息元模型或基于 XML 的表示方式。它能够表达以下类型的
信息:
(1) 交换文档实例的流程设计;
(2) 对商务处理流程和信息元模型或商务文档的引用(可能是 DTD 或 Schema ),对商
务数据引入结构;
(3) 为商务处理流程中每个参与者定义的角色。
一个商务处理流程应提供核心组件使用时的上下文约束,提供建立 CPA 时的框架,
指明商务处理流程的所有者和有关联系信息。

12.2.3 贸易伙伴草案和协定

为了更方便地引导电子商务的运作,潜在的贸易伙伴需要一种机制对外发布他们所支
持的商务处理流程以及交换商务信息的技术实现细节,这可以通过 CPP 实现。CPP 是一个
文档,贸易伙伴可以用来表达所能够支持的商务处理流程和商务服务接口,这种方式也能
够被其他 ebXML 兼容的贸易伙伴所理解。

·270·
第 12 章 ebXML 简介 ·271·

CPP 描述了贸易伙伴具体的技术能力以及为交换商业文档所提供的服务接口。CPP 中
包含贸易伙伴的基本信息,它可以包含但不限于:合同信息、行业分类、支持的商务处理
流程、接口需求和消息服务需求,还可以包括安全性和其他具体的实现细节。每个贸易伙
伴都应该在一个 ebXML 兼容的 Registry 系统中注册它们的 CPP,这样就可提供一种发现
机制用于贸易伙伴之间互相查找,发现其他贸易伙伴支持的商务处理流程。CPP 定义中对
于存在多种实现可能(如 HTTP 或 SMTP)时,应该明确指定使用哪一种选择。
CPA 是描述两个或多个 CPP 交集的文档,希望通过 ebXML 进行电子商务的贸易伙伴
各方对此都表示同意。CPA 描述了消息服务,双方或多方同意的商务处理流程需求。从概
念上讲,ebXML 支持一个嵌套模式的 3 层视图来达成 CPA,从外到内依次是一个贸易伙伴
所有可能做的、能够做的以及实际将要做的,内层是外层的子集。
一个 CPA 包括消息服务接口需求和贸易伙伴双方都同意用于引导电子商务的商务处
理流程的实现细节。贸易伙伴可以在 ebXML 兼容的 Registry 服务中注册他们的 CPA,但
这并不是 CPA 创建过程的必要部分。
商务合作是贸易伙伴首先要声明支持的,由一个单独的描述来表示对特定商务合作的
支持声明,它主要用于在一个目录服务中发布,例如一个 ebXML Registry 或其他可用服务。

12.2.4 注册表

ebXML Registry 提供了一组服务来实现用户之间的信息共享,维护注册项目与元数据


之间的接口,同时还提供存取 ebXML Registry 的 API 接口。Registry 应该允许存储多字节
字符集语法表示的注册项目。每个注册项目在不同层次上的粒度由提交机构定义,它必须
是唯一的标志。这是实现应用程序到 Registry 检索的基础。在一定上下文中检索 UID 或
GUID,Registry 应该返回 0 或一个正值。如果检索时返回两个或两个以上的正值,那么就
应该向 Registry 认证报告错误。一个注册项目应该是一个结构,它可以包含一系列相关的
信息进行标识和命名,描述注册项目、权限和存取状态,可以定义稳定性和不稳定性,根
据预先定义的分类方案进行分类,声明文件的表现类型、标识提交和负责机构。Registry
接口支持从应用程序到 Registry 的自动存取,人与 Registry 之间的交互应该通过一个
Registry 客户端(如浏览器)在接口上层实现,而不应该作为一个单独的接口使用。
Registry 支持的处理还可以包括:
(1) 一个在 Registry 与 Registry 客户端之间专用的 CPA;
(2) 一组 Registry 与 Registry 客户端用到的处理函数;
(3) 一组在 Registry 与 Registry 客户端之间的商务消息,作为一个特殊商务处理流程的
一部分;
(4) 一组基本的接口机制,以支持商务消息和有关的检索与响应机制;
(5) 一个专门的 CPA,用于在兼容 ebXML 的 Registry 之间进行交互;
(6) 一组 Registry 与 Registry 之间交互的处理函数;
(7) 一组错误响应和恢复处理条件。
为了有助于 Registry 中项目的查找、浏览和传播,Registry 应该提供人机交互的检索方
式(如浏览器)。用户应该能够根据可用的 Registry 分类方案浏览和研究其内容。Registry 消
息应该能够用于创建、修改和删除注册项目及其元数据。当 Registry 存取 Repository 时,

·271·
·272· XML 实用教程

可以采用适当的安全协议对 Repository 进行认证和保护。ebXML Registry 中所有项目都应


该由统一标识符(UIDs)标识。通过 UID 可以引用所有 ebXML 内容。使用全球统一标识符
(UUIDs)确保 Registry 中的注册项目在全球范围内唯一,这样当系统通过 UUID 检索 Registry
时,可以保证有且只有一个返回结果。
为了更好地识别商务处理流程和信息元模型的语义,注册系统应该提供一种便于人类
阅读的表示机制。现有的商务处理流程和信息元模型(如 RosettaNet PIPs)在注册到 ebXML
兼容的 Registry 系统时,赋予它一个 UID。这些 UID 可以通过 XML 语法以各种方式来实
现。ebXML 中包含的组件必须实现多语言支持。为了支持多语言,ebXML 规范应该兼容
Unicode 和 ISO/IEC 10646 字符集,兼容 UTF-8 或 UTF-16 字符编码。

12.2.5 核心组件

ebXML 核心组件提供行业间的互操作性和商务性能,核心组件作用于单个的数据元素
级别。核心组件识别商家最常使用和跨行业的数据项,给它们分配中立的名字和唯一的标
识符。通过核心组件,企业能够将一个行业的数据同另一个行业中相似的数据对应起来,
或从一个 XML 术语对应到早先定义的 EDI 交易。
核心组件用于捕捉现实世界中商务概念里的信息以及这些概念与上下文之间的联系。
所谓的上下文描述了一个核心组件或集成组件在特定的 ebXML 电子商务场景中应如何使
用。一个核心组件可以是一个独立的商务信息块,也可以由一组能够封装在一起的商务信
息块组成,即集成组件。ebXML 核心组件工程小组应该定义一组基本的核心组件,这样
ebXML 用户可以使用这个核心库或者对其进行扩展。

12.3 ebXML 的应用过程

12.3.1 实现阶段

实现阶段主要是构造基于 ebXML 应用程序的过程。一个希望进行 ebXML 兼容商业交


易的贸易伙伴必须先取得一份 ebXML 规范的副本。研究规范后将要求下载核心库和商务
对象库,也可以取得其他贸易伙伴商务处理流程的信息(存在商务描述中)进行分析和评价。
使用第三方开发的应用程序也是一种选择。贸易伙伴可以向一个 ebXML 兼容的 Registry
提交自己的商务处理流程信息。

12.3.2 发现和获取阶段

发现和获取阶段覆盖了发现 ebXML 相关资源的各个方面。现在一个已经实现 ebXML


商业服务接口的贸易伙伴能够开始进入发现和获取阶段。一种可行的发现方法是取得另一个
贸易伙伴的贸易伙伴描述。ebXML 应用程序应该支持更新核心库、商务对象库和更新/创建
商务处理流程及信息元模型的请求。在这个阶段贸易伙伴的任务是发掘商务信息中的含义。

·272·
第 12 章 ebXML 简介 ·273·

12.3.3 实时运行阶段

实时运行阶段根据实际的 ebXML 交易执行一个 ebXML 场景。在该阶段通过 ebXML


消息服务在贸易伙伴之间交换 ebXML 消息。例如,一个 ebXML CPA 就是一组设计好的商
务消息交换,它们通过 ebXML 消息服务连接起来。

12.4 ebXML 展望

12.4.1 电子商务全球化解决方案

全球化解决方案是当今更加扩大的市场运营的关键技术。ebXML 的基本目的是促进国
际贸易。为了实现有利于国际贸易的“单一的全球市场”,关键的问题是简化现有的交换标
准技术,并与不同交易方式相协调。这种简化和协调性可通过与核心部件相结合的方式开
发商务元结点得以实现,从而适应不同国家和多国商务过程的需求,并支持向前和向后兼
容 ebXML 的技术框架。而且所有的 ebXML 技术规范应能由某种语言(如英语)转换成其他
的自然语言。

12.4.2 可用性和互通性

ebXML 技术规范的可用性和互通性是商务全球化最基本的要求。可用性和互通性的组
成要素包括结构、传输、路由和组装、可扩展性以及适当利用现有技术,而 ebXML 结构
是其中最主要的要素。
ebXML 结构将支持整个商务过程,包括参与数据交换的双方必须在商务过程上下文连
接方面执行相同的事务处理;共同的语义,即单词表述或表示形式不同而意义相同;共同
的词汇,即单词和意义之间直接通信;共同的字符编码;共同的表述,即 XML 元素名称、
属性和这些元素的利用、文件构成的方法都相同;共同的保密措施;共同的数据传送协议
以及共同的网络层。

12.4.3 从现有的 EDI 和 XML 方案迁移

商业企业看中的是其应用和贸易伙伴应用之间的最大的互通性。这种互通性凭借从事
商务的单一的电子方式,即将 ebXML 用于电子商务的单一的标准得以实现,但是许多商
业企业在基于现有标准的 EDI 和新的 XML 商务方面有相当多的投入。这些企业需要一种
容纳基于现有标准的传统 EDI 解决方案和 XML 解决方案的机制迁移途径。ebXML 不仅提
供从现有的 EDI 和 XML 解决方案迁移的途径,而且能够保证在开发 ebXML 技术规范方
面优先实现最大程度的互通性。

12.4.4 安全性保证

安全性主要体现在会话层,即网络交换数据的会话期间要求保证安全性,或对独立应
用的文件实例应用安全性规范。而且,安全性规范应用于特殊的数据交换或文件实例时,

·273·
·274· XML 实用教程

还必须根据商务需求而确定,并能默认不受限制和非密的数据交换。在特殊的商务信息交
换中,可能要求多种类型的安全功能。

12.5 小 结

ebXML 是国际技术达成一致的专门集合,它由普通的 XML 语义和相关文档结构组成,


目的是使全球贸易便利。ebXML 的目的是便于不同规模的团体之间开展电子贸易,也可以
说它通过允许商家以不同的方式进行商业活动,尽可能将商家的商业行为越来越多地合并
到规范中,从而成功地成为通用协议。
ebXML 技术体系结构由消息传送、商务处理流程和信息建模、贸易伙伴草案和协定注
册表及核心组件构成。

12.6 习 题

1. 什么是 ebXML?
2. ebXML 的任务是什么?
3. 简述 ebXML 的技术体系结构。
4. 简述 ebXML 的应用过程。

·274·
第 13 章 XML 与.NET 构建小型 Web 应用

教学提示:XML 是数据访问领域的最新技术,Microsoft 公司从诞生 XML 概念起就积


极地提供对它的支持。Visual Studio.NET 是一套完整的开发工具,它完全支持 XML,提供
了 XML 设计器以使编辑 XML 和创建 XML 架构更容易。.NET Framework 的 system.xml
名称空间提供了大量的类支持 XML 操作。
教学目标:理解 Microsoft .NET Framework 的基本概念,介绍 Visual Studio.NET 集成开
发环境,理解.NET 处理 XML 文档的方式,了解 XmlTextReader 类读取及 XmlTextWriter
类书写 XML 文档,了解如何使用数据集存储和处理 XML 文档,最后使用.NET 框架建立
一个网上书店。

13.1 .NET Framework 介绍

.NET Framework 是一种新的计算平台,为其能在高度分布式的互联网环境中使用,它


简化了 Internet 环境中的应用程序开发。由于要加强分布式.NET 应用程序之间的通信,所
以.NET 结构很大程度地使用了 XML。事实上,XML 是.NET Framework 的默认编码语言,
它不仅用于封装数据使之能够在应用程序之间传送,还用在配置文件中。在.NET 体系结构
中,XML 是各应用之间无缝接合的关键。只有明白了.NET Framework 究竟是什么,才能
明白选择使用 XML 的合理性。
.NET Framework 给计算机带来了可靠性、易用性和互通性,帮助软件开发人员、系统
管理人员更轻松地开发、管理,提升了性能,加强了安全,提高了稳定性。主要有以下优点:
(1) 提供标准的面向对象的开发环境,不仅可以在本地与对象交互,还可以通过 Web
Service 和.NET Remoting 技术在远程与对象交互。
(2) 提供优化的代码执行环境,使以前让人们头痛的程序版本问题得到了解决。可以
在同一台计算机中安装相同程序的不同版本。而且部署也得到了改善,能够像复制文件一
样简单。
(3) 提供代码运行安全性。以前担心网页中包含的 ActivX 控件会执行恶意的代码,现
在则无须担心,因为.NET Framework 保障了执行代码的安全性。
(4) 使用 JIT(Just In Time Activation)技术,提高代码运行速度。
(5) 提供标准的框架和强大的开发工具,可以让程序员在实际的开发当中,积累更多
的经验。
(6) .NET 遵循业界标准规范,因此.NET 里的代码可以与其他系统交互。
·276· XML 实用教程

13.1.1 .NET 构架

.NET Framework 具有两个主要组件:公共语言运行库和 .NET Framework 类库。公共


语言运行库是 .NET Framework 的基础。可以将运行库看成一个在执行时管理代码的代理,
类似于 Java 的虚拟机。它提供核心服务(如内存管理、线程管理和远程处理),而且还强制
实施严格的类型安全并可确保安全性和可靠性等其他形式的代码准确性。事实上,代码管
理的概念是运行库的基本原则。以运行库为目标的代码称为托管代码,而不以运行库为目
标的代码称为非托管代码。.NET Framework 的另一个主要组件是类库,它是一个综合性的
面向对象的可重用类型集合,可以使用它开发多种应用程序,这些应用程序包括传统的命
令行或图形用户界面(GUI)应用程序,也包括基于 ASP.NET 所提供的最新的应用程序(如
Web 窗体和 Web 服务)。采用组件封装的方式,使用起来就更简单了。.NET Framework 架
构如图 13.1 所示。

图 13.1 .NET Framework 架构

13.1.2 从 MSXML 到.NET 的 XML

在.NET Framework 出现之前,习惯使用 MSXML 服务——一个基于 COM 的类库,编


写 Windows 的 XML 的驱动程序。与.NET Framework 中的类不同,MSXML 类库的部分代
码比 API 更深,它完全地嵌在操作系统的底层。MSXML 的确能够与应用程序通信,但是
它不能真正地与外部环境结合。
MSXML 类库能在 Win32 中被导入,也能在 CLR 中运用,但它只能作为一个外部服务
器组件使用。基于.NET Framework 的应用程序能直接的用 XML 类与.NET Framework 的其
他名称空间整合使用,并且写出来的代码也易于阅读。
作为一个独立的组件,MSXML 分析器提供了一些高级的特性如异步分析。这个特性
在.NET Framework 中的 XML 类及.NET Framework 的其他类都没有提供,但是.NET
Framework 中的 XML 类与其他的类整合可以很轻易地获得相同的功能,在这个基础上可以
增加更多的功能。
.NET Framework 中的 XML 类提供了基本的分析、查询、转换 XML 数据的功能。在.NET
Framework 中,可以找到支持 XPath 查询和 XSLT 转换的类,及读/写 XML 文档的类。另

·276·
第 13 章 XML 与.NET 构建小型 Web 应用 ·277·

外,.NET Framework 也包含了其他处理 XML 的类,例如对象的序列化(XmlSerializer 和 the


SoapFormatter 类)、应用程序配置(AppSettingsReader 类)和数据存储(DataSet 类)。

13.1.3 XML 分析模式

既然 XML 是一种标记语言,就应该有一种工具按一定的语法来分析和理解存储在文
档中的信息。这个工具就是 XML 分析器。
所有的 XML 分析器,不管它属于哪个操作平台,不外乎是以下两类:基于树或者基
于事件的处理器。这两类通常都用 XMLDOM(the Microsoft XML Document Object Model)
和 SAX(Simple API for XML)来实现。XMLDOM 分析器是一个普通的基于树的 API,它把
XML 文档当成一个内存结构树呈现,SAX 分析器是基于事件的 API,它处理每个在 XML
数据流中的元素(它把 XML 数据放进流中再进行处理)。通常,DOM 能被一个 SAX 流载入
并执行,因此,这两类的处理不是相互排斥的。
总的来说,SAX 分析器与 XMLDOM 分析器正好相反,它们的分析模式存在着极大的
差别。XMLDOM 被很好地定义在它的 functionalition 集合里面,不能对其进行扩展。当处
理一个大型的文档时,它要占用很大的内存空间来处理 functionalition 这个巨大的集合。
SAX 分析器则利用客户端应用程序, 通过现存的指定平台的对象实例去处理分析事件。
SAX 分析器控制整个处理过程,把数据“推出”到处理程序,该处理程序依次接受或拒绝
处理数据。这种模式的优点是只需占用很小的内存空间。
.NET Framework 完全支持 XMLDOM 分析器,但不支持 SAX 分析器。因为.NET
Framework 支持两种不同的分析模式:XMLDOM 分析器和 XML 阅读器,它显然不支持
SAX 分析器,但这并不意味着它没有提供类似 SAX 分析器的功能。通过 XML 阅读器 SAX
的所有功能都能很容易的实现并更有效的运用。与 SAX 分析器不同,.NET Framework 的
整个阅读器都运作在客户端应用程序下面。这样,应用程序本身就可以只把真正需要的数
据“推出”,然后从 XML 数据流中跳出来,而 SAX 分析模式要处理所有对应用程序中
有用和没有用的信息。
阅读器是基于.NET Framework 流模式工作的,它的工作方式类似于数据库的游标。有
趣的是,实现类似游标分析模式的类提供对.NET Framework 中 XMLDOM 分析器的底层支
持。XmlReader、XmlWriter 两个抽象类是所有.NET Framework 中 XML 类的基础类,包括
XMLDOM 类、ADO.NET 驱动类及配置类。因此在.NET Framework 中有两种可选的方法
去处理 XML 数据:用 XmlReader 和 XmlWriter 类直接处理 XML 数据,或者用 XMLDOM
分析器处理。

13.2 Visual Studio .NET 集成开发环境

Visual Studio .NET 能够快速创建下一代 XML Web 服务和应用程序,这些服务和应用


程序面向任何 Internet 设备并在编程语言和操作系统之间集成。Visual Studio .NET 和 XML
Web 服务提供简单、灵活、基于标准的模型,允许开发人员用新的和现有的代码汇编应用
程序,而与平台、编程语言或对象模型无关。

·277·
·278· XML 实用教程

13.2.1 Visual Studio .NET 主界面

Visual Studio.NET 的 IDE 已经将几乎所有的功能都集中到同一个界面内。


为所有 Visual
Studio .NET 支持的语言提供了单一的代码编辑器,而同时为每一种语言提供了特定的功
能。其编辑器引入了编辑环境方面的一些增强功能,诸如单词补齐、增量搜索、代码凸显、
缩进文本、标记行号、彩色打印和快捷方式等。编辑器还提供了许多为特定语言设计的功
能,例如在输入原型和函数调用的时候能够自动完成这些字符串的输入。除了编程语言,
编辑器还提供对 HTML 文档甚至 XML 编写过程的支持,软件主界面如图 13.2 所示。

图 13.2 Visual Studio .NET IDE 开发环境

13.2.2 XML 编辑器

Visual Studio .NET 还内置了一个 XML 编辑器(如图 13.3 所示),提供一套可视化工具,


用于处理 XML 架构、ADO .NET 数据集和 XML 文档。XML 设计器支持由 W3C 定义的
XML 架构定义(XSD)语言。该设计器不支持 DTD(文档类型定义)或其他 XML 架构语言,
如 XDR(简化 XML 数据)。可以很容易地为文档生成一个相应的 XSD 模式。若要显示该设
计器,将数据集、XML 架构或 XML 文件添加到项目中或打开相应类型文件即可。
针对 XML 文件,提供两种视图模式。一个是数据视图,提供可以用来修改 XML 文件
的数据网格。在数据视图中只能编辑 XML 文件的内容(不能编辑标记和结构)。
在数据视图中有两个单独的区域:数据表和数据(如图 13.4 所示)。【数据表】区域是

·278·
第 13 章 XML 与.NET 构建小型 Web 应用 ·279·

在 XML 文件中定义的关系的列表,按嵌套顺序排序(从最外到最内)。【数据】区域是根
据【数据表】区域中的选定内容显示数据的数据网格。
另一个是 XML 视图(如图 13.3 所示),提供用于编辑原始 XML 的编辑器,并且提供
智能感知和颜色编码。当处理 XSD 文件和具有关联架构的 XML 文件时可以使用语句完成
功能。输入“<”以开始一个标记,将会提供在该位置有效的元素列表。输入元素名并按
Space 键后,将会看到该元素支持的属性列表。

图 13.3 XML 编辑器

在 Visual Studio .NET 中打开 XML 文档时,XML 中使用的关键词如 XML 声明和属性


被高亮显示。这个编辑器还提供了源代码和数据的视图(如图 13.4 所示)。在数据视图中,
文档的结构被显示在左边的窗口里。当在这个级联的结构中选择一个 XML 元素时,这个
窗口右边的部分就会显示其子元素并能够一直深入查看元素数据。
需要为 XML 文档创建模式,可以选择【XML】菜单中的【创建架构】命令,就会生
成相应的模式文件。如图 13.5 所示是 books.xml 生成的模式文档。生成模式文件后,如果
后面对 XML 文档进行改动时,也可以选择【XML】菜单中的【验证 XML 数据】命令来
验证数据的合法性。

·279·
·280· XML 实用教程

图 13.4 XML 文档的数据视图

图 13.5 Books.xml 生成的模式文档

13.3 用.NET 处理 XML 文档

整个 ADO .NET Framework 是在 XML 技术的基础之上进行设计的,许多 ADO .NET


数据处理方法都离不开 XML 技术的支持。.NET Framework 的 System .Xml 名称空间提供
了大量的类,用来存储和处理 XML 文档。这些类也可称为 XML .NET。主要支持两类功能:
怎样读写、解析和书写 XML 文档,怎样在内存中存储、构造和处理 XML 文档。

·280·
第 13 章 XML 与.NET 构建小型 Web 应用 ·281·

13.3.1 .NET 下与 XML 相关的类简介

在深入进行.NET 框架下 XML 文档的操作之前,有必要介绍.NET 框架中与 XML 技术


有关的名称空间和其中一些重要的类。.NET 框架提供了以下名称空间:System.Xml、
System.Xml.Schema、System.Xml.Serialization、System.Xml.Xpath 和 System.Xml.Xsl 来包
容和 XML 操作相关的类。
System.Xml 名称空间包含了一些最重要的 XML 类,其中最主要的类是与 XML 文档
的读写操作相关的类。这些类中包括 4 个与读相关的类以及两个与写相关的类。分别是
XmlReader 、 XmlTextReader 、 XmlValidatingReader 、 XmlNodeReader 、 XmlWriter 和
XmlTextWriter。下面将重点介绍这些类,因为它们是最基本也是最重要的类。
XmlReader 类是一个虚基类,它包含了读 XML 文档的方法和属性。该类中的 Read 方法是
一个基本的读 XML 文档的方法,它以流形式读取 XML 文档中的结点。另外,该类还提供了
ReadString、ReadInnerXml、ReadOuterXml 和 ReadStartElement 等更高级的读方法。除了提供读
XML 文档的方法外,XmlReader 类还为程序员提供了 MoveToAttribute、MoveToFirstAttribute、
MoveToContent、MoveToFirstContent、MoveToElement 和 MoveToNextAttribute 等具有导航功
能的方法。
XmlTextReader、XmlNodeReader 和 XmlValidatingReader 等类是从 XmlReader 类继承过
来的子类。根据它们的名称,可以知道其作用分别是读取文本内容、读取结点和读取 XML
模式。
XmlWriter 类为程序员提供了许多写 XML 文档的方法,它是 XmlTextWriter 类的基类。
XmlNode 类是一个非常重要的类,它代表了 XML 文档中的某个结点。该结点可以是
XML 文档的根结点,这样它就代表了整个 XML 文档。它是许多很有用的类的基类,这些
类包括插入结点的类、删除结点的类、替换结点的类以及在 XML 文档中完成导航功能的
类。同时,XmlNode 类还为程序员提供了获取双亲结点、子结点、最后一个子结点、结点
名称以及结点类型等的属性。它的 3 个最主要的子类包括 XmlDocument、XmlDataDocument
和 XmlDocumentFragment。XmlDocument 类代表了一个 XML 文档,它提供了载入和保存
XML 文档的方法和属性。这些方法包括了 Load、LoadXml 和 Save 等。同时,它还提供了
添加特性(Attributes)、说明(Comments)、空间(Spaces)、元素(Elements)和新结点(New Nodes)
等 XML 项的功能。XmlDocumentFragment 类代表了一部分 XML 文档,它能被用来添加到
其他的 XML 文档中。XmlDataDocument 类可以更好地完成与 ADO.NET 中的数据集对象
之间的交互操作。
除了上面介绍的 System.Xml 名称空间中的类外,该名称空间还包括了 XmlConvert、
XmlLinkedNode 和 XmlNodeList 等类,有兴趣的读者可以参考相关文档资料。
System.Xml.Schema 名称空间中包含了与 XML 模式相关的类,这些类包括 XmlSchema、
XmlSchemaAll、XmlSchemaXPath 与 XmlSchemaType 等类。
System.Xml.Serialization 名称空间中包含了和 XML 文档的序列化和反序列化操作相关
的类,XML 文档的序列化操作能将 XML 格式的数据转化为流格式的数据并能在网络中传
输,而反序列化则完成相反的操作,即将流格式的数据还原成 XML 格式的数据。

·281·
·282· XML 实用教程

System.Xml.XPath 名称空间包含了 XPathDocument、XPathExression、XPathNavigator


和 XPathNodeIterator 等类,这些类能完成 XML 文档的导航功能。在 XPathDocument 类的
协助下,XPathNavigator 类能完成快速的 XML 文档导航功能,该类为程序员提供了许多
Move 方法以完成导航功能。
System.Xml.Xsl 名称空间中的类能完成 XSLT 的转换功能。
System.Xml 名称空间中包含的重要的处理 XML 的类,如图 13.6 所示。

图 13.6 System.Xml 名称空间中包含的重要的处理 XML 的类

【例 13.1】 书籍的 XML 文档 books.xml。


<?cml version="1.0" encoding="gb2312"?>
<BookStore xmlns="http://tempuri.org/books.xsd">
<book ISBN="0-764-58007-8" CAT="S">
<title>三国演义</title>
<price>5.95</price>
<author>罗贯中</author>
<publisher>文艺出版社</publisher>
<quantity>3</quantity>
</book>
</BookStore>

另外,为了书写方便,以下示例的代码都采用与 html 代码杂合的方式编写。

13.3.2 用 XmlTextReader 类读取和解析 XML 文档

XmlReader 是一个抽象类,可以继承并扩展它的功能。XmlTextReader 类是 XmlReader


类的具体实现,这个类的对象可用于读取非缓存的基于只向前的 XML 数据流。它能够检
查 XML 文档格式的正确性。阅读器先验证 XML 文档是否是格式良好的文档,如果不是则
抛出一个异常。XmlTextReader 通过 XML 文档的文件名,或它的 URL,或者从文件流中
载入 XML 文档,然后快速地处理 XML 文档数据。如果需要对文档的数据进行验证,可以
用 XmlValidatingReader 类。

·282·
第 13 章 XML 与.NET 构建小型 Web 应用 ·283·

在创建新对象的构造函数中指明 XML 文件的位置即可。


dim myRdr as New XmlTextReader(Server.MapPath("books.xml"))

所有 XmlTextReader 类的构造函数都要求指定数据源调用。一旦读取对象创建完毕,
就可以调用其 Read 方法来读取文档。Read 方法顺序读取数据段,每段数据类似于 XML
树的结点,NodeType 属性包含了该段数据的类型,Name 属性包含了结点的名称,Value
属性包含结点的值(若有值的话)。然后使用下列语句来输出信息。
Response.write(myRdr.NodeType.ToString()+" "+
_myRdr.Name+":"+myRdr.Value)

另外,在 XmlTextReader 对象中处理 XML 结点属性的方式稍有不同。当读取一个结


点时,可以使用读取对象的 HasAttributes 属性来查看是否存在与之相关的属性。如果元素
中有属性,可以应用 MoveToAttribute(i)方法遍历属性集合。AttributeCount 属性包含当前元
素的属性数。一旦处理完所有属性,则需要应用 MoveToElement 方法将光标移回当前元素
结点。下面的代码将会显示一个元素的属性。
if myRdr.HasAttributes then
for i=0 to myRdr.AttributeCount-1
myRdr.MoveToAttribute(i)
Response.Write(myRdr.NodeType.ToString()+":"+myRdr.Name_
+":"+myRdr.Value+"</br>")
next i
myRdr.MoveElement()
end if

1. 解析 XML 文档
下面给出一个完整的实例,说明应用 XmlTextReader 类解析和显示 books.xml 文件。将
其中的信息显示在 Web 页中。
【例13.2】 使用 XmlTextReader 类解析并显示 books.xml 文件,代码如源程序 xmlText
Reader1.aspx 所示。
<%@ Page language="VB" debug="true" %>
<%@ Import Namespace="System.Xml" %>
<html>
<script runat="server">
sub Page_Load(sender as Object, e as EventArgs)
dim myRdr as New XmlTextReader(Server.MapPath("books.xml"))
dim i as integer
while myRdr.Read()
Response.Write(myRdr.NodeType.ToString()+":"+myRdr.Name _
+":"+myRdr.Value+"</br>")
if myRdr.HasAttributes Then
for i=0 to myRdr.AttributeCount-1
myRdr.MoveToAttribute(i)
Response.Write(myRdr.NodeType.ToString()+":"+myRdr.Name_
+":"+myRdr.Value+"</br>")
next i

·283·
·284· XML 实用教程

myRdr.MoveToElement()
end if
end while
myRdr.Close()
end sub
</script>
<body style="font: 10pt verdana"></body>
</html>

本例的部分输出如图 13.7 所示。

图 13.7 代码的部分输出

上例代码先打开一个 XML 文档,调用 XmlTextReader 的 Read 方法,从文档顶部开始,


遍历文档的所有结点。当数据读取结束,Read 方法就返回 false。在显示数据时,用冒号将
输出的结果中的结点类型、结点名和结点值分隔开来。
2. 检索 XML 文档的数据
在上面所举的例子中,遍历 XML 文档中所有的数据并进行显示,包括了空格符,下
面的例子将浏览整篇文档,只显示应用程序所需的数据。使用列表框显示所有商品的名称,
用户首先选择一个商品名,然后程序将自动查询 XML 文档寻找并显示商品的价格。程序
进行两次查询 XML 文件,第一次加载列表框的数据,第二次查找选定商品的价格。当然,
不断读取文件会使程序速度变慢,更好的方法是在第一次查询 XML 数据时构建商品的数
组或数组链表,这样就可以避免第二次查询文件。但例 13.3 的程序只是为了演示的目的,
界面效果如图 13.8 所示。
要加载列表框的数据,需要执行下列步骤:在 Page_Load 事件中加载列表框。程序将
一次读取一个结点,如果结点为元素型结点,则检查它的名称是否为 title,即书名。如果
是,则用 Read 方法读取文本结点并调用 myRdr.ReadString 方法提取结点值,然后将其加载
到列表框。最后关闭 Reader 对象。

·284·
第 13 章 XML 与.NET 构建小型 Web 应用 ·285·

图 13.8 检索 XML 文档数据


while myRdr.Read()
if XmlNodeType.Element
if myRdr.Name="title" Then
lstBooks.Items.Add(myRdr.ReadString)
end if
end if
end while
myRdr.Close()

要查找选定商品的价格,在发生 Show Price 命令按钮的 Click 事件时,再进行显示。


设计 ShowPrice 函数进行处理,单击按钮时进行调用。
<asp:Button id="btnShowPrice" runat="server" Text="显示价格"
onClick="ShowPrice"> </asp:Button>

这里需要加入第二个 XmlTextReader 对象。当要查找价格时,顺序扫描所有结点。


XmlTextRead 类可以通过 MoveTocontent 方法跳过不需要的结点。MoveTocontent 检查当前
结点是否为内容结点,如果不是,则跳到下一个内容结点。最开始,实例化 XmlTextReader
对象时,它的结点类型是 None,恰好不是内容结点。因此,第一个 MoveTocontent 语句找
到内容结点,然后程序检查是否是名为 title 的结点,并检查该结点 ReadString 的返回值是
否与选定商品名相同。如果一样,程序将调用 Read 方法访问下一个结点。Read 方法可能
会移动到空格结点,因此,程序调用 MoveTocontent,找到 price 结点。
【例 13.3】 查找选定商品的价格的示例函数。
sub showPrice (s as Object, e as EventArgs)
dim myRdr2 as New XmlTextReader(Server.MapPath("books.xml"))
dim unitPrice as Double
dim qty as Integer
do while not myRdr2.EOF()
if (myRdr2.MoveToContent()=XmlNodeType.Element _
and myRdr2.Name="title" _
and
myRdr2.ReadString()=lstBooks.SelectedItem.ToString())
myRdr2.read()
if(myRdr2.MoveTocontent()=XmlNodeType.Element _

·285·
·286· XML 实用教程

And myRdr2.Name="price")
unitPrice=Double.Parse(myRdr2.ReadString())
lblPrice.Text="Unit Price =" +Formatcurrency(unitPrice)
exit do
end if
end if
myRdr2.Read()
loop
end sub

13.3.3 用 XmlTextWriter 类书写 XML 文档

XmlWriter 类包含了写 XML 文档所需的方法和属性,它是 XmlTextWriter 类和 XmlNodeWriter


类的基类。该类包含了 WriteNode、WriteString、WriteAttributes、WriteStartElement 和
WriteEndElement 等一系列写 XML 文档的方法,其中有些方法是成对出现的。比如要写入
一 个 元 素 , 首 先 得 调 用 WriteStartElement 方 法 , 接 着 写 入 实 际 内 容 , 最 后 是 调 用
WriteEndElement 方法以表示结束。该类还包含了 WriteState、XmlLang 和 XmlSpace 等属
性,其中 WriteState 属性表明了写的状态。因为 XmlWriter 类包含了很多写 XML 文档的方
法,所以这里只是介绍最主要的几种。下面通过其 XmlTextWriter 子类来说明如何写 XML
文档。使用 XmlTextWriter 输出到 XML 文档的界面效果如图 13.9 所示,部分代码如图 13.10
所示。

图 13.9 使用 XmlTextWriter 输出到 XML 文档

图 13.10 部分输出

·286·
第 13 章 XML 与.NET 构建小型 Web 应用 ·287·

设计过程中,首先要创建一个 XmlTextWriter 类的实例对象。该类的构造函数 XmlTextWriter


有 3 种重载形式,其参数分别为一个字符串、一个流对象和一个 TextWriter 对象。这里运
用字符串的参数形式,该字符串就指明了所要创建的 XML 文件的位置,方法如下:
dim myWriter as New XmlTextWriter _
(Server.MapPath("Customer.xml"),Nothing)
XmlTextWriter textWriter = New XmlTextWriter("C:\\myXmFile.xml", null);

在创建完对象后,调用 WriterStartDocument 方法开始写 XML 文档,在完成写工作后,


就调用 WriteEndDocument 结束写过程并调用 Close 方法将它关闭。在写的过程中,可以调用
WriteComment 方法来添加说明,通过调用 WriteString 方法来添加一个字符串,通过调用
WriteStartElement 和 WriteEndElement 方法对来添加一个元素,通过调用 WriteStartAttribute
和 WriteEndAttribute 方法对来添加一个属性。还可以通过调用 WriteNode 方法来添加整个
结点,其他写的方法还包括 WriteProcessingInstruction 和 WriteDocType 等。下面的实例就
是介绍通过 Web 页收集用户给定的数据,然后在 XML 文件中写入这些数据。把数据写入
到 Customer.xml 磁盘文件中。文件写入完毕后,调用:
Response.Redirect ("Customer.xml")

在浏览器中直接显示 XML 文档的内容。这里要注意的是必须在服务器端有写入文件


的权限,否则会出错。
【例 13.4】 用 XmlTextWriter 类书写 XML 文档的示例。
<%@ Page language="VB" Debug="True" %>
<%@ Import Namespace="System.Xml" %>
<html><head><title>XmltextWriter Example</title></head>
<body><form runat="server">
<b>XmlTextWriter Example</b><br/><br/>
<asp:Label id="lblAcno" Text="Account Number :"
runat="server"/>&nbsp;&nbsp;
<asp:TextBox id="txtAcno" runat="Server" width="50" text="ST124" /><br/>
<asp:Label id=“lblName" Text="Name :" runat="server"/>&nbsp;&nbsp;
<asp:TextBox id="txtName" runat ="server" width="100" text="Benjamin
Frank"/>
<br/>
<asp:Label id="lblCity" Text="City :" runat="server"/>&nbsp;&nbsp;
<asp:TextBox id="txtCity" runat ="server" width="100" text="Xiamen"/>
<asp;Button id="cmdWriteXML" Text="Creat XML File" runat="server"
onclick="writeXML" />
<br></form>
<script Language="VB" runat="server">
sub writeXML(sender as Object, e as EventArgs)
dim myWriter as New
XmlTextWriter(Server.MapPath("Customer.xml"),nothing)
'设置
myWriter.Formatting=Formatting.Indented
'开始写过程,调用 WriteStartDocument 方法
myWriter.WriteStartDocument()

·287·
·288· XML 实用教程

myWriter.Writecomment("XmlTextWriter Example")
myWriter.WriteStartElement("CustomerDetails")
myWriter.WriteAttributeString("AccountNumber","Saving")
myWriter.WriteStartElement("AccountNumber","")
myWriter.WriteString(txtAcno.Text)
myWriter.WriteEndElement()
myWriter.WriteStartElement("Name","")
myWriter.WriteString(txtName.Text)
myWriter.WriteEndElement()
myWriter.WriteStartElement("City","")
myWriter.WriteString(txtCity.Text)
myWriter.WriteEndElement()
myWriter.WriteEndDocument()
myWriter.Flush()
myWriter.Close()
Response.Redirect ("Customer.xml")
end sub
</script>

13.3.4 存储和处理 XML 文档

存储和处理 XML 文档主要通过 XmlDocument 类的对象。XmlDocument 的对象代表了一


个 XML 文档,
它也是一个非常重要的 XML 类。
当 XmlDocument 对象被加载后,
它将把 XML
文档的内容组织成一棵树。XmlTextReader 只提供一个前向游标来访问结点,
而 XmlDocument
对象提供了多种结点快速直接访问的方式。一些常用成员包括 DocumentElement(树根)、
ChildNodes(一个结点的所有子结点)、FirstChild、LastChild、HasChildNodes、InnerText(文
本格式的子树的内容)、Name(结点名称)、NodeType 和 Value(文本结点的值)。
一般可以使用父—子层次结构对结点编址。结点的第一个子结点是 ChildNode(0),第
二个子结点是 ChildNode(1),以此类推。

1. 加载并保存 XML 文档

XmlDocument 包含了 Load、LoadXml 以及 Save 等重要的方法。其中 Load 方法可以从


一个字符串指定的 XML 文件或是 XmlReader 对象导入 XML 数据。LoadXml 方法完成从一
个特定的 XML 文件导入 XML 数据的功能。Save 方法则将 XML 数据保存到一个 XML 文
件中或是一个流对象、TextWriter 对象、XmlWriter 对象中。
以下程序中用到了 XmlDocument 类对象的 LoadXml 方法,它从一个 XML 文档段中读
取 XML 数据并调用其 Save 方法将数据保存在一个文件中。
// 创建一个 XmlDocument 类的对象
XmlDocument doc = new XmlDocument();
doc.LoadXml(("<Student type='regular' Section='B'><Name>Tommy
Lex</Name></Student>"));
// 保存到文件中
doc.Save(Server.MapPath("student.xml"));

·288·
第 13 章 XML 与.NET 构建小型 Web 应用 ·289·

这里,还可以通过改变 Save 方法中的参数,将 XML 数据显示在控制台中,如:


doc.Save(Console.Out);

而在以下程序中,用到了一个 XmlTextReader 对象,通过它读取 books.xml 文件中的


XML 数据。然后创建一个 XmlDocument 对象并载入 XmlTextReader 对象,这样 XML 数据
就被读到 XmlDocument 对象中了。最后,通过该对象的 Save 方法将 XML 数据显示在控制
台中。
XmlDocument doc = new XmlDocument();
// 创建一个 XmlTextReader 对象,读取 XML 数据
XmlTextReader myRdr = new XmlTextReader(Server.MapPath("book.xml"));
myRdr.Read();
// 载入 XmlTextReader 类的对象
doc.Load(myRdr);
// 将 XML 数据显示在控制台中
doc.Save(Console.Out);

2. 遍历 XML 文档
把 XML 文档看成是一棵树,可以使用 XmlDocument 对 XML 文档进行遍历,下面的
例子主要是遍历 DOM 树并显示每个结点包含的信息。遍历的结果如图 13.11 所示。

图 13.11 遍历的结果

这里,实现了以下两个过程。
(1) DisplayNode:传递一个结点参数,并检查它是不是终端结点或者有没有包含属性。
如果有的话则打印结点内容。
(2) TravelDownATree:传递一棵树,采用先序遍历方式,首先调用 DisplayNode,显示
根结点信息,然后递归调用自己访问子树。
【例 13.5】 用 XmlTextWriter 类书写 XML 文档的示例。
<%@ Page Language = "VB" Debug="True" %>
<%@ Import Namespace="System.Xml" %>
<script language="vb" runat="server" >
sub Page_Load(s as Object, e as EventArgs)
if not Page.IsPostBack then

·289·
·290· XML 实用教程

dim myXmlDoc as New XmlDocument()


dim myRdr as new XmlTextReader(Server.MapPath("books.xml"))
myRdr.WhitespaceHandling=WhitespaceHandling.None
myXmlDoc.Load(myRdr)
TravelDownATree(myXmlDoc.DocumentElement)
myRdr.close()
end if
end sub
sub TravelDownATree(tree as XMLNode)
if not IsNothing(tree) then
DisplayNode(tree)
end if
if tree.HasChildNodes then
tree=tree.FirstChild
while not IsNothing(tree)
TravelDownATree(tree)
tree=tree.NextSibling
end while
end if
end sub
sub DisplayNode(node as XMLNode)
if not node.HasChildNodes then
Response.Write("Name="+node.Name+"Type=" _
+node.NodeType.ToString()+"Value=
"+node.Value="<br/>")
else
Response.Write("Name="+node.Name+"Type=" _
+node.NodeType.toString()+"<br/>")
if node.NodeType=XmlNodeType.Element then
dim x as XmlAttribute
for each x in node.Attributes
Response.Write("Name="+x.Name+"Type="+ _
x.NodeType.ToString()+"Value="+x.Value+"<br/>")
next
end if
end if
end sub
</script>

3. 使用 XmlDataDocument 类
XmlDataDocument 类是 XmlDocument 类的扩展,它最吸引人的一点是提供了同一数据
的两种可选择的视图:XML 视图和关系视图。XmlDataDocument 拥有一个称为 DataSet 的
属性,通过该属性可以将数据分解为一个或多个相关或不相关的数据表。一旦加载了一个
XmlDataDocument 对象,就可以通过 DataSet 属性把它当做 DOM 树或者把它的数据当做一
个数据表(或是数据表的集合)使用。当把数据当做 DOM 树时,与 XmlDocument 类访问 DOM
树的行为方式是一样的。下面举例示例如何从 XmlDataDocument 的 DataSet 数据表视图中
获取数据,结果如图 13.12 所示。

·290·
第 13 章 XML 与.NET 构建小型 Web 应用 ·291·

图 13.12 XmlDataDocument 转换 XML 为 DataSet 输出

要将 books.xml 文档的数据以 DataGrid 的关系表形式处理和显示,该文档的模式可以


使用 Visual Studio.NET XML 设计器直接生成 books.xsd。
然后,在代码中利用 XmlDataDocument 对象的 ReadXmlSchema 方法加载模式如下:
myDataDoc.DataSet.ReadXmlSchema(Server.MapPath("books.xml"))

接着,加载 XmlDataDocument 如下:


myDataDoc.Load(Server.MapPath("books.xml"))

因为 XmlDataDocument 提供了两种视图,所以下面使用 DataSet.Table(0)属性作为


DataGrid 的数据源。把数据源与 DataGrid 控件绑定就可以显示所有书籍信息了。
【例 13.6】 使用 XmlDataDocument 类显示 XML 文档的示例。
<%@ Page Language="VB" Debug="True" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Data" %>
<html><head></head>
<body><form runat="server">
select a Book:<br/>
<asp:DataGrid id="myGrid" runat="server"/>
</form></body></html>
<script Language="VB" runat="server">
sub Page_Load(s as Object, e as EventArgs)
if not Page.IsPostBack then
dim myDataDoc as New XmlDataDocument()
myDataDoc.DataSet.ReadXmlSchema(Server.MapPath("books.xsd"))
myDataDoc.Load(Server.MapPath("books.xml"))
myGrid.DataSource=myDataDoc.DataSet.Tables(0)
myGrid.DataBind()
end if
end sub
</script>

4. 利用 XSLT 对 XML 文档进行转换


前面介绍了使用 XSLT 将一个 XML 文档转换成另一个 XML 文档或是其他类型(如

·291·
·292· XML 实用教程

HTML 和文本型)的文档。在.NET 中,可以利用 XSLT 类的 Transform 方法来对一个 XML


进行转换。对于 IE 5.5 以上版本都有一个自动将 XML 文档转换为 HTML 文档的内部 XSL
转换器。即如果在 IE 中打开 XML 文档时,用可折叠的树状形式来显示数据。要使用.NET
进行 XML 文档转换时,同样需要源 XML 文档和提供转换规则的 XSL 文档。.NET 的转换
只是起到一个执行 XSL 文档中转换指令的作用。
下面的例子将一个 XML 文档转换成 HTML 文档,以列表的方式形式显示过滤的数据。
在第 8 章介绍有一个完整的转换实例,实际是从 shoppingCart.xml 文档中提取购物车信息,
最终将以 HTML 表的形式显示。调用 shoppingCart.xsl 文档对其进行转换。
在 ASP 文件中,已经包括了 asp.xml 的 XSL 转换控件。定义这个控件时,将它的 DocumentSource
属性放进 shoppingCart.xml 中,它的 TransformSource 属性放进 shoppingCart.xsl,那么页面
启动时就可以直接执行转换。
【例 13.7】 利用 XSLT 对 XML 文档进行转换的示例。
<%@ Page Language="VB" Debug="True" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import namespace="System.Xml.xsl" %>
<html><head></head><body><form runat="server">
<b>XSL Transformation Example&nbsp;</b><br/>
<asp:Xml id="ourXSLTTransform" runat="server"
DocumentSource="shoppingCart.xml" TransformSource="shoppingCart.xsl" />
</form></body></html>

13.3.5 XML 与数据库协调工作

数据库用来存储和管理企业的数据,将数据从数据库传送给远程客户端和业务伙伴时,
特别是不清楚客户端将如何使用数据时,传统方法就显得比较困难。用 XML 文档发送所
需的数据,就使得数据的容器与客户端的平台无关。数据库和其他的相关数据存储方式还
在,XML 不会替代它们,但 XML 将提供一种在源和目标之间交换数据的通用媒介。XML
也使得不同软件之间能够交换数据。在此背景下,XML 在 ADO.NET 同其他程序间建立了
一座桥梁。由于.NET Framework 集成了 XML,在.NET 中用 XML 交换数据要比其他的软
件开发环境容易。数据可以通过 XML 从一个数据源转换到另一个。.NET Framework 主要
基于 DataSet 类,因此它非常依赖 XML 体系结构,DataSet 类具有许多处理 XML 的方法,
其 中 常 用 的 有 ReadXml 、 WriteXml 、 GetXml 、 GetXmlSchema 、 InferXmlSchema 、
ReadXmlSchema 和 WriteXmlSchema。
下面的两个例子就是让 XML 和数据库进行协同工作。第一个例子中,将用 SQL 查询
创建一个数据集,并把它的内容写成 XML 文档的形式。第二个例子中,将读回第一个例
子所产生的 XML 文档并加载一个数据集。
1. 用查询数据库创建 XML 文档
首先用 Access 数据库中查询到的书籍结果来填充数据集。当单击一个按钮时,写出
XML 文件和它的模式文件。这里可以采用 WriteXml 和 WriteXmlSchema 方法来完成创建
文档的任务。生成的 XML 文档格式如下:

·292·
第 13 章 XML 与.NET 构建小型 Web 应用 ·293·

<myXMLBooks>
<dtBooks>
<BookID>1</BookID>
<Title>三国演义</Title>
<Author>罗贯中</Author>
<Price>24</Price>
<Quantity>5</Quantity>
</dtBooks>
</myXMLBooks>

DataSet 的输出如图 13.13 所示。

图 13.13 DataSet 的输出

【例 13.8】 用查询数据库创建 XML 文档的示例。


<%@ Page Language="VB" debug="true" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.IO" %>
<%@ Import Namespace="System.Data.OleDb" %>
<html><head><title>A example of DataSet</title></head>
<body>
<form runat="server"><b>Books List:</b><br><br>
<asp:datagrid id="myGrid" runat="server"></asp:datagrid><br>
<asp:Button id="cmdWriteXML" text="Create XML File" runat="server"
OnClick="writeXML"/> </form>
<script language="VB" runat="server">
sub Page_Load(s as Object, e as EventArgs)
iF not Page.IsPostBack then
dim myDataSet as new DataSet("myXMLBooks")
dim myConn aS new _
OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;" & _
"User ID=Admin;" & _
"Data Source=" & Server.MapPath("shopDb.mdb"))
myConn.Open()
dim myDataAdapter as new OleDbDataAdapter _

·293·
·294· XML 实用教程

("select BookID,Title,Author,Price,Quantity FROM books",


myConn)
myDataAdapter.Fill(myDataSet,"dtBooks")
myGrid.DataSource=myDataSet.Tables(0)
myGrid.DataBind
Session("sessDs")=myDataSet
end if
end sub
sub writeXml(s as Object,e as EventArgs)
dim myFs1 as new FileStream _

(Server.MapPath("myXMLData.xml"),FileMode.Create,FileShare.ReadWrite
)
dim myFs2 as new FileStream _
(Server.MapPath("myXMLData.xsd"),FileMode.Create,FileShare.ReadWrite
)
dim myDataSet As new DataSet
myDataSet=Session("sessDs")
'使用 DataSet 的 writeXml 方法把 DataSet 数据输出到 XML 文档
myDataSet.WriteXml(myFs1)
myFs1.Close()
myDataSet.WriteXmlSchema(myFs2)
myFs2.Close()
end sub
</script></body></html>

2. 将 XML 文档读入数据集
前面的例子利用 DataSet 来创建 XML 文档,那么,下面的例子则是将 XML 文档读入到
数据集中。这可以利用 ReadXml 方法来读取 XML 文档,加载到数据集中,结果如图 13.14
所示。

图 13.14 从 XML 文档加载数据集

【例 13.9】 将 XML 文档读入数据集的示例。


<%@ Page Language="VB" Debug="true" %>
<%@ Import Namespace="System.Xml" %>
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.IO" %>

·294·
第 13 章 XML 与.NET 构建小型 Web 应用 ·295·

<%@ Import Namespace="System.Data.SqlClient" %>


<html><head><body><form runat="server">
<b>Books Data From XML File:</b><br/><br/>
<asp:DataGrid id="myGrid" runat="server" /><br/><br/>
</form></body></head></html>
<script language="VB" runat="server">
sub Page_Load(s as Object, e as EventArgs)
if not Page.IsPostBack then
dim myDataSet as new DataSet("myXMLProduct")
dim myFs as new FileStream _

(Server.MapPath("myXMLData.xml"),FileMode.Open,FileShare.ReadWrite)
myDataSet.ReadXml(myFs)
myGrid.DataSource=myDataSet.Tables(0)
myGrid.DataBind
myFs.close
end if
end sub
</script>

13.4 利用 XML 和.NET 构建动态网站

本节利用前面的 XML 知识以及.NET 技术,构建一个假想的网上书店。

13.4.1 网上书店项目概述

这里只是一个讲解 XML 技术在实际中应用的示例,所实现的网上书店功能比较简单,


包括:让在线顾客能从网站购书或是其他相关物品。首先让顾客在线浏览商品,当其选中
某个商品时,就可以把它选入购物车内,当然在这之前用户必须登录。购物车应用程序能
够验证用户,显示当前购物车内的物品,顾客在此时也可以进行添加、更新以及结账等操
作。网上书店完成后的用户界面如图 13.15 所示。
经过简化后,要实现以上需求,整个网站分为以下几个部分:
(1) 书籍浏览选购模块;
(2) 购物车管理;
(3) 网上商店用户管理。
具体实现时,需要创建:
(1) 保存所有书籍信息的 XML 文件;
(2) 用于连接用户的接口(UI);
(3) 为顾客设计购物车接口来处理添加、更新、删除和检索等操作。

·295·
·296· XML 实用教程

图 13.15 网上书店完成后的用户界面

13.4.2 网站后台数据文件

首先,一个商务网站离不开后台。这里只是为了讲解 XML 文件的使用,因此采用 XML


文件作为网站要设计整个网站的后台数据文件。实际上,商务网站还是使用传统的数据库
作为网站的后台数据库,采用 Web Service 方法来实现数据库逻辑,XML 只是作为中间的
数据库传输媒介,从而可以把用户接口和数据层分离开来。同时,使数据可以被多种的客
户端访问。
这里用到的 XML 文件有:
(1) 用于存放书籍信息的 Books.xml 文件。
<?xml version="1.0" encoding="gb2312" ?>
<books>
<book>
<isbn>0-764-58007-8</isbn>
<title>三国演义</title>
<author>罗贯中</author>
<price>36</price>

·296·
第 13 章 XML 与.NET 构建小型 Web 应用 ·297·

<resume>滚滚长江东逝水,浪花淘尽英雄。是非成败转头空。青山依旧在,几度夕阳红。
白发渔樵江渚上,惯看秋月春风。一壶浊酒喜相逢。古今多少事,都付笑谈中。
</resume>
<image_path>bookimage/1.bmp</image_path>
<category>1</category>
</book>
</books>

(2) 存放用户信息的 users.xml 文件。


<?xml version="1.0" encoding="gb2312" ?>
<users>
<user>
<id>1</id>
<username>Jerry</username>
<password>123</password>
</user>
</users>

(3) 保存用户定购信息的 orders.xml 文件。


<?xml version="1.0" standalone="yes"?>
<orders>
<item>
<username>guest</username>
<date>2005-7-18 0:00:00</date>
<orderlist>
<username>guest</username>
<isbn>0-764-58007-8</isbn>
<title>三国演义</title>
<quantity>1</quantity>
<price>36</price>
</orderlist>
<orderlist>
<username>guest</username>
<isbn>121123</isbn>
<title>红楼梦</title>
<quantity>1</quantity>
<price>36</price>
</orderlist>
</item>
</orders>

(4) 书藉分类的 categories.xml 文件。


<?xml version="1.0" encoding="gb2312" ?>
<categories>
<item id="1">文学</item>
<item id="2">艺术</item>
<item id="3">计算机</item>
<item id="4">儿童读物</item>
</categories>

·297·
·298· XML 实用教程

13.4.3 网站站点架构

设计好后台数据文件以后,现在再来设计网站中间层的业务数据层和界面,这是建立
网上顾客与商店之间的桥梁,网站的结构如图 13.16 所示。

图 13.16 网上书店结构图

顾客通过 index.asp 页面浏览网站上待售的书籍信息。进行选购时,则先要登录到网站,


然后选择自己满意的书籍。当然顾客如果没有账户,可以使用 adminCustomer.asp 来注册新
用户,可以通过这部分修改用户资料。顾客选择的书籍先放到购物车中,当顾客想要进行
购买时,可以进行到 shopCart.asp 页面来完成选购。

13.4.4 具体实现

这里主要介绍显示书籍信息以及购物车功能的实现。由于 DataSet 提供更方便的处理


方式,在处理过程中,都是采用 DataSet 作为中间缓冲。把 XML 文件读入 DataSet 后,或
者把数据先保存到数据集中,然后再处理。
显示书籍信息供顾客浏览是在 index.asp 页面实现。首先在页面放置好适当控件,使用
DataList 控件来显示全部书籍信息。页面顶部是网站信息,左边放置用户登录接口。当用
户登录后,可以在左边直接显示顾客的一些信息。登录后的界面如图 13.17 所示。
设计好页面布局后,需要完成的内容主要有以下几点。

1. 加载书籍信息

当顾客访问网上书店时,显示 index.asp 页面,需要加载书籍分类信息及列举出图书列


表,也就是在页面加载的函数中实现加载。

·298·
第 13 章 XML 与.NET 构建小型 Web 应用 ·299·

图 13.17 用户登录后网上书店首页

书籍分类信息使用一个列表框控件,直接把分类信息加载到列表框即可:
ds.ReadXml(Server.MapPath("data\\categories.xml"))
for i = 0 To ds.Tables(0).Rows.Count - 1
ddlcat.Items.Add(ds.Tables(0).Rows(i).Item(1))
next

对于书籍信息,则使用 DataList 来显示。在 DataList 中放置相应的控件,设定要显示


的字段。一切设定妥当后,只需要对相应的数据集加载数据表,并与 DataList 控件绑定,
就可以直接在页面显示书籍信息了。
ds.ReadXml(Server.MapPath("data\\books.xml"))
DataList1.DataSource = ds
DataList1.DataBind()

2. 顾客登录
顾客要选购图书,则必须先进行登录,否则就无法选择图书。当顾客登录完后,后继
的订购过程都是以该用户为中心,需要全程保存用户的信息,可以使用 Session 来保存。验
证用户登录,只是一个简单的比较过程:
ds.ReadXml(Server.MapPath("data\\users.xml"))
for i = 0 to ds.Tables(0).Rows.Count - 1
if (ds.Tables(0).Rows(i).Item(1) = usernametxt.Text) then
'成功,使用 session 记录用户信息
Session("username") = Me.usernametxt.Text
Session("id") = ds.Tables(0).Rows(i).Item(0)
'处理界面,显示顾客信息
oklab.Text = "欢迎您"
usernametxt.Visible = false
passwordtxt.Visible = false
userlab.Visible = false

·299·
·300· XML 实用教程

passlab.Visible = false
userinfolab.Visible = true
userinfolab.Text = "用户:" & Session("username")
loginbtn.Text = "退出"
regbtn.Visible = false
exit for
end if
next

3. 书籍选购
当顾客选择某一书时,需要把书籍信息放入购物车。也可能顾客还没有登录,所以开
始时需要先判断顾客登录与否。
if CChar(Session("username")) = "" then
Response.Write("<script language=javascript>alert('对不起!你
还未登录,不能购买,请先登录!
');window.location.href='index.aspx';</script>")
Response.End()
else

end iF

如果顾客已经登录,则需要记录顾客所选择的书籍,可以使用 ArrayList 来记录。记录


完毕应该转到购物车界面让顾客查看他所选择的书籍。
dim orderlist as ArrayList
dim qtylist as ArrayList
'获取购物栏中的商品
orderlist = Session("orderlist")
qtylist = Session("qtylist")
'获取所选中的图书的 ISBN()
bk_isbn =
CType(Me.Datalist1.Items(e.Item.ItemIndex).FindControl("isbnlab"),
Label).Text()
bk_isbn = Datalist1.DataKeys(Me.Datalist1.SelectedIndex) '检
查是否已买了此书
if orderlist.IndexOf(bk_isbn) = -1 then
'否,未曾购买
orderlist.Add(bk_isbn)
qtylist.Add("1")
else
'如果此书已存在于购物栏,数量+1
dim num as Integer = orderlist.IndexOf(bk_isbn)
qtylist(num) = CInt(qtylist(num)) + 1
end if
'存储购物栏
Session("orderlist") = orderlist
Session("qtylist") = qtylist
'转到购物车界面
Response.Redirect("shopCart.aspx", True) '

·300·
第 13 章 XML 与.NET 构建小型 Web 应用 ·301·

4. 实现购物车
购物车存放用户选择的书籍及需要购买的数量等信息。用户通过购物车界面能够管理
购物车中的物品,包括删除和更改购买数量等。使用 DataGrid 控件来显示用户已经订购的
商品。
当页面加载时,或者用户进行删除、更改购买数量等操作时,都要重新初始化购物车,
必须更新购物车信息,显示用户已经订购的书籍信息。
private sub updatashopcart()
dim orderlist as ArrayList
dim qtylist as ArrayList
dim i as Integer
dim bookisbn as String
dim book as DataRow
dim tot as Double
dim ordertable as DataTable = New DataTable("ordertable")
'创建新行和列
dim ordercol as DataColumn
dim orderrow as DataRow
'创建数据列
'==书名
ordercol = New DataColumn
ordercol.DataType = System.Type.GetType("System.String")
ordercol.ColumnName = "bk_name"
ordertable.Columns.Add(ordercol)
'==数量
ordercol = New DataColumn
ordercol.DataType = System.Type.GetType("System.Int32")
ordercol.ColumnName = "bk_num"
ordertable.Columns.Add(ordercol)
'==单价
ordercol = New DataColumn
ordercol.DataType = System.Type.GetType("System.Double")
ordercol.ColumnName = "bk_price"
ordertable.Columns.Add(ordercol)
'==小计
ordercol = New DataColumn
ordercol.DataType = System.Type.GetType("System.Double")
ordercol.ColumnName = "bk_total"
ordertable.Columns.Add(ordercol)
'创建数据行
orderlist = Session("orderlist")
qtylist = Session("qtylist")
'
tot = 0
for i = 0 to orderlist.Count - 1
bookisbn = orderlist(i)
book = getbookrow(bookisbn)
orderrow = ordertable.NewRow
orderrow("bk_name") = book("title")

·301·
·302· XML 实用教程

orderrow("bk_num") = qtylist(i)
orderrow("bk_price") = book("price")
orderrow("bk_total") = book("price") * qtylist(i)
ordertable.Rows.Add(orderrow)
'统计总金额
tot += book("price") * qtylist(i)
'
next
DataGrid1.DataSource = ordertable.DefaultView
DataGrid1.DataBind()
'显示总金额
Me.totlab.Text = String.Format("{0:C}", tot)
end sub

另外,用户完成选购时,点击“购买”链接,把用户的订购信息保存起来,以备后台
管理人员根据订单发送书籍。
ds.ReadXml(Server.MapPath("data\\orders.xml"))
Dim rowNew1 As DataRow = ds.Tables(0).NewRow()
Dim rowNew2 As DataRow = ds.Tables(1).NewRow()
orderlist = Session("orderlist")
qtylist = Session("qtylist")
‘记录用户信息
rowNew1("username") = Session("username")
rowNew1("date") = Today
ds.Tables(0).Rows.Add(rowNew1)
'循环记录用户订购书籍的信息
For i = 0 To orderlist.Count - 1
book = Me.getbookrow(orderlist(i))
rowNew2("username") = Session("username")
rowNew2("isbn") = book("isbn")
rowNew2("title") = book("title")
rowNew2("quantity") = qtylist(i)
rowNew2("price") = book("price")
ds.Tables(1).Rows.Add(rowNew2)
rowNew2 = ds.Tables(1).NewRow()
Next
'建立两张表之间的嵌套关系
dim dr as new DataRelation("orderrelation",_
ds.Tables(0).Columns("username"), ds.Tables(1).Columns("username"))
dr.Nested = True
ds.Relations.Add(dr)
ds.WriteXml(Server.MapPath("data\\orders.xml"),
XmlWriteMode.IgnoreSchema)
Response.Write("<script language=javascript>alert('您已成功订购了!
10 天后您将收到你所要图书!');window.location.href='index.aspx';</script>")
Response.End()

实现后的购物车界面如图 13.18 所示。

·302·
第 13 章 XML 与.NET 构建小型 Web 应用 ·303·

图 13.18 购物车的界面

13.5 小 结

.NET Framework 是一种新的开发平台,为其能在高度分布式的互联网环境中使用,它


简化了 Internet 环境中的应用程序开发。由于要加强分布式.NET 应用程序之间的通信,所
以.NET 结构很大程度地使用了 XML。事实上,XML 是.NET Framework 的默认编码语言,
它不仅用于封装数据使之能够在应用程序之间传送,还用在配置文件中。在.NET 体系结构
中,XML 是各应用之间无缝接合的关键。只有明白了.NET Framework 究竟是什么,才能
明白选择使用 XML 的合理性。
Visual Studio .NET 能够快速创建下一代 XML Web 服务和应用程序,这些服务和应用
程序面向任何 Internet 设备并在编程语言和操作系统之间集成。Visual Studio .NET 和 XML
Web 服务提供简单、灵活、基于标准的模型,允许开发人员用新的和现有的代码汇编应用
程序,而与平台、编程语言或对象模型无关。
.NET Framework 的 System.Xml 名称空间提供了丰富的 XML 相关类,用来存储和处理
XML 文档。其他的软件开发平台也可使用这些类。本章简单地说明了用来读取、存储和处
理 XML 文件的.NET 类。
最后介绍了如何开发一个网上书店的实例,可以让顾客浏览书目,把选定的书籍添加
到虚拟的购物车中,或从购物车中删除条目,通过登录到网站并提交更新信息到数据文件
中来模拟订单处理。充分应用了 XML 的强大功能及表示数据和结构的能力,并使用 Visual
Studio .NET 语言实现。

·303·
·304· XML 实用教程

13.6 习 题

1. .NET Framework 开发平台带来的主要优点有哪些?


2. 使用 Visual Studio .NET 内置的 XML 编辑器生成以下 movies.xml 文件的模式文件。
<?xml version="1.0" encoding="GB2312"?>
<movies type="动作片">
<id>1</id>
<name>致命摇篮</name>
<brief>李连杰最新力作!</brief>
<time>2003</time>
</movies>

3. 应用 XmlTextReader 对象解析和显示 movies.xml 文件。


4. 使用 XmlDocument 对 movies.xml 文档进行遍历,并用网页形式显示出来。
5. 试着读取一个 XML 文件,并将其存储到 DataSet 中,然后用 DataGrid 等数据控件
进行显示。
6. 编写把 movies.xml 文件转换成 HTML 文件的转换 XSLT 文件,转换成如下格式。
并借助.NET 提供的 XML 处理类,对 movies.xml 文件进行转换。

第 1 部电影
名称 简介 时间 类型
致命摇篮 李连杰最新力作 2003 动作片

7. 编写程序实现读取 movies.xml 文件的内容并将内容保存到 Access 数据库中。


onblur="tblbooks.dataPageSize=this.value;">笔
</center>
<center>请单击上表有兴趣的图书行</center>
<hr>
<center>单本图书信息:书名: <span id="title"></span></center>
<table border="1" align="center" >
<tr><td width="50%">
分类: <span id="bookcategory"></span><br>
书号: <span id="ISBN"></span><br>
作者: <span id="author"></span><br>
</td>
<td width="50%">
出版: <span id="publisher"></span><br>
定价: <span id="price"></span> 元<br>
剩余: <span id="remain"></span>本<br>
</td>
</tr>
</table>
<hr>
</body>
</html>

·304·
参 考 文 献

1 美 David Jorgensen. 使用 XML 开发.NET Web 服务. 北京:科学出版社,2003.6


2 美 Kurt Cagle. XSL 高级编程. 北京:机械工业出版社,2002.4
3 美 Priscilla Walmsley. XML 模式权威教程. 北京:清华大学出版社,2003.1
4 丘广华,张文敏. XML 编程实例教程. 北京:科学出版社,2004.4
5 陈会按. XML 网页制作彻底研究.北京:中国铁道出版社,2003.2
6 美 Benoit Marchal.XML 示例程序导学. 北京:清华大学出版社,2002.9
7 李永祥等. XML 网页开发实例教程. 北京:清华大学出版社,2002
8 美 Ann Navarro 等. XML 从入门到精通. 北京:电子工业出版社,2000
9 林锦雀等. 最新 XML 入门与应用. 北京:中国铁道出版社,2001
10 美 Michael J.Young. XML 学习指南. 北京:机械工业出版社,2001
11 卢啸龙. XML 完全实例教程. 北京:电子工业出版社,2001
12 美 Graeme Malcolm. SQL Server 2000 与 XML 数据库编程(第 2 版). 北京:清华大学出版社,2003
13 Niclolas chase.计算机导论(第二版). 北京:机械工业出版社,2003
14 雷之宇等. Java 项目开发实践—网络篇. 北京:中国铁道出版社,2005
15 夏邦贵,刘凡新等. XML 网页制作实作教程. 北京:清华大学出版社,2002.12
16 陈勤意,陈长念. XML&ASP 网页程序设计. 北京:清华大学出版社,2001.8
17 蔡翠平,尚竣杰. 网络程序设计-ASP(2). 北京:清华大学出版社,北方交大出版社,2004.2
18 陈锦辉. XML 与 ASP 网站实作大全. 北京:中国铁道出版社,2001.12
19 栗松涛. XML 程序设计. 北京:清华大学出版社,2001

You might also like