分类 标签 存档 ME! 黑客派 订阅 搜索

使用 JAXB 处理 XML 文档——先睹为快

152 浏览

JAXB 以其方便的 XML 数据处理能力可能会引起你的兴趣。你可能还不了解 JAXB 是什么,想要知道它到底有
什么好处,如果这是你需要的,你才会再花时间去细细的研究它,或者你只需要使用最基本的功能。然而 Sun 关于 JAXB 的文档有 80 页之多。我想大部分人都
没有耐心看完这样的长篇大论。本文以简短的篇幅介绍了 JAXB 的基本使用,算是先睹为快吧。本文附带的代码包括了 JAXB1.0 early
access 版本和本文所使用的代码。欢迎与我讨论: mailto:boyofjava@sina.com

 

本文假设你会使用 Java 编程,了解并能够看懂 XML,DTD。

 

1 为什么要使用 JAXB


Java 中处理 XML 数据的常规方法有 SAX,DOM 等。其中 SAX 使用起来很麻烦,不能修改 XML 数据;而 DOM 的处理大文档速度非常的慢,易用性也不
必 SAX 好到哪里去。实际上,无论是 SAX 还是 DOM 都不是专门为 Java 准备的,它们都是访问 XML 文档的统一底层接口,与语言无关。

现在我们有了另外的选择。这就是 JAXB 和 JDOM。JDOM 与本文无关,目前最新的版本是 beta8,感兴趣的话,可以访问http://www.jdom.org/。

JAXB
的全名是 Java ? Architecture for XML Binding,目前是 1.0 的 early
access 版本,在 Sun 的 Java 站点只有注册为成员才能够下载。JAXB 的特点就是将你用 DTD 定义好的 XML 文档映射为 Java 对象,提供简单、
快速的数据操作方式。要访问 XML 中的元素、属性只要通过相应对象上的一系列 getter 和 setter 方法。你还可以通过 marshal 方法将对象的
数据写进 XML 文件,通过 unmarshal 方法将 XML 文件的数据读入对象,通过 validate 方法验证 XML 文件是否符合 DTD 的约束。JAXB 的
缺点就在于只能访问特定的(也就是你用 DTD 定义的)XML 文档。

 

2 JAXB如何工作

JAXB
包括了一个运行类库和一个模式编译器。首先你要定义 XML 的 DTD,然后编写一个绑定模式(Binding
Schema)。DTD 定义了 XML 文档,绑定模式也是一个 XML 文件,指出 DTD 定义的 XML 文档如何被映射为 Java 对象。运行编译器,将 DTD 和绑
定模式作为参数传给编译器,编译器就会生成 Java 代码。编译生成的 Java 代码,通过这些代码就可以访问 XML 文档了。

 

3 JAXB的安装

以 1.0
early
access 为例,它不包含在 JDK 中,先到http://java.sun.com/xml 下载。注意由于是早期版本,需要先登录才能下载,本文附带的
源码包含了 JAXB1.0 early
access。下载后将文件解压缩,在 lib 目录中有两个文件。jaxb-rt-1.0-ea.jar 是运行支持库,jaxb-xjc-1.0-
ea.jar 是模式编译器。注意 bin 目录中的 xjc 文件只能在 UNIX 下使用,如果你的系统是 Windows,那么你需要在命令行窗口手工输入命令来编
译。为了在任何地方都可以运行模式编译器和它生成的代码,我们要把这两的文件加入 CLASSPATH。一个简单的办法是把这两个文件拷贝到 jre/lib
/ext 下。

 

4 一个简单的例子

有这样一个 XML 文档。它描述书的列表,举例如下:

文件 exampleA.xml

   

        Java 编程入门

        张三

        2002-6-6

        35.0

   

   

        XML 在 Java 中的应用

        李四

        2002-9-16

        92.0

   

 

其 DTD 文件如下:

文件 bookList.dtd

>

 

现在我们就来编写一个最简单的绑定模式,其文件扩展名应该为 xjs。

文件 bookList.xjs

   

 

现在就可以运行模式编译器生成 Java 代码,请先保证 CLASSPATH 中包含了 JAXB 的两个 JAR 文件。Windows 用户注意 bin 目录下的那个文件是没用的。在命令行运行:

java com.sun.tools.xjc.Main bookList.dtd bookList.xjs

如果没出问题,编译器就生成了 Book.java,BookList.java 两个文件。你不用去理解这两个源文件里面的代码,只要知道怎么使用它们提供的方法就可以了。它们的继承结构都是这样的:

java.lang.Object

   javax.xml.bind.ValidatableObject

      javax.xml.bind.MarshallableObject

         javax.xml.bind.MarshallableRootElement

                BookList or Book

 

BookList.java 主要包含了以下方法

BookList()    // 构造函数

List getBook()    // 得到书的集合,List 中的对象实际类型是 Book,可以添加、修改、删除其中的元素

void deleteBook()   // 删除集合

void emptyBook()    // 删除并生成一个新的空集合

void marshal(X)      // 将数据写进 XML 文档

void unmarshal(X)   // 将数据从 XML 文档读入对象

void validate(X)    // 检查是否符合 DTD 约束,同时检查子树。在这个例子中就是 BookList 的 Book 集合

