王朝网络
分享
 
 
 

Zeus实现XML-JAVA的数据绑定

王朝java/jsp·作者佚名  2006-12-16
宽屏版  字体: |||超大  

内容:

ZEUS 简介

预备知识

编译你的Zeus

生成描述XML的Java对象

Marshal与Unmarshal--XML与JAVA Object的转换

选择Zeus的理由与思考

参考资料

关于作者

钟家豪 (judson78@yahoo.com.cn)

2003 年 3 月

Zeus可以将JAVA对象与XML文件进行绑定,绑定使数据在J2EE中的应用更加方便。本文主要介绍Zeus的编译与使用。对绑定过程中使用的DTD和XML文件也有说明。

1 ZEUS简介

Enhydra是以生长于美国加利福尼亚海边的小水獭命名的非营利组织的名字。从但与著名的Apache不同,Enhydra致力于围绕Application Server的电子商务解决方案的研究。Zeus就是Enhydra开发的众多的工具软件中的一个,功能是对JavaObject和XML进行数据绑定。它可以将任意的XML文件转化为对应的JavaObject文件,并且将数据方便的在这两种形式之间转换。Zeus最新版本是Zeus1.0 Beta 3.5,由于是完全的源码开放,可以到 http://zeus.enhydra.org/software/downloads/index.html 下载源代码后自己编译。

2 预备知识

2.1 用XML作为数据载体

XML(Extensible Markup Language)由W3C组织制定并得到世界上几乎所有大公司的支持。XML是一种非常灵活的文本格式,与HTML相比,XML延续了其简单、易懂的语法,但是却有了更大的灵活性和扩展能力。例1是一段描述Customer信息的XML文件,作为描述数据的语言,XML的组织形式很自由且表述清晰。

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

<Customer Customer_No= "00001">

< Name>李俊</ Name>

<Id_No>210106421016001</Id_No>

<Sex >男</Sex>

<Birth_Place>大连</Birth_Place>

<Birth_Date>1942-10-16</Birth_Date>

<Nationality>中国</Nationality>

<Education>高中</Education>

<Address>大连市沙河口</Address>

<Contact_Info Id = "00001">

<Zip_Code>116001</Zip_Code>

<Tel_No>2645677</Tel_No>

</Contact_Info>

</Customer>

例1:描述Customer的XML文件

这段XML结构很清晰:描述的是一个"顾客"实体,这个实体有其属性:姓名、身份证号、性别、出生地、生日、出生地、联系方式(邮编、电话)等。

第一行<?xml version="1.0" encoding="GBK"?>表述此XML文件的版本是1.0,用的是"GBK"的编码方式(如果要解析中文,GBK或GB2312是必须的)。<Customer Customer_No= "00001></Customer>组成该文件完整的"根标记",Customer_No是Customer标记的"属性",<Name></Name>、<Nationality></Nationality>是<Customer>的子标记。而在< Contact></Contact>中还可以继续包含子标记:<Zip_Code>、<Tel_No>。用户自定义tag的XML语言给了用户足够的自由度表示数据,但是也为显示和解析带来了难度,为了解决这一问题,W3C在格式控制和标记定义上对XML加以限制。例如<customer></Customer>就是一对不合格的标记。

2.2 DTD定义数据

DTD(Document Type Definition)目的是定义XML文档中的元素和各元素间的关系。DTD可以与应用它的XML共存在一个文件中,也可以单独成为一个文件。例2是一个描述例1所述的xml文件的DTD文件。

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

