4.6.6 XML的解析

4.6.6 XML的解析

1.XML解析器概述

XML作为一种通用的描述和组织数据的方式,其平台无关性、语言无关性、系统无关性给数据集成与交互带来了极大的方便。在很多实际应用中,用户或程序需要从XML文档中提取需要的信息。例如,应用程序可能需要从描述图书信息的XML文档中提取价格信息进行分析处理。这就需要用到XML解析器。

XML解析器是XML文档和应用程序中间的一个软件组织,它能识别XML语法、载入XML文档并分析其结构、提取相应的数据内容。XML应用一般都是围绕解析器建立的。

目前常用的解析器有以下两种。

(1)基于DOM的解析器

DOM是W3C制定的一套规范(http://www.w3.org/DOM/),其基本思想是在内存中建立与文档对应的树形结构模型,并提供一系列与浏览器、平台、语言无关的面向对象的编程接口,以便灵活地操作文档的各个组成部分。它既可以用于HTML文档解析,也可以用于XML文档解析。

(2)基于事件处理的解析器SAX

SAX(Simple API for XML)解析器提供了与平台、语言无关的开源的API用于解析XML文档,其核心是事件处理机制。在解析时SAX解析器需要扫描XML文档,每读到文档的一个组成部分时,如一个XML元素时,就会触发一个事件,相应的事件监听器监听到事件发生后调用相应的事件处理方法,应用程序通过事件处理方法实现对XML文档的操作。

两种解析器各有自己的特点。DOM将文档的树形结构映射在内存中,可以方便地操作树中的节点,提取需要的信息。但如果XML文档较大,或者只需要解析文档的一部分,则会占用大量的内存空间。而SAX以序列的形式处理文档,对内存需求较少,且当找到需要的信息时,SAX可以随时终止解析。不过因为SAX没有将整个文档载入内存,所以它不能对文档进行随机访问,而且开发人员只能按顺序处理数据,在处理包含大量交叉引用的文档时会有局限。

下面主要介绍DOM解析器。

2.XML DOM的文档结构

XML DOM定义访问和操作XML文档的标准方法,它定义了XML文档元素的对象和属性以及访问它们的接口,使应用程序能动态访问操作文档的结构、样式和内容。DOM实际也是一组语言中立的API,它将XML文档看作一个文档对象,可以使用某种编程语言,如Java、JavaScript等,遵循DOM的规范实现其定义的文档操作的属性和方法,就可以对文档对象进行访问和操作了。

DOM解析器在解析XML文档时会将其载入内存并建立一个树形的层次化对象模型来表示文档。DOM将XML文档看作一棵节点树,文档的每一个组成部分,如每个标签、文本、属性都视为树中的一个节点。DOM文档结构的节点可以分为以下几种不同的类型:

·整个文档是一个文档节点,对应节点树的最顶端节点即根节点;

·每一个XML标签都是一个元素节点;

·包含在XML元素中的文本是文本节点;

·每一个XML属性为一个属性节点;

·注释属于注释节点。

此外还包括不太常用的CDATA类型、处理指令类型的节点。

和HTML DOM一样,节点与其他节点存在某种层次关系,可以用父、子、同级节点来描述。父节点拥有子节点,拥有相同父节点的子节点称为同级节点,它们位于相同层级上。文档节点是整个文档中所有其他节点的父节点。元素节点可以有其他元素节点、属性节点、文本节点作为其子节点。这些多层节点共同构成了文档树,它展示了节点的集合以及它们之间的联系。如【例4-44】所示的XML文档可以由图4-34的节点树表示。

图4-34 XML文档的文档树示例

【例4-44】一个XML文档示例:bookinfo.xml。

由上例可以看到,整个XML文档对应了文档节点,它也是节点树的起点。XML文档的根元素books对应了文档节点的一个元素类型的子节点。文档中其他元素均包含在根元素内。根节点下包含2个同级元素子节点指代book标签。book元素节点带有属性节点,表示book元素属性category。每个book元素节点包含5个同级元素子节点:booktitle、author、isbn、publisher和price。它们各自带有文本节点,author和price元素节点还包含属性节点。

3.XML DOM接口和对象

DOM规范提供了一系列节点接口,将每个节点看成一个可以交互的对象,定义了各自拥有的属性和方法。DOM接口是一组方法声明的集合,它包含许多类型。常用的基本接口有Document接口、Node接口、Node List接口、Named Node Map接口、Element接口、Text接口、CDATASection接口和Attr接口等。某个类型的接口是针对节点树的某个对象的一系列方法。按照DOM规范通过编程语言实现相关接口的一个对象,即为DOM对象。例如,使用JavaScript实现了Element接口的对象,即获得一个Element对象,里面封装了元素节点的属性和元素操作方法。下面对常见的对象和接口进行简要介绍。

·Document对象代表整个文档,Document接口提供了对文档数据的最初(或最顶层)的访问入口和创建其他节点对象的方法,它是从Node接口继承过来的。

·Node对象代表了树中的一个节点,Node接口提供了访问节点信息的方法。Node接口是其他大多数接口的父类,如Document、Element、Attr、Text、Comment等接口都是从Node接口继承过来的。

·Node List对象代表一个有顺序的节点列表,包含某个节点中的所有子节点,Node List接口提供了通过节点索引号来访问节点列表中的节点的方法。

·Named Node Map对象表示一个无顺序的节点列表,通过Named Node Map接口可以建立节点名和节点之间的一一映射关系,从而利用节点名可以直接访问节点列表中的节点。

·Element对象代表文档中的元素,元素可包含属性、其他元素或文本。如果元素含有文本,则在文本节点中表示该文本。Element接口继承自Node接口和Node List接口,提供操作元素的方法。

·Text对象表示元素或属性的文本内容,通过Text接口可以访问文本节点的文本内容。

XML文档在加载到内存中时都会被转化成由不同类型的多层节点构成的节点树。XML DOM规范和HTML DOM类似,也提供了一系列节点接口,定义了DOM对象的属性和方法,典型的DOM属性和方法如表4-12所示。通过这棵树状的层次化对象模型和DOM接口就可以访问、修改、添加、删除、创建树中的节点和内容,以实现对XML文档的操作。

表4-12 典型的DOM属性和方法示例

4.使用DOM访问XML文档

下面采用JavaScript语言简要介绍通过DOM访问XML文档的过程。所有浏览器都内建了用于读取和操作XML的XML解析器。解析器把XML文档读入内存,并把它转换为可被JavaScript访问的XML DOM对象。

使用DOM访问XML文档需要首先加载XML文档并创建DOM对象,然后再调用DOM接口实现对文档的操作。

在IE中通过JavaScript加载XML文档,可以使用下述语句:

其中第1句用于创建微软XML文档对象,第2句关闭异步加载,这样可使解析器在文档完整加载之前不继续执行脚本,最后一句告知解析器加载名为“bookinfo.xml”的文档。其他浏览器中的解析器使用DOMParser对象进行加载,与微软解析器有所差别。可以用以下函数在不同浏览器中加载文档,该函数存储在名为“loadxmldoc.js”的文件中。

下面的例子给出一个HTML文档,在head元素中包含了一个指向“loadxmldoc.js”的链接,并使用load XMLDoc()函数加载【例4-45】所示的XML文档(“bookinfo.xml”)。

【例4-45】遍历访问文档元素示例。

上述代码使用DOM的接口遍历节点树,循环显示了根元素下的各book元素的各个子节点的名称和文本内容。语句x=xmlDoc.documentElement.child Nodes中的documentElement是文档对象xmlDoc的一个属性,xmlDoc.documentElement返回了XML文档的根元素books,x=xmlDoc.document Element.child Nodes则返回了根元素下的子节点集合,即两个book节点。n=x[i].child Nodes获得了第i个book节点的所有子节点。n[m].nodeName代表第m个子节点的名称,而n[m].child Nodes[0].node Value表示第m个子节点的第1个子节点的节点值,即文本内容。在IE中的显示效果如图4-35所示。

图4-35 遍历节点树的方式访问XML文档

【例4-46】则采用了DOM对象提供的getElementsBy Tag Name(name)方法以获取由name指定的标签名称的所有元素。

【例4-46】根据标签名提取文档信息示例。

上述代码中x=xmlDoc.get ElementsBy Tag Name(booktitle)返回了booktitle元素,x[i].child Nodes[0].node Value返回的是该元素的第1个子节点的节点值,即文本内容。上例从XML文档中提取了booktitle、price标签包含的文本内容,并采用表格的方式进行显示,显示效果如图4-36所示。

图4-36 根据标签名提取XML文档内容的显示效果