void validateThis()   // 检查是否符合 DTD 约束,不检查子树

其中 marshal,unmarshal,validate 被重载,有多种参数形式(可以参考 JAXB 的 API 文档)。

 

 

Book.java 主要包含了以下方法

Book()

String getName()

String getAuthor()

String getPublishDate()

String getPrice()

void setName(String x)

void setAuthor(String x)

void setPublishDate(String x)

void setPrice(String x)

void marshal()

void unmarshal()

void validate()

现在我们就可以使用这两个文件访问 XML 了。首先编
译这两个文件。编写一个 Test.java 文件,把它和生成的两个文件以及前面的 exampleA.xml 放在一起。这个程序从
exampleA.xml 读入数据,作修改(把第一本书作者改成王五)后写入 exampleB.xml。因为中文的编码问题,所以我们需要多一点手续。

文件 Test.java

import java.io.;

import java.util.;

import javax.xml.bind.;

import javax.xml.marshal.*;

public class Test{

       public static void main(String[] args) throws Exception{

        BookList bl = new BookList();

        FileInputStream fis = new FileInputStream("exampleA.xml");

        try{

            bl = bl.unmarshal(fis);

        }finally{

            fis.close();

        }

        List books = bl.getBook();

        Book b = (Book)books.get(0);

        b.setAuthor(" 王五");

 

        bl.validate();  // 先验证,不然 marshal 会出错

        FileOutputStream fos = new FileOutputStream("exampleB.xml");

        XMLWriter xw = new XMLWriter(fos,"GBK");

        try{

            bl.marshal(xw);

        }finally{

            fos.close();

        }

       }

}

 

编译运行,生成的文件 exampleB.xml 如下:

 

 

    Java 编程入门

    王五

    2002-6-6

    35.0

 

    XML 在 Java 中的应用

    李四

    2002-9-16

92.0

 

5 更进一步:数据类型转换


可能已经注意到在上面的例子中,生成的 Book 对象的 getPrice 方法返回的是 String,实际上它应该是 float。同样 publishDate
以该是日期类型,而不是字符串。这是因为我们的绑定模式写得太简单了,模式编译器生成了默认的 String 类型。现在我们这样写:

文件 bookList2.xjs

   

   

   

   

            parse="TransDate.parseDate" print="TransDate.printDate"/>

 

用 java com.sun.tools.xjc.Main bookList.dtd bookList2.xjs 运行编译器。生成的 Book 文件的相应代码为:

float getPrice()

java.util.Date getPublishDate()

 

bookList2.xjs
第 3 行将 Price 转换成了 float 类型,float 类型是一个简单类型,因此用 convert="float" 描述就可以了。而
publishDate 需要转变成 java.util.Date,这是一个类,而且他没有以字符串作为参数的构造函数。
parse="TransDate.parseDate" 就表示使用 unmarshal 读取数据的时候,会调用
TransDate.parseDate() 方法。这个静态方法以字符串为参数,返回 java.util.date。
print="TransDate.printDate" 的作用相反。TransDate 这个类需要我们提供。

文件 TransDate.java

import java.util.Date;

public class TransDate {

    private static java.text.SimpleDateFormat df

           = new java.text.SimpleDateFormat("yyyy-MM-dd");

 

    public static Date parseDate(String d) {

           try {

               return df.parse(d);

          } catch (java.text.ParseException pe) {

               System.out.print(pe);

               return new Date();

           }

    }

 

    public static String printDate(Date d) {

           return df.format(d);

    }

}

 

6 那些使 JAXB能够做到,但本文没有提到的

本文提供的这个例子很简单,实际上 JAXB 还可以定义文档的哪些元素(属性)可以被转换成类,哪些被转换成类的属性。处理元素的属性。处理枚举值。为一些元素共同的子元素生成接口(因为 JAXB 不支持 NameSpace),定义继承结构等等。


7 JAXB不能做到的

Sun 的文档里提到的:

仅支持用 DTD 定义 XML

不支持 NameSpace

不支持内部子集、NOTATIONs、ENTITY、ENTITIES 等。

 

另外,我发现如果要写一条处理指令到 XML 文档中,例如指定转换的样式单


JAXB 中好像做不到,在 javax.xml.marshal.XMLWriter 中有一个 chars(String
str) 方法,可以把字符串到 XML 文件的声明后面,但是这个方法对特殊字符作了转义,也就是没办法可以做到。这很奇怪,因为这是一个常用的功能,要实现
也不难。也许还有我没有发现的办法。倒是有一个 doctype 方法可以写 DOCTYPE 声明。

 

8 参考文档

1 The Java ? Architecture for XML Binding User’s Guide

 (http://java.sun.com/xml/jaxb/jaxb-docs.pdf)

2
Web Services Made Easier. The Java TM APIs and Architectures for XML, A
Technical White Paper (http://java.sun.com/xml/webservices.pdf )



转自:http://www.cn-teacher.com/fuwu/dn/bcjs/javajc/200704/192483_5.html

 


欢迎注册黑客派社区,开启你的博客之旅。让学习和分享成为一种习惯!

评论  
留下你的脚步
推荐阅读