<!ELEMENT Customer (Name?,Id_No?,Sex?,Birth_Place?,Birth_Date?,Nationality?, Education?, Contact_Info?>

<!ATTLIST Customer

Customer_No CDATA #REQUIRED

>

<!ELEMENT Name (#PCDATA)>

<!ELEMENT Id_No (#PCDATA)>

<!ELEMENT Sex (#PCDATA)>

<!ELEMENT Birth_Place (#PCDATA)>

<!ELEMENT Birth_Date (#PCDATA)>

<!ELEMENT Nationality (#PCDATA)>

<!ELEMENT Education (#PCDATA)>

<!ELEMENT Contact_Info (Zip_Code?,Tel_No?)>

<!ATTLIST Contact_Info

id CDATA #REQUIRED

>

<!ELEMENT Zip_Code (#PCDATA)>

<!ELEMENT Tel_No (#PCDATA)>

例2:DTD文件

无规矩不成方圆,例2的DTD文件定义了例1的XML描述的Customer元素,通过DTD的定义,XML中的标记都被赋予了意义,并且很好的解释了Customer与其它元素之间的关系。DTD文件的存在使XML中的数据有了规定的形式,二者由如此紧密地联系容易联想到另外一种重要的数据组织方式--数据库的表中的字段和数据。DTD-XML这种与表结构-数据类似的结构为这两种技术的相互转换提供了天然的方便条件,借助于DTD,可以方便的将表中的数据用XML表示。

3 编译你的Zeus

下载下来的Zeus是一个zip文件,如果选择的是源代码下载,就必须首先编译才能够使用。本文介绍zeus的使用,首先从源代码的编译说起。

编译的方法在下载的docs文件夹中有详尽的描述,作为Java技术阵营的一份子,Zeus在将自己完全奉献的同时也使用了其他的一些杰出的Java工具。比如编译就使用了Apache的Ant。可以在Zeuslib下找到Ant.jar文件。

在编译之前唯一要做的事就是设定好操作系统的JAVA_HOME环境变量。例如在windows系统,如果jdk安装在D:/jdk1.3.1,则运行set JAVA_HOME = D:/jdk1.3.1。完成了准备工作就可以开始编译zeus,Ant本身是易于使用的编译工具,build.xml文件可以设定所有编译的细节和文件的组装。Zeus的编译文件位于根目录下的build.xml,这个XML文件包含了对Zeus编译并组装zeus.jar文件的一切细节而且有很高的可读性。

确定在zeus的根目录下,运行./bin/build.bat targets,Ant可以找到位于当前目录下的build.xml文件,如果不输入任何参数,ant会输出提示要你输入编译targets:

compile:编译zeus的所有源代码,并将之放置于buildclasses下;

bin:将原srcin下的文件拷到buildin下,原lib目录下的jar文件拷到buildlib下并将组合好的zeus.jar置于此文件夹下;

doc:编译javadoc,并将结果拷到bindocsapidoc下。

sample和test分别用于编译例程和测试代码。如果不想一步一步编译,可以将targers参数设为all,这样ant就会以正确的次序为你自动编译好所有的targets。编译后的会出现一个build文件夹,所有编译好的文件都在这个文件中。检查build/bin文件夹,出现的Zeus.jar文件就是编译好的工具。如果你有足够的经验去修改Zeus的源代码和build.xml文件,完全可以打造属于你自己的Zeus。

4 生成描述XML的Java对象

生成Java对象的第一步是使用Zeus自动生成Java源代码。使用zeus的批处理文件在buildin的zeus.bat,使用语法如下:

zeus.bat -constraints=

[-outputDir=]

[-collapseSimpleElements=]

[-ignoreIDAttributes=]

[-javaPackage=]

[-root=]

参数解释如下:

参数 必须 默认值 描 述

Constraints Yes 无 指定产生java代码的约束文件(dtd或xsd.文件)

OutputDir No 当前目录 放置生成java文件的根目录

CollapseSimpleElements No False 是否支持简单元素的精简,所谓"简单元素"就是在DTD文件中描述的没有属性(attribute)的元素(Element)。如果这样的简单元素以"精简"形式被Zeus解析,则生成的Java类使用其父元素的get[ElementName]()的形式来得到XML中该元素的值,这种形式比普通的get[ElementName]().getContent()的形式更简便。而且减少了很多不必要的生成类。

IgnoreIDAttributes No False 此参数设定判断"简单元素"的条件:是否将ID属性作为条件。设定此参数为true会导致那些只有一个"id"属性的元素被看作是"简单元素"

JavaPackage No 无 指定生成的java类的包。例如:指定com.zjh.tools后,所有生成的java类都在com.zjh.tools包内。

Root No 由DTD解析器决定 确定用于解析的根元素。解析有多个顶级元素的DTD文件时,指定根元素使之生成正确的java类。

继续上面的例子,将例1的XML文件与Java Objects绑定,第一步要生成Java文件,具体方案就是使用Zeus.jar中的org.enhydra.zeus.util.DTDSourceGenerator,例2中的Customer.dtd文件作为必须的constrains参数。首先执行下列命令:

将Customer文件置于c:zeusdtd文件下,建立c:zeuszjhsample,执行下列命令:

C:zeus>.uildinzeus.bat -constraints=dtdCustomer.dtd -outputDir=zjhsample -javaPackage =com.zjh.zeustest.binding -collapseSimpleElements=true

查看c:zeuszjhsamplecomzjhzeustestinding文件夹,发现生成了六个文件:Customer.java、CustomerImpl.java、Contact_Info.java、Contact_InfoImpl.java、CustomerUnmarshaller.java、Unmarshallable.java。

生成的类名有规可循:Customer、Contact_info是DTD文件中非简单元素的名称,Zeus生成与其同名的接口;CustomerImpl、Contact_infoImpl是实现这两个接口的类。CustomerUnmarshaller与Unmarshallable看起来有些奇怪,但也不是凭空而来:Unmarshallable接口继承自org.xml.sax.ContentHandler,提供解析XML合法性的接口,所有的ElementImpl类都要继承该接口;CustomerUnmarshaller提供反解码XML的接口,将XML文件输入,返回Customer对象。

数据绑定的所有秘密都隐藏在这几个文件中,可以用任何的文本编辑器对其进行编辑。但是就像程序声明所述:修改这些程序也许会导致数据绑定操作的失败。

最后编译这六个java文件:javac *.java,生成class文件。这样,就得到了用于描述XML文件的Java类。

5 Marshal与Unmarshal--XML与JAVA Object的转换

通用的XML文件适合不同技术平台之间的数据传输,Java对象可以为Java程序提供更加方便的使用接口,通过Zeus工具生成的Java Object就像是一座桥梁,将二者紧密地联系在一起(见图1)。它不仅在内部构建了足够的用来描述XML文件各个元素值的属性,更提供了可以将Java对象与XML文件相互转化的接口:Unmarshal和Marshal。

Unmarshal:将XML文件"反解码"为JavaObject;

Marshal:将JavaObject"解码"为XML文件。

图1:Java对象与XML文件的转换

5.1 Unmarshal XML文件到Java对象

一旦用Zeus生成的Java对象被编译,将XML文件转化为Java形式的表述就变成了一件简单且惬意的事。这一过程被描述为"反解码(Unmarshal)",其实它是Zeus根据DTD文件生成的ElementImp对象的Unmarshal()方法。如同科幻小说中的物品自动制造机,向Unmarshal方法投入以Java File、Writer、或InputStream形式包装的XML文件,一按Unmarshal按钮,XML数据的Java表示版就轻而易举的诞生了。示例程序(例3)中的CustomerUnmarshal类完成了Unmarshal例1中customerInfo.xml的工作,并把结果输出到屏幕上。

package com.zjh.zeustest;

import java.io.*;

import com.zjh.zeustest.binding.*;

public class CustomerInfo {

public static void main(String[] args) {

if(args.length!=1){

System.out.println("please in put the location of XML file");

return;

}

try{

Customer customer = CustomerUnmarshaller.unmarshal((new File(args[0])),false);

System.out.println("姓名:"+customer.getName());

System.out.println("证件号码:"+customer.getId_No());

System.out.println("性别:"+customer.getSex());

System.out.println("出生地:"+customer.getBirth_Place());

System.out.println("国籍:"+customer.getNationality());

System.out.println("学历:"+customer.getEducation());

System.out.println("邮政编码:"+customer.getContact_Info().getZip_Code());

System.out.println("电话号码:"+customer.getContact_Info().getTel_No());

}catch(Exception e){

e.printStackTrace();

}

}

}

例3 Unmarshal XML

编译该程序后用下列命令运行:

java -classpath .;..libxerces.jar com.zjh.zeustest.Customer Unmarshal ..cust.xml

输入如下:

姓名:李俊

证件号码:210106421016001

性别:男

出生地:大连

国籍:中 国

学历:高 中

邮政编码:116001

电话号码:2645677

5.2 Marshal Java对象到XML文件

把数据从Java Object的形式转换为XML文件是Unmarshal的逆过程,在语义上用的也是Marshal(解码)这一名词。下面提供的例子(例4)提供一个数据绑定使用完整的例子:

将Cust.xml读入

Unmarshal XML

修改Java对象的属性值

Marshal Java对象

package com.zjh.zeustest;

import java.io.*;

import com.zjh.zeustest.binding.*;

public class CustomerMarshal {

public static void main(String[] args) {

if(args.length!=1){

System.out.println("please in put the location of XML file");

return;

}

try{

Customer customer = CustomerUnmarshaller.unmarshal((new File(args[0])),false);

Contact_Info contactInfo = customer.getContact_Info();

contactInfo.setId("0002");

contactInfo.setZip_Code("116001");

contactInfo.setTel_No("6656456");

customer.setBirth_Date("1979-10-1");

customer.setBirth_Place("大连");

customer.setContact_Info(contactInfo);

customer.setCustomer_No("1234566");

customer.setEducation("大学");

customer.setId_No("210204197910012233");

customer.setName("李明");

customer.setNationality("中国");

customer.setSex("男");

customer.marshal((new File("MarshalCust.xml")));

}catch(Exception e){

e.printStackTrace();

}

}

}

例4 Marshal JavaObject

执行该程序后生成的新的MarshalCust.xml如下所示:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE Customer SYSTEM "D:zeusdtdCustomer.dtd">

<Customer Customer_No="1234566">

<Name>李明</Name>

<Id_No>210204197910012233</Id_No>

<Sex>男</Sex>

<Birth_Place>大连</Birth_Place>

<Birth_Date>1979-10-1</Birth_Date>

<Nationality>中国</Nationality>

<Education>大学</Education>

<Contact_Info id="0002">

<Zip_Code>116001</Zip_Code>

<Tel_No>6656456</Tel_No>

</Contact_Info>

</Customer>

选择Zeus的理由与思考:

Java与XML是一对天生的兄弟,在所有计算机软件技术都高举XML大旗的时候,有一万个理由实现Java与XML的完美结合。Sun、Apache也提供了功能强大XML解析包,站在巨人的肩膀上(实际上Zeus使用了Apache的Xerces来解析XML),Zeus提出的是数据绑定的概念。

从解析到绑定不需要很复杂的实现手法,但却提供给使用者更加简单和灵活的解决方案。编程技术的发展和开放软件的出现为创意提供了更广阔的空间,选择Zeus,使用Zeus,思考Zeus--没有复杂的技术,只有令人赞叹的创意。这也许就是后软件时代程序生存的真谛,我想。

关于作者

钟家豪,目前在中国广东从事金融领域的软件开发,主要致力于J2EE架构、XML、WebService和数据库方面的研究。可以通过 judson78@yahoo.com.cn 与他联系。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
>>返回首页<<
推荐阅读
 
 
频道精选
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
© 2005- 王朝网络 版权所有