xml 是现在非常流行的数据表达格式,其特点是可移植、与平台无关以及具有直接可读的形式。Document Object Model (DOM) 是应用程序存取 XML 数据的接口。不幸的是,DOM 是一种相当复杂的 API,因而较难以迅速把握。但是,如能知道所存取数据的 DTD,这时就轻易得多了。本文将通过若干简单步骤,对如何利用 java 版的 DOM 来存取 XML 数据进行介绍。
可扩展标记语言 (XML) 已经相当普及,它是一种可移植的、与平台无关的且直接可读的数据格式。许多软件厂商均已宣称“支持 XML”,这通常是指他们的软件产品将生成或用到 XML 格式的数据。
XML 也同样被看作是企业间交流数据的通用格式。它答应企业在 XML 文档类型定义(即 DTD)的基础上对所交流的数据取得一致。这些 DTD 文件独立于企业中所使用的数据类型。
许多标准化组织正在致力于规范交流数据的 DTD。其中一个例子就是国际出版通信委员会(请参见资源)已经定义了一个 XML 的 DTD,这个 DTD 可以使“所传输的带有标记的新闻信息能够轻松地转换为电子出版格式”。这些市场标准将使不同应用程序之间能够在未事先确定方式的情况下进行数据的交换。
由 W3C 定义的 XML 规范(请参见资源)中规定了 XML 的语法和语义。一个 XML 文档必须经过语法分析才能被处理。假如每个程序都必须先对 XML 进行语法分析再去处理,那将是非常困难的,因为给出这种语言的语法和语义是很复杂的。W3C 已经定义了文档对象模型(DOM)(请参见资源)来解决这一问题。DOM 是一个针对XML数据的应用编程接口。大部分 XML 语法分析器都为所分析的 XML 生成一个 DOM 描述。
DOM 标准 DOM API 被定义为一系列 CORBA IDL 接口(请参见资源)。它用一个抽象树来描述一个经过语法分析的 XML 文档。之所以说它是抽象的,这是因为只有这些接口反映出树形的结构。而用来实现抽象树的实际数据结构和算法不必是树形结构。
由于 DOM API 是以 CORBA IDL 形式规定的,所以它被许多编程语言所支持,包括 Java 语言。我们假定本文中使用标准的 Java 语言。DOM 规范给出了具体的基于Java 接口。
DOM 第一层规范是在 1998 年被采用的。它留下一些保留部分,以根据后来的实践经验来进一步扩充。DOM 第二层规范在第一层的基础上增加了对 XML 命名空间、文档创建、视图和式样单等内容的支持。第二层规范尚有待公众评价。虽然从技术上而言还没有最终完成,但是也已经相当稳定。
对于一个 XML 文档,许多 XML 语法分析器均可供 Java 程序使用,以生成 DOM 的第一层描述。因此,这里的代码只假定为基于DOM 的第一层子集。
通用或特定 DTD 代码 在Java中使用DOM API编写的代码要么是通用的,要么是基于特定的DTD。通用代码在所有 XML 文档中都能正常工作。通用代码一般更难编写,因为它通常必须遍历整个 DOM 树,考虑各种可能。代码不能依靠任何特定的元素、属性和文档结构。通用代码用于处理一般性事务,例如检查文档中的拼写错误、计算文字数目、通过网络发送文件,等等。
另一方面,特定 DTD 代码是在根据特定的 DTD 写出的。它不能用来操作由另一种 DTD 定义的 XML 文档。特定的 DTD 比较轻易编写,因为它假设 XML 文档具有该特定 DTD 所指定的格式。例如,假设一个 DTD 声明一个名为“NAME”的元素要求具有一个名为“GIVEN”的属性,Java 代码可以假设这个属性存在并通过简单地 DOM getAttribute() 调用来访问它
应当注重的是,这个接口的实现可有多种不同方式,其中的一些与 XML 无关(例如,某个实现可向数据库发出请求)。当然,这里我们只关心用DOM API 来实现处理 XML 数据的操作,这些数据同前面基于DTD的订单一致。
实现接口 现在编写一个实现该接口并封装 DOM 文档的类。例如,我们定义:
class orderImpl implements order { Document theDocument;
在构建器中将 DOM 文档捆绑至封装类 将 DOM 文档传递给封装类的构建器。构建器检查文档类型,以确定该文档确实符合订单 DTD。记住这些代码只是针对这个 DTD 的,并对数据的结构和内容做出假设。
public orderImpl(Document document) throws Exception { theDocument = document; DocumentType docType = theDocument.getDoctype(); if (docType==null) throw new Exception("Cannot determine document type."); if (!docType.getName().equals("order")) throw new ? Exception("Document is not an order."); }
从唯一的子树中返回一个元素的属性值 在诸如 name 这样的名称不唯一的情况下,billingName 方法是获得元素值的一种方法。注重 name 在这个文档中不唯一,但是在 billing 子树中却是唯一的。另外还要注重,billing 元素在整个文档中是唯一的。这样,我们可以在文档中简单地调用 getElementsByTagName("billing"),然后在返回的 billing 元素中调用 getElementsByTagName。由于 getElementsByTagName 也是在 DOM API 中的 Element 接口中定义的,所以可以这样做。
public String billingName() { NodeList bl = theDocument.getElementsByTagName("billing"); NodeList nl = ((Element)bl.item(0)).getElementsByTagName("name"); Element name = (Element)nl.item(0); return name.getAttribute("given")+" "+name.getAttribute("family"); }
public class test { public static void main(String[] args) { XML4J2DOMSource parser = new XML4J2DOMSource(); try { parser.parse("order.xml"); order theOrder = new orderImpl(parser.getDocument()); System.out.println("The credit card is "+theOrder.creditCard()); System.out.println("The total price is "+theOrder.totalPrice()); System.out.println("The billing name is "+theOrder.billingName()); theOrder.authorizeCredit() } catch(Exception e) { e.printStackTrace(); } } }
我们通过这个非常简单的例子向大家展示了 DOM API 的 10 个重要的操作。通过这些操作,我们说明了如何在已知 DTD 时进行查找、浏览、遍历元素以及获得元素及其属性值。这将为学习其它 DOM API 打下坚实的基础。
资源
XML 语法分析器及 DOM 实现 假如您想用 DOM API 编写 Java 代码,就需要一个 DOM 的实现,也就是一个语法分析器。幸运的是,现在已经可以找到一些了。这里有一些相关的资源:
Apache Xerces XML Parser IBM's XML Parser for Java Oracle (要访问 Oracle Technology Network,您必须成为其会员。注册是免费的。) Sun's Java Project X Xbeans Xbeans 是一个开放源代码的 Java Beans 知识库,使用最一般的方法来处理 DOM 文档。通过构造 Xbeans,可以创建分布式应用程序来处理 XML。这里是通用DOM 代码的极佳来源。 jGuru XML FAQ 国际出版通讯委员会 (International Press Telecommunications Council)是一个对数据交流中的 DTD 进行统一的标准化组织。 XML 规范 DOM 规范 CORBA IDL 关于作者 BrUCe Martin 是分布式对象计算领域的一位带头人。90 年代初期,他在惠普实验室设计并实现了一种接口定义语言,它后来成为惠普最初的 CORBA 子项目的基础。在 Sun 微系统公司,他是 Sun 的 CORBA 体系结构设计者之一,同时还是五项 OMG 的 CORBA 服务规范的制定者。在 Inprise 公司,Bruce 是该公司第一个以 CORBA 为基础的 Java 应用服务器的设计者和开发者。Bruce 具有关于 Java、XML 和 DOM 的渊博的实践经验。
现在,Bruce 已经成为 jGuru 的软件领袖。他正在致力于维护 xbeans.org(一个开放源代码计划),以创建一个用来处理 XML 并且能够很轻易地融入分布式应用的 Java Beans 的知识库。
Bruce 在加利福尼亚大学圣地亚哥分校获得了计算机科学硕士和博士学位,此前他在位于加利福尼亚大学伯克利分校获得了计算机科学学士学位。