XML与java文档格式.docx
- 文档编号:17069035
- 上传时间:2022-11-28
- 格式:DOCX
- 页数:58
- 大小:209.67KB
XML与java文档格式.docx
《XML与java文档格式.docx》由会员分享,可在线阅读,更多相关《XML与java文档格式.docx(58页珍藏版)》请在冰豆网上搜索。
去年,我写了一篇文章,讲述了如何使用Castor框架以进行Java对象到XML文档的映射数据绑定。
我曾经答应要写一篇后续文章,其中将探讨代码生成方法,包括介绍JAXB,JavaCommunityProcess(JCP)正在开发JAXB,它是用Java语言编写的、用于数据绑定的标准API。
就在较早的那篇文章发布不久,Sun宣布对JAXB的方向做出了重大调整(请参阅重新架构JAXB)。
由于这方面的变化,所以我想,为了更贴近最终的JAXB代码,最好先不写这篇后续文章,现在,我很高兴,终于可以写这篇文章了!
数据绑定字典
下面是一个微型字典,里面包含了我在本文中所使用的一些术语:
文法(Grammar)是用于定义一系列XML文档结构的一套规则。
其中一类文法是XML规范所定义的文档类型定义(DocumentTypeDefinition,DTD)格式。
另一类日渐普及的文法是XMLSchema规范所定义的W3CXMLSchema(Schema)格式。
文法定义了哪些元素和属性可以出现在文档中,以及在文档中元素是如何嵌套的(通常包括嵌套元素的次序和数目)。
一些类型的文法(譬如Schema)还可以更进一步,使字符数据内容与特定数据类型甚至正则表达式相匹配。
在本文中,我会常使用术语描述,将它作为引用一系列文档的文法的非正式方法。
编组(Marshalling)是在内存中为对象生成XML表示的过程。
与Java对象序列化一样,这种表示需要包含所有依赖的对象:
我们的主对象引用的对象、这些对象引用的对象等等。
数据分解(Unmarshalling)是与编组相反的过程,在内存中根据XML表示构建一个对象(而且可能是链接对象的图)。
在本文中,我将讨论根据XML文档文法生成Java语言代码的五种XML数据绑定框架:
JAXB、Castor、JBind、Quick和Zeus。
它们都可以免费获取,除了JAXB之外,其它四种框架都可以在开放源码和专利项目中使用。
当前JAXB参考实现beta测试版的许可证只允许用于评估,但当它作为产品发行时,这种情形很可能会改变。
JAXB、Castor和JBind都提供了根据XML文档的Schema描述生成代码,而Quick和Zeus根据DTD描述生成代码。
Castor和Quick还支持将现有类映射到XML,以此作为另一种生成代码的方法。
这些框架各有优缺点,所以我会试图逐步指出每种框架所具有的最佳(和最差)特性。
在第2部分,我将进一步向您显示这些框架如何对一些样本文档进行处理,另外,还将探讨,对于许多类型的应用程序,现有的数据绑定框架怎么会缺乏一些重要的特性。
相对于我在以前文章中所描述的映射绑定方法,根据Schema或DTD文法生成Java语言代码具有一些突出的优点。
使用生成的代码,您可以确定数据对象被正确地链接到XML文档,不象映射绑定方法,需要直接指定链接,并确保正确地涵盖了所有的结构变体。
在使用Schema时,甚至可以利用文法所提供的类型信息,用合适的数据类型来生成代码。
代码生成方法也有一些不足之处。
这种方法造成应用程序数据结构与XML文档结构之间紧密耦合。
另外,它还可能限定您使用简单的数据类(没有关联行为的被动数据容器),而不是真正的对象类,在编组和数据分解过程中,还可能限制应用数据的定制转换的灵活性。
在本文后面,我会权衡代码生成和映射绑定这两种方法(请参阅映射绑定vs.代码生成)。
回页首
数据和代码
对于将在第2部分中讨论的性能测试,我用每一种数据绑定框架来生成代码。
用于性能测试的文档包含模拟航班时刻表的信息。
下面是一个样本文档,您可以感受一下其中的结构:
清单1.样本文档
<
?
xmlversion="
1.0"
>
timetable>
<
carrierident="
AR"
rating>
9<
/rating>
URL>
/URL>
name>
ArcticAirlines<
/name>
/carrier>
CA"
7<
CombinedAirlines<
airportident="
SEA"
location>
Seattle,WA<
/location>
Seattle-TacomaInternationalAirport<
/airport>
LAX"
LosAngeles,CA<
LosAngelesInternationalAirport<
routefrom="
to="
flightcarrier="
number>
426<
/number>
depart>
6:
23a<
/depart>
arrive>
8:
42a<
/arrive>
/flight>
833<
10a<
10:
52a<
433<
9:
00a<
11:
36a<
/route>
311<
7:
45a<
20a<
593<
27a<
12:
04p<
102<
30p<
3:
07p<
/timetable>
图1显示了用于映射数据绑定到这些文档的类结构。
为了进行比较,我将在有关各个数据绑定框架章节中显示生成的类结构。
这里包含的这些图仅仅是所有情况的缩略图;
如果要看全图,请单击这个小图像。
图1.映射绑定类图(单击进行放大)
JAXB面前的漫漫长路
用于XML绑定的JavaAPI(JavaAPIforXMLBinding,JAXB)是一个处于不断发展中的Java平台数据绑定标准。
JavaCommunityProcess正在开发作为“JSR-31―XML数据绑定规范(XMLDataBindingSpecification)”的JAXB。
该项目始于1999年8月,其目的是定义一种方法,生成与XML结构相链接的Java语言代码。
最初打算在2000年第2季度发布,但最后在JavaOne2001上宣布了初步的EarlyAccess(EA)版本,该版本在2001年6月向公众发布。
JAXB的EA版本基于具有创新意义的拉解析器(pullparser)设计,这种设计使验证可以方便地构建到生成的数据分解代码中。
它根据DTD生成代码,构建在解析XML文档时自动验证XML文档结构(而不是数据)的类。
我们期望这种方法能快速和有效地处理XML和Java语言对象之间的转换,但EA代码仅仅是部分实现,显然在成为完整的实现之前,仍需要做大量工作。
专家组不久之后开始收到关于EA发行版的反馈。
作为对反馈意见的部分响应中,他们研究决定重新架构JAXB,之后更新了网站,声明JAXB在几个方面正在得到增强。
该站点还声明,下一版本在API级上不与早期版本兼容―但您仍然可以下载EA版本。
重新架构JAXB
直到2002年3月,新体系结构的细节才公布于众,在JavaOne上,Sun宣布,作为在JAXB方面进一步工作的基础,实际上正在放弃EA代码。
它将被新设计所替代,在新设计中,共享了一些常见的功能,但新设计使用不兼容的API和内部体系结构。
发展方向变化如此之大,让我和那些对EA代码有兴趣的人们感到惊讶。
JAXB项目的SUNJSR负责人JosephFialli把这么大的变化归结为以下一些因素。
主要问题是扩展原有代码库以支持W3CXMLSchema的复杂性。
这是一个相当复杂的规范,以至于在批准之后的两年多时间里,在所有平台上,仍然只有少数几个解析器能接近完全符合规范。
最初的JAXB代码需要实际对象来控制验证,而且将这种方法扩展到Schema将耗费太多精力,以至于在合理的期限内无法实现这项工作。
为适应Schema而做出变更的同时,专家组还决定重新考虑处理验证的方法。
原来的JAXB代码无条件地验证文档的结构,如果发现错误,则抛出异常并中止处理。
Fialli说,在公众的意见中,抱怨这种方法局限性太大、限制太严―在一些情况下,用户希望能够一次检查多个验证错误,而在另一些情况下,则希望完全禁用验证(或者由于性能原因,或者在编组没有精确匹配文法的文档时)。
新的JAXB体系结构能够满足这两种需求。
最后,专家组决定放弃单个绑定框架运行时(就象在原来EA发行版中所看的)的想法。
而采用接口方法,其实质是可以使用不同的数据绑定框架。
这使用户代码可以在各框架之间进行移植,而不需移植生成的类―这些类特定于专门的数据绑定框架,它们只能由该框架运行。
强制性的SAX2.0解析器支持替代了EA运行时中所使用的拉解析器方法,对于其它解析器(可能包括新的拉解析器,该解析器基于用于XML的流式API,JSR173正在定义此API),提供可选的特定于框架的支持,数据结构本身被更改为类JavaBean的数据对象,外部框架可以方便地操作此数据对象。
JAXBbeta测试版
自3月以来,JAXB项目一直在朝着这个新方向前进。
这一工作的第一个公开成果是,去年夏天发布了该规范的新草案(但草案仍处于准备阶段)。
接着在10月,Sun提供了JAXB参考实现新的beta测试版,最终它会替代过时已久的EA版本。
在这些文章中,我用这个最近的beta测试版进行评估和性能测试。
它直接根据Schema文档描述进行工作,生成与为文档所定义的元素类型和用法相匹配的类的层次结构。
该层次结构包括四种常规类型的类:
用于已定义类型的接口、用于实际元素的接口和这两组接口的实现。
图2.JAXB接口类图(单击进行放大)
图3.JAXB实现类图(单击进行放大)
从应用程序的角度来看,类型接口是这些类最有趣的部分。
对于类型内的数据,存在着JavaBean样式的get方法和set方法集合。
包含在类型接口中的这些方法遵循JAXB规范所规定的规则,所以应用程序代码可以安全地使用这些接口来访问所有数据,同时还保持了JAXB实现间的可移植性。
这些接口使JAXB生成的代码可以相当容易地与现有文档一起使用。
然而,构造和修改数据结构有点困难。
因为使用接口,所以不能直接构造实例;
而是必须使用工厂方法创建实例,然后使用类JavaBean的取值方法来填充数据值。
用JAXB根据Schema描述生成代码非常简单。
所提供的绑定编译器xjc是一个命令行工具。
它将Schema文档作为输入,将文件生成到指定的输出包和目标目录。
其中所具有的选项还使用户可以控制生成的代码文件是否是只读的,以及是否严格验证Schema描述。
通过使用绑定声明,JAXB规范定义了一些方法来定制生成数据绑定的一些方面。
包括:
∙用于控制所生成类的名称和属性的选项
∙指定由绑定所使用的现有实现类的方法
∙允许(有限地)控制验证处理和用于编组和数据分解的序列化器/反序列化器(serializer/deserializer)的选项
要么在实际的Schema文档中以注释形式嵌入这些定制,要么通过使用单独的外部绑定声明文档来单独提供这些定制。
参考实现的当前beta测试版只支持第一种方法,但在以后的发行版中将支持使用外部绑定声明文档。
总体说来,JAXB正成为一种功能强大而灵活的工具,它用于将Java语言代码绑定到W3CXMLSchema文法所定义的文档。
由于有可能批准将JAXB作为一个Java平台标准,因此它将会受到广泛支持,而且在各实现之间移动绑定应用程序会象在servlet引擎之间移动Web应用程序一样容易(一般来讲,很简单,但偶尔也会有一些波折)。
然而,JAXB确实也有一些缺点。
目前最大的局限是只有用于评估用途的许可证。
在该产品发行版(目前计划在这个季度发布)之前,JAXB还无法用于实际项目中。
另外,定制的程度也局限于只能应用到生成的代码。
在许多情形中,您可以为JAXB所定义的接口定义自己的实现类,但这些接口本身总是与Schema描述联系在一起,不太可能进行修改。
Castor
用于XML数据绑定的Castor框架支持映射绑定和生成绑定。
在我的上一篇文章中,我讨论了Castor映射绑定方法的一些特性。
对于本文,我只讨论根据Schema生成代码,但在第2部分,我将研究这两种方法的性能。
请回顾以前的文章(请参阅参考资料),了解有关Castor中映射数据绑定工作方式的更多信息。
图4.Castor生成的类图(单击进行放大)
在一些细节上,Castor的代码生成支持不同于JAXB方法,但在目的上,两者非常相似。
与使用JAXB一样,Castor向应用程序提供类JavaBean结构的数据模型。
主要差别在于Castor避免使用接口,而是喜欢直接使用生成的实现类。
除了每个实现类,Castor还生成描述符(descriptor)类,该类包含绑定和验证代码。
由于Castor使用具体的类,而不是接口,因此对于构造或修改文档数据结构,它要比JAXB略微简单。
可以仅仅直接使用相应类的构造函数,而不用通过工厂类。
Castor的当前beta测试版(我写这篇文章时,该版本为0.9.4.1)不支持在代码生成中进行任何实质的定制,但这种情况有望得到改变。
下一beta测试发行版预计将支持使用映射文件来控制代码生成的各个方面。
起初,在这些方面中,只支持类名和包名,但从更长远来看,计划将添加对用户所提供的实现类的支持。
Castor开发人员还计划在Castor中支持JAXB,可能是通过使用某类兼容性层来实现这一点。
用Castor根据Schema描述生成代码与用JAXB一样方便,使用的基本选项也一样。
Castor确实使用一些附加的命令行参数选项,而且通过属性文件设置,甚至提供了更多选项。
这些选项主要用在一些特殊的情形中,但不包括象JAXB那样通过Schema文档注释提供对类名和验证的控制。
现在,用Castor来生成源代码这种方法的主要缺点是对定制的支持有限。
这种情形正在开始发生转变,可以用Castor的映射数据绑定方法来实现实质的定制(见前一篇文章中的描述―请参阅参考资料),我期望最终在定制方面至少与源代码生成方法具有同样的灵活性。
从长远来看,这将使它的适应性比JAXB更强。
Castor按照BSD样式的许可证进行发布,完全可用于商业用途,而没有什么重大限制。
它看起来相当稳定,但每当遇到需要修正错误时,您将需要更新到最新的开发代码(或等待新的beta测试发行版)。
JBind
与JAXB和Castor类似,JBind根据XML文档的Schema描述来生成绑定代码。
尽管具有这种相同的性质,但实际上JBind的着重点与前两个大不相同。
JBind的主要创建者StefanWachter称此着重点为“XML代码”,他是这样描述它的:
它将由Schema所描述的XML数据和由Java语言代码所实现的行为组合在了一起。
JAXB和Castor更多地着重于使Java语言应用程序方便地使用XML,而JBind是围绕XML构建应用程序代码框架。
一旦JBind构建好框架,则可以用自己的代码扩展它来添加功能。
图5.JBind生成的类图(单击进行放大)
JBind还可以用于常规的数据绑定,在第2部分所讨论的性能测试中,我就是以这种方式用JBind的。
但这样做略微有点笨拙,部分原因是由于JBind总是需要在运行时处理文档的Schema。
如果实例文档不直接引用相应的Schema,则需要使用特殊的映射文件,或在读取实例文档之前,用手工将正确的Schema装入到自己的代码。
目前的文档不会真正向您显示这是如何做的。
与其它数据绑定框架相比,对处理绑定文档结构的更改,JBind也很严格。
通过使用ListIterator,可以删除现有的元素对象,但只有使用生成的create(创建)方法才能创建新的元素对象,这些方法自动地将这些元素对象添加到现有内容的后面。
实质上,JBind采用与前面框架大不相同的方法来处理文档数据。
JBind不生成JavaBean样式的数据类(但JAXB和Castor是这样做的),而是将一切存储在文档模型(目前为DOM级别2实现)中,构建绑定代码做为前端(facade)来访问存储在文档模型中的数据。
这是一种非常有趣的方法,如果完全实现,这可能具有一些不错的跨范例好处。
目前这种方法所具有的唯一好处是在生成代码中支持基于XPath的约束和访问方法。
由于存储机制相对于JBind的主旨是次要的,因此将来这种机制还可能会有所变动。
JBind所具有的好处是,在考虑过的所有数据绑定框架中,它支持Schema最彻底,并且提供上面所说的XPath扩展。
如果应用程序的核心是处理XML文档,则使用由JBind构造的“XML代码”框架可能非常简单。
对于一般的数据绑定用法,如果应用程序涉及到XML文档,而不是其重点时,则其它数据绑定方法可能会更简单些。
由于数据分解时需要验证以及由于文档模型后端存储机制(我将在第2部分更详细地讲述此问题),因此与其它框架相比,JBind还存在明显的性能劣势。
JBind是按照Apache样式的许可证分发的,完全可用于商业用途。
Quick
Quick文档将自身描述为:
不是作为处理XML的工具,而是作为对使用XML的Java语言的扩展。
它基于位于Java平台和XML之前的一系列开发成果,在此过程中进行了大量的重构工作。
它确实为在Java平台上使用XML提供了非常灵活的框架―它所具有的灵活性远远超出了为写本文我所能够了解和使用到的。
图6.Quick生成的类图(单击进行放大)
Quick的灵活性是有代价的。
它使用一系列相当复杂的步骤来根据DTD文档描述移到生成的代码,在此过程中使用了作为中间步骤的三个独立的绑定模式(不要与W3CXMLSchema混淆)文档:
∙QDML文档提供文档描述,它大致相当于DTD,不过添加了一些类型和继承。
∙QJML文档定义了XML到Java语言对象的绑定。
∙QIML文件基本上是QJML的编译形式,可以用它来生成实际的绑定代码。
在第2部分Quick的性能测试中,我尽可能少地定制这些文件,但为了得到预期的最终结果,仍然需要做一些手工编辑。
根据DTD文法生成QDML文件之后,必须编辑该文件来定义文档的根元素,并为非String值(在这里,是几个int)添加类型信息。
然后,运行程序来从QDML生成QJML文件,并编辑生成的QJML,从而向引用添加类型信息。
其实,并不真正需要这一步,但有了这一步,就可以用针对对象引用的特定类型生成代码(Castor和JAXB代码生成不支持该特性)。
最后,运行该工具以从QJML生成QIML文件,然后运行代码生成工具完成整个过程,从而获得类JavaBean的对象类和实际的绑定类(用来从XML转换到Java类以及从Java类转换到XML)。
再对这些文件进行一些手工编辑,则可以避免生成用于该对象类的新代码,直接链接到Castor映射绑定所使用的现有的类。
这种可以使用现有类的能力是一项功能非常强大的特性。
由于模式文件很复杂,而且为了利用该特性必须做大量的更
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- XML java