帝国软件
  设为首页 加入收藏 关于我们
 
解密帝国网站管理系统
栏 目:
 
您的位置:首页 > 技术文档 > JAVA编程
使用Quick在Java对象和XML之间进行转换
作者:未知 发布时间:2005-03-12 来源:JSP天空网
将 Java 对象与 XML 数据集成
级别:中级


Brett McLaughlin(brett@oreilly.com)
作家兼编辑,O´Reilly and Associates
2002 年 8 月

Quick 是一种开放源码数据绑定框架,着重于运行时转换。这篇介绍性文章向您演示了如何使用这种框架来快速且方便地将您的 Java 数据转换成 XML 文档,而无需其它数据绑定框架所需的类生成语义。本文还包括了大量的代码样本。
近几年来,XML 的确给编程世界带来了巨大冲击。然而,XML 应用程序的复杂性(从一开始就很复杂)在最近几年中并没有减少多少。开发人员仍要花几个星期的时间(即使不是几个月)来学习复杂的 XML 语义和 API(如 SAX 和 DOM)来操作 XML。然而,在过去的 6 个月到 12 个月中,相对于那些较复杂的 API,另一种新的比较简单的 XML API(称为 Quick)已经越来越受到欢迎。

数据绑定允许您直接在 Java 对象和 XML 之间映射,而不必处理 XML 属性和元素。另外,它允许 Java 开发人员使用 XML,而无需花时间去钻研 XML 规范。Quick 是这样一种数据绑定 API,它是使 Java 应用程序适合业务用途的项目。

安装与设置
在钻研使用 Quick 的细节之前,您需要下载和安装该项目。请访问 Quick 的网站(请参阅参考资料),然后选择 Download。然后,您可以下载该项目的 .zip 文件;在我写本文时,最新的可用版本是 Quick 4.3.1,可通过 Quick4.3.1.zip 文件得到。

解压缩 .zip 文件以创建 Quick 分发版(distribution)。清单 1 显示了目录层次结构:

清单 1. Quick 目录结构
Quick4
|
+-- JARs
+-- BATs
+-- Doc
+-- dtdParserSrc
+-- DTDs
+-- examples
+-- JARs
+-- QDMLs
+-- QJMLs
+-- quickSrc
+-- UTILs
+-- utilSrc
+-- XSLs




开发人员最关注的两个目录是 Quick4/BATs(它应该被添加到 PATH 环境变量)和 Quick4/JARs(它包含应该被添加到 CLASSPATH 环境变量的 jar 文件)。明确地讲,您需要将 dtdparser115.jar、Quick4rt.jar 和 Quick4util.jar 添加到当前类路径中。您还需要一个 SAX 解析器实现,如 Apache 项目的 Xerces-J(请参阅参考资料)。同样,将 xerces.jar 或您自己喜爱的解析器添加到类路径中。

Java 类和 XML 文档
数据绑定将集中于 XML 和 Java,所以让我们研究如何把这些 XML 文档和 Java 类与 Quick 联系起来。为了说明这些问题,让我们研究几个简单的 Java 类和一个简单的 XML 文档。

简单的 XML 文档
首先,清单 2 显示了一个小的 XML 文档。我已经使事情简单化,因此您读完 10 个或 15 个 Java 类之后,不会不理解概念。

清单 2. 表示一个人的 XML
<?xml version="1.0"?>
<!DOCTYPE person SYSTEM "person.dtd">
<person>
<firstName>Gary</firstName>
<lastName>Greathouse</lastName>
<address type="home">
<street>10012 Townhouse Drive</street>
<city>Waco</city>
<state>TX</state>
<zipCode>76713</zipCode>
</address>
<phoneNumber>
<type>home</type>
<number>2545550287</number>
</phoneNumber>
<phoneNumber>
<type>work</type>
<number>2545556127</number>
</phoneNumber>
</person>




虽然清单 2 不是有关如何编写 XML 的主要示例,但其中有几个关于 Quick 的要点值得注意。您还需要研究清单 3 中所示文档的 DTD。

清单 3. person.xml 的 DTD
<!ELEMENT person (firstName, lastName, address+, phoneNumber+)>

<!ELEMENT firstName (#PCDATA)>
<!ELEMENT lastName (#PCDATA)>

<!ELEMENT address (street, city, state, zipCode)>
<!ATTLIST address
type (home | work | other) "home"
>

<!ELEMENT street (#PCDATA)>
<!ELEMENT city (#PCDATA)>
<!ELEMENT state (#PCDATA)>
<!ELEMENT zipCode (#PCDATA)>

<!ELEMENT phoneNumber (type, number)>
<!ELEMENT type (#PCDATA)>
<!ELEMENT number (#PCDATA)>




Java 类
在许多数据绑定实现中,您现在需要生成 Java 源文件来表示这种类型的 XML 文档。那种类型的实现假设(通常都不是真的)您缺少要使用的 Java 业务对象。更常见的是,您有一组要开始持久存储 XML 的 Java 类。这个用例正是 Quick 所能帮助解决的问题。根据这个用例,清单 4、5 和 6 是三个代表某人的 Java 源文件。

清单 4. Person 类
import java.util.LinkedList;
import java.util.List;

public class Person {

/** The first name of the person */
private String firstName;

/** The last name of the person */
private String lastName;

/** The addresses of the person */
private List addressList;

/** The phone numbers of the person */
private List phoneNumberList;

public Person() {
addressList = new LinkedList();
phoneNumberList = new LinkedList();
}

public Person(String firstName, String lastName,
List addressList, List phoneNumberList) {

this.firstName = firstName;
this.lastName = lastName;
this.addressList = addressList;
this.phoneNumberList = phoneNumberList;
}

public String getFirstName() {
return firstName;
}

public void setFirstName(String firstName) {
this.firstName = firstName;
}

public String getLastName() {
return lastName;
}

public void setLastName(String lastName) {
this.lastName = lastName;
}

public List getAddressList() {
return addressList;
}

public void setAddressList(List addressList) {
this.addressList = addressList;
}

public void addAddress(Address address) {
addressList.add(address);
}

public List getPhoneNumberList() {
return phoneNumberList;
}

public void setPhoneNumberList(List phoneNumberList) {
this.phoneNumberList = phoneNumberList;
}

public void addPhoneNumber(PhoneNumber phoneNumber) {
phoneNumberList.add(phoneNumber);
}
}




清单 5. Address 类
public class Address {

/** The type of address */
private String type;

/** The street address */
private String street;

/** The city */
private String city;

/** The state */
private String state;

/** The zip code */
private String zipCode;

public Address() { }

public Address(String type, String street, String city,
String state, String zipCode) {

this.type = type;
this.street = street;
this.city = city;
this.state = state;
this.zipCode = zipCode;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}

public String getStreet() {
return street;
}

public void setStreet(String street) {
this.street = street;
}

public String getCity() {
return city;
}

public void setCity(String city) {
this.city = city;
}

public String getState() {
return state;
}

public void setState(String state) {
this.state = state;
}

public String getZipCode() {
return zipCode;
}

public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
}




清单 6. PhoneNumber 类
public class PhoneNumber {

/** The number itself */
private String number;

/** The type of number */
private String type;

public PhoneNumber() { }

public PhoneNumber(String type, String number) {
this.type = type;
this.number = number;
}

public String getNumber() {
return number;
}

public void setNumber(String number) {
this.number = number;
}

public String getType() {
return type;
}

public void setType(String type) {
this.type = type;
}
}




这些类相当简单明了。它们与您在清单 2 中看到的 XML 结构很类似。假设您要将 XML 文档转换成这些 Java 对象的实例,然后再转换回来。Quick 使这些转换成为一件轻松的事情。

初始化
一旦您有了一个 XML 文档(或多个文档)、DTD 和 Java 类,就需要告诉 Quick 框架如何将数据从一种格式映射到另一种格式。这是一个多步骤过程:

从 XML 文档的 DTD 创建 QDML 文件
从 QDML 文档创建 QJML 文件
从 QJML 文档创建 QIML 文件
使用 QIML 将 Java 映射到 XML 并再次映射回来
我将在接下来的几节中依次向您演示如何完成每一个步骤。虽然好象需要许多步骤来使 Quick 运行起来,但您应该注意到,其中的每一个步骤只需要执行一次,所以这是使用 Quick 框架要“预付”的。一旦您处理了这些步骤,就可以在应用程序中根据您的需要任意次数地使用 Quick,而无需再重复这个过程的开销。

创建 QDML
您需要让 Quick 准备做的第一件事情是创建 QDML 文件。QDML(Quick 文档标记语言(Quick Document Markup Language))本质上是 DTD 的 Quick 版本,它为 Quick 框架定义 XML 文档结构。此时,您没有提供任何映射信息;您只是以 Quick 可以理解的格式定义您的文档。当然,这是通过 Quick 工具完成的,这种工具使开发人员工作起来更方便。

首先,确保您的类路径如安装与设置中指示的那样设置。然后,可以使用 cfgDtd2Qdml 脚本,它位于 Quick 分发版的 BATs 目录中。对于 Windows 用户,使用 cfgDtd2Qdml.bat;对于 Unix 用户,使用 cfgDtd2Qdml.sh。(本文中的示例都是以 Unix 格式,但您可以在 Windows 上轻松地完成这些任务。)

发出下列命令:

sh cfgDtd2Qdml.sh -in=person.dtd -out=person.qdml


您不会看到有什么令人兴奋的输出,但应该得到一个名为 person.qdml 的新文件。现在,DTD 的格式更容易被 Quick 理解了,您就要准备继续下一步了。

在继续之前,需要让 Quick(和它使用的 QDML 文件)知道 XML 文档的根元素。在该例中,它是 person 元素。要做到这一点,使用另一个 Quick 实用程序:

sh cfgSetQdmlRoot.sh -in=person.qdml -out=person.qdml -root=person


创建 QJML
现在,需要创建一个 QJML 文件,以供 Quick 使用。QJML 是 Quick Java 标记语言(Quick Java Markup Language),与绑定模式等价,它是为那些熟悉 JAXB 或其它数据绑定实现的人而准备的。Quick 使用 QJML 将 XML 文件中的构造转换成它们对应的 Java 构造,反之亦然。

我们也可以从头创建 QJML 文件;然而,Quick 提供了自动生成 QJML 文件的工具,通常您只需做一些极小的更改。出于这个原因,这是推荐使用的方法。使用 cfgQdml2Qjml.bat 或 cfgQdml2Qjml.sh 脚本来完成它,并将最新生成的 QDML 文件作为输入提供(Quick 读取 QDML 来确定要映射的构造;现在明白为什么需要这个文件了吧?):

sh cfgQdml2Qjml.sh -in=person.qdml -out=person.qjml


您现在应该有了一个新文件 person.qjml。

正如我刚才说的那样,您将需要对该文件做一些更改,因为 Quick 对 Java 变量名做了一些有问题的假设。打开文件,添加粗体编码,使它看上去象清单 7 那样。

清单 7. 编辑 QJML
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE qjml SYSTEM "classpath:///qjml.dtd">
<qjml root="person">
<bean tag="person">
<targetClass>Person</targetClass>
<elements>
<item coin="firstName">
<property name="firstName"/>
</item>
<item coin="lastName">
<property name="lastName"/>
</item>
<item coin="address" repeating="True">
<property kind="list" name="addressList"/>
</item>
<item coin="phoneNumber" repeating="True">
<property kind="list" name="phoneNumberList"/>
</item>
</elements>
</bean>
<text tag="firstName"/>
<text tag="lastName"/>
<bean tag="address">
<targetClass>Address</targetClass>
<attributes>
<item coin="address.type" optional="True" value="home">
<property initializer="home" name="type"/>
</item>
</attributes>
<elements>
<item coin="street">
<property name="street"/>
</item>
<item coin="city">
<property name="city"/>
</item>
<item coin="state">
<property name="state"/>
</item>
<item coin="zipCode">
<property name="zipCode"/>
</item>
</elements>
</bean>
<text label="address.type" tag="type">
<enum value="home"/>
<enum value="work"/>
<enum value="other"/>
</text>
<text tag="street"/>
<text tag="city"/>
<text tag="state"/>
<text tag="zipCode"/>
<bean tag="phoneNumber">
<targetClass>PhoneNumber</targetClass>
<elements>
<item coin="type">
<property name="type"/>
</item>
<item coin="number">
<property name="number"/>
</item>
</elements>
</bean>
<text tag="type"/>
<text tag="number"/>
</qjml>




将原始文件与清单 7 中显示的文件相比,您应该看到这些更改相当明显;它们都涉及将 XML 特性映射成正确的 Java 特性名,如源代码中所定义的那样(请参阅清单 4、5 和 6 来复习一下)。

创建 QIML
您几乎已经完成了设置工作;但仍需要执行最后一步。Quick 使用 QIML(Quick 内部标记语言(Quick Internal Markup Language))文件可以执行得更好。顾名思义,Quick 使用该内部格式以避免 QJML 文件的运行时编译、转换和处理。执行下列简单步骤,使 QJML 成为 Quick 可以更方便使用的格式:

sh cfgQjml2Qiml.sh -in=person.qjml -out=person.qiml


最后,为进一步改进性能,将这个基于文本的格式转换成可以编译的 Java 源文件(使用二进制对象总是比使用未编译的文本文件格式好):

sh cfgQiml2Java.sh -in=person.qiml -out=PersonSchema.java
-class=PersonSchema -key=person.qjml


您真的不必对此处发生的事情太担心;它完全是特定于 Quick 的,实用程序会处理它们。现在,您应该编译这个创建的源文件(以及其余的 Java 源文件,如果还未创建的话)并确保将所有内容都添加到类路径中。这些步骤全部完成之后,您可以开始做一些数据绑定工作。

数据绑定
所有设置工作都完成之后,使用 Quick 框架将 XML 文档转换成 Java 字节码然后再转换回来的工作就很简单了。我将会使它的示例简单化;一旦您获得了基础知识,就可以得心应手地使用数据绑定,虽然我不知道您的用例,但我让您从样本代码中获取您所需要的信息并开始工作!请看一下清单 8,然后我将解释主要的概念。

清单 8. 在 Java 中使用 Quick
import java.util.Iterator;

// Quick imports
import com.jxml.quick.QDoc;
import com.jxml.quick.Quick;

public class PersonTest {

public static void main(String[] args) {
try {
if (args.length != 2) {
System.err.println("Usage: java PersonTest [input file] [output file]");
return;
}

// Initialize Quick
QDoc schema = PersonSchema.createSchema();

// Convert input XML to Java
QDoc doc = Quick.parse(schema, args[0]);

// Get the result
Person person = (Person)Quick.getRoot(doc);

// Output block
System.out.println(" --------------- Person ------------------ ");
System.out.println(" First Name: " + person.getFirstName());
System.out.println(" Last Name : " + person.getLastName());
for (Iterator i = person.getAddressList().iterator(); i.hasNext(); ) {
Address address = (Address)i.next();
System.out.println(" Address (" + address.getType() + "):");
System.out.println(" " + address.getStreet());
System.out.println(" " + address.getCity() + ", " + address.getState() +
" " + address.getZipCode());
}
for (Iterator i = person.getPhoneNumberList().iterator(); i.hasNext(); ) {
PhoneNumber number = (PhoneNumber)i.next();
System.out.println(" Phone Number (" + number.getType() + "):");
System.out.println(" " + number.getNumber());
}

// Add a new address
Address address =
new Address("work", "357 West Magnolia Lane", "Waco", "TX", "76710");
person.getAddressList().add(address);

// Change a phone number
PhoneNumber number = (PhoneNumber)person.getPhoneNumberList().get(1);
number.setNumber("2547176547");

// Write out modified XML
Quick.express(doc, args[1]);
} catch (Exception e) {
e.printStackTrace();
}
}
}



处理 Quick 的代码部分原来只有四行!必须先装入 QIML(已编译为 Java 字节码),以便让 Quick 知道哪些 XML 元素和属性变成哪些 Java 类和特性。通过生成的 PersonSchema 类的 createSchema() 方法(它是静态的)来完成这一任务。一旦装入该模式,就将它和输入文件传递给 Quick.parse() 方法,由该方法执行转换。从那里开始,您只需获取产生的 QDoc 的根元素并象使用任何其它 Java 对象那样使用它。在最后几行代码中再次用到了 Quick ,其中 express() 方法输出一个已修改的 XML 版本。非常简单,不是吗?

注: 不要为输入和输出提供相同文件名,因为这样会覆盖原始数据,并且会发生各种不可预料的事情。

结束语
很好,您已经在这里看到了一些真正能让您感兴趣的功能。首先,数据绑定通常可以使编程任务变得非常简单,特别是当您需要将数据持久存储到某种类型的静态存储器(如本文中所示的文件)中时更是如此。另外,Quick 为您在自己的项目中完成这一任务提供了一种快速、简单的方法。研究一下使用 Quick 的代码块,了解您是否喜欢它。希望您喜欢,希望能在网上与您见面。

参考资料

通过单击本文顶部或底部的讨论来参与本文的论坛。


获取本文的源代码以及 Quick 生成的文件和代码。


从 Quick Project 主页下载 Quick,该主页还包括其它下载和文档。


请参考 Apache XML Project XML,它提供了几种解析器和处理器,所有这些都是免费使用的。


请访问 Apache Xalan XSLT 处理器主页,在那里可以研究和下载 XSLT 处理器。


请在 developerWorks XML 技术专区上查找更多 XML 参考资料。


请了解一下 IBM WebSphere Studio Application Developer,这是一个易于使用的集成开发环境,用于构建、测试和部署 J2EE 应用程序,包括从 DTD 和模式生成 XML 文档。


了解如何成为一位 XML 和相关技术的 IBM 认证开发人员。

关于作者
Brett McLaughlin 自从流行 Logo 语言的时代起就一直从事计算机行业(记得小三角形吗?)。目前,他专门从事使用 Java 以及与 Java 相关的技术来构建应用程序基础结构的工作。最近几年,他在 Nextel Communications and Allegiance Telecom, Inc. 从事这些基础结构的实现。Brett 是 Java Apache 项目 Turbine 的共同创始人之一,该项目通过使用 Java servlet 为 Web 应用程序开发构建可重用组件体系结构。他还是 EJBoss 项目(一种开放源码 EJB 应用程序服务器)和 Cocoon(一种开放源码 XML Web 发布引擎)的贡献者之一。 
  
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关链接
 ·使用JavaServer Pages技术生成动  (2005-03-12)
 ·使用J2EE建立基于XML的网络服务  (2005-03-12)
 ·使用Java Swing 创建一个XML编辑  (2005-03-12)
 ·使用Java Swing 创建一个XML编辑  (2005-03-12)
 ·使用Java Swing 创建一个XML编辑  (2005-03-12)
 ·Java中的XML:使用Castor进行数据  (2005-03-12)
 ·使用 Jacl 脚本扩展 XML 工具  (2005-03-12)
 ·使用 XMLHTTPRequest 编程原文章  (2005-03-12)
 ·使用XML小服务程序配置文件配置小  (2005-03-12)
 ·使用JAXB处理XML文档??先睹为快  (2005-03-12)

   栏目导行
  PHP编程
  ASP编程
  ASP.NET编程
  JAVA编程
   站点最新
·致合作伙伴的欢迎信
·媒体报道
·帝国软件合作伙伴计划协议
·DiscuzX2.5会员整合通行证发布
·帝国CMS 7.0版本功能建议收集
·帝国网站管理系统2012年授权购买说
·PHPWind8.7会员整合通行证发布
·[官方插件]帝国CMS-访问统计插件
·[官方插件]帝国CMS-sitemap插件
·[官方插件]帝国CMS内容页评论AJAX分
   类别最新
·谈谈JDBC
·JDBC专题介绍
·JDBC接口技术
·利用weblogic的POOL(连接池)连接
·Jsp中调用Oracle存储过程的小例子
·JSP数据库操作例程
·JSP数据库连接大全
·用连接池提高Servlet访问数据库的效
·一种简单JDBC连接池的实现
·数据库连接池Java实现小结
 
关于帝国 | 广告服务 | 联系我们 | 程序开发 | 网站地图 | 留言板 帝国网站管理系统