一个XML 模式(Schema)用XML语法表达了一个XML文档的结构。J2EE的开发者也许会需要一个符合XML模式的XML文档。Java XML绑定架构(JAXB)提供了一个绑定编译器,xjc,来从一个XML模式中生成Java类。用JAXB的xjc生成的Java类代表了在XML模式中不同的元素和复杂类型(complexType)。(一个复杂类型通过指定属性和元素内的元素来提供对一个元素的限定)。一个符合XML模式的XML文档可以从这些Java类中构建出来。
在这篇教程中,作者使用了JAXB用来从一个XML模式中生成Java类。这些Java类将会生成一个范例XML文档。这篇文章由以下几个部份组成:
1.预设置
2.概述
3.从XMl模式中生成Java类
4.从Java类中生成一个XML文档
预设置
为了用JAXB从一个XML模式中生成Java类,JAXB API类库和xjc工具应该存在CLASSPATH环境变量中。将Java Web服务开发包 (JWSDP) 1.5装入一个安装目录中。将下列的.jar文件加入CLASSPATH环境变量中。
·<JWSDP>/jaxb/lib/jaxb-api.jar
·<JWSDP>/jaxb/lib/jaxb-impl.jar
·<JWSDP>/jaxb/lib/jaxb-libs.jar
·<JWSDP>/jaxb/lib/jaxb-xjc.jar
·<JWSDP>/jwsdp-shared/lib/namespace.jar
·<JWSDP>/jwsdp-shared/lib/jax-qname.jar
·<JWSDP>/jwsdp-shared/lib/relaxngDatatype.jar
<JWSDP>是Java Web服务开发包1.5的安装目录。把<JWSDP>/jaxb/bin加入PATH环境变量中。<JWSDP>/jaxb/bin目录中包含了xjc编译器。把<JWSDP>/jwsdp-shared/bin目录加入到PATH环境变量中。<JWSDP>/jwsdp-shared/bin目录中包含了setenv的批处理文件,它设置了JAVA_HOME, ANT_HOME和JWSDP_HOME这几个环境变量。
概述
JAXB生成对应着XML顶层元素和顶层复杂类型元素 的Java类和接口。在一个XML模式中,一个元素由<xs:element/>表示,一个复杂类型元素由<xs:complexType/>表示。这篇教程列举了一个能够表示一篇在科学杂志上发表的文章的示例模式,同时这个示例模式将会被JAXB绑定编译器编译。XML模式,catalog.xsd,如下:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="catalog" type="catalogType"/>
<xsd:complexType name="catalogType">
<xsd:sequence>
<xsd:element ref="journal" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:attribute name="section" type="xsd:string"/>
<xsd:attribute name="publisher" type="xsd:string"/>
</xsd:complexType>
<xsd:element name="journal" type="journalType"/>
<xsd:complexType name="journalType">
<xsd:sequence>
<xsd:element ref="article" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="article" type="articleType"/>
<xsd:complexType name="articleType">
<xsd:sequence>
<xsd:element name="title" type="xsd:string"/>
<xsd:element name="author" type="xsd:string"/>
</xsd:sequence>
<xsd:attribute name="level" type="xsd:string"/>
<xsd:attribute name="date" type="xsd:string"/>
</xsd:complexType>
</xsd:schema>
一些XML模式的构造不被JAXB支持。假如这些不被支持的构造包含在了模式中,那么当你试图用xjc来生成Java类时将会报错。下列模式元素不被支持:xs:any, xs:anyAttribute, xs:notation, xs:redefine, xs:key, xs:keyref, 和 xs:unique. 下列模式的属性不被支持: complexType.abstract, element.abstract, element.substitutionGroup, xsi:type, complexType.block, complexType.final, element.block, element.final, schema.blockDefault, 和 schema.finalDefault.
生成Java类
xjc工具基于此模式来绑定一个模式到Java类。针对本文的示例模式来进行绑定的命令是:
>xjc catalog.xsd
xjc命令行接口的一些选项列在下表:
-nv 对于输入的模式不执行严格的XML验证
-b <file> 指定外部的绑定文件
-d <dir> 指定生成的文件的存放路径
-p <pkg> 指定目标包
-classpath <arg> 指定classpath
-use-runtime <pkg> impl.runtime包不被生成
-xmlschema 输入的模式是一个W3C XML模式(默认)
对于示例模式catalog.xsd来说,xjc将会生成45个类,显示在如下xjc的输出中:
parsing a schema...
compiling a schema...
generatedimpl untimeErrorHandlerAdaptor.java
generatedimpl untimeMSVValidator.java
generatedimpl untimeNamespaceContext2.java
generatedimpl untimeUnmarshallableObject.java
generatedimpl untimeMarshallerImpl.java
generatedimpl untimeValidationContext.java
generatedimpl untimeUnmarshallerImpl.java
generatedimpl untimeDefaultJAXBContextImpl.java
generatedimpl untimeContentHandlerAdaptor.java
generatedimpl untimeGrammarInfoFacade.java
generatedimpl untimeUnmarshallingContext.java
generatedimpl untimeUnmarshallingEventHandlerAdaptor.java
generatedimpl untimeXMLSerializable.java
generatedimpl untimeDiscarder.java
generatedimpl untimePrefixCallback.java
generatedimpl untimeSAXMarshaller.java
generatedimpl untimeNamespaceContextImpl.java
generatedimpl untimeUnmarshallingEventHandler.java
generatedimpl untimeGrammarInfo.java
generatedimpl untimeInterningUnmarshallerHandler.java
generatedimpl untimeValidatableObject.java
generatedimpl untimeGrammarInfoImpl.java
generatedimpl untimeValidatingUnmarshaller.java
generatedimpl untimeValidatorImpl.java
generatedimpl untimeSAXUnmarshallerHandlerImpl.java
generatedimpl untimeXMLSerializer.java
generatedimpl untimeUtil.java
generatedimpl untimeSAXUnmarshallerHandler.java
generatedimpl untimeAbstractUnmarshallingEventHandlerImpl.java
generatedimplArticleImpl.java
generatedimplArticleTypeImpl.java
generatedimplCatalogImpl.java
generatedimplCatalogTypeImpl.java
generatedimplJAXBVersion.java
generatedimplJournalImpl.java
generatedimplJournalTypeImpl.java
generatedArticle.java
generatedArticleType.java
generatedCatalog.java
generatedCatalogType.java
generatedJournal.java
generatedJournalType.java
generatedObjectFactory.java
generatedgm.ser
generatedjaxb.properties
对于示例XML模式中的每个顶层xs:element和顶层xs:complexType,都对应地生成了一个Java接口和一个Java类。同时也创建了一个工厂类(ObjectFactory.java),包含了创建接口对象的方法。可以在在篇文章的示例代码文件jaxb-java-resources.zip中找到ObjectFactory.java类。
Catalog.java是对应顶层元素catalog生成的接口。从模式的元素中生成的接口扩展了javax.xml.bin.Elemnt类。
Catalog.java:
package generated;
public interface Catalog
extends javax.xml.bind.Element, generated.CatalogType
{
}
CatalogType.java是对应顶层复杂元素catalogType生成的接口。CatalogType接口对应catalog元素的每个属性指定了setter和getter方法,还有对应catalog元素中的journal元素 的一个getter方法。
CatalogType.java:
package generated;
public interface CatalogType {
java.lang.String getSection();
void setSection(java.lang.String value);
java.util.List getJournal();
java.lang.String getPublisher();
void setPublisher(java.lang.String value);
}
CatalogImpl.java 和CatalogTypeImpl.java是分别对应Catalog.java 和 CatalogType.java接口的实现类。
从Java类中创建一个XML文档
这一节中,一个示例XMl文档将会通进JAXB从Java类被创建。示例XML文档,catalog.xml,如下显示:
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="http://www.w3.org/2001/XMLSchema-Instance"
section="Java Technology"
publisher="IBM developerWorks">
<journal>
<article level="Intermediate" date="January-2004" >
<title>Service Oriented Architecture Frameworks </title>
<author>Naveen Balani</author>
</article>
<article level="Advanced" date="October-2003" >
<title>Advance DAO Programming</title>
<author>Sean Sullivan</author>
</article>
<article level="Advanced" date="May-2002" >
<title>Best Practices in EJB Exception Handling </title>
<author>Srikanth Shenoy </author>
</article>
</journal>
</catalog>
从Java类中创建一个CatalogImpl类, 并且使用一个Marshaller(排列者)将CatalogImpl序列化来生成一个XML文档。
创建Marshaller(排列者)
首先,导入javax.xml.bind包,其中包含了Marshaller, UnMarshaller, 和 JAXBContext类。Marshaller类用来将一个Java类转换为XML数据。UnMarshaller类转换一个XML文档成Java对象。
import javax.xml.bind.*;
创建一个JAXBContext
一个JAXBContext对象被用来实现JAXB绑定框架的操作:marshal, unmarshal和validate。应用使用静态方法newInstance(String contextPath)来创建一个新实例(对象)。contextPath指明一组由模式生成的接口的包名。
JAXBContext jaxbContext=JAXBContext.newInstance("generated");
目录generated包含了JAXB生成的类和接口
使用createMarshaller方法创建一个Marshaller。Marshaller类重载了marshal方法,可以将Java对象序列化(也就是,转换一个Java对象到XML数据)成SAX2事件,文档对象模型(DOM),OutputStream, javax.xml.transform.Result或者java.io.Writer对象。
Marshaller marshaller=jaxbContext.createMarshaller();
为XML文档创建一个Java对象:CatalogImpl
为了创建一个Java对象,首选生成一个ObjectFactory。ObjectFactory将会创建一个实现类的实例。对于每一个模式生成的Java类,ObjectFactory中定义了一个静态方法来创建一个它的对象。
ObjectFactory factory=new ObjectFactory();
使用ObjectFactory类中的createCatalog来创建一个catalog元素。CatalogImpl是Catalog接口的实现类。
CatalogImpl catalog=(CatalogImpl)(factory.createCatalog());
使用CatalogImpl类中的setSection方法来设置catalog元素的section属性。
catalog.setSection("Java Technology");
用setPublisher方法来设置catalog元素的publisher属性。
catalog.setPublisher("IBM developerWorks");
为XML文档创建一个Java对象:JournalImpl和ArticleImpl
用ObjectFactory类中的createJournal方法来创建一个jounal元素。JournalImpl是Journal接口的实现类。
JournalImpl journal=(JournalImpl)(factory.createJournal());
将journal元素加入catalog元素。从CatalogImpl得到JournalImpl的java.util.List,并把journal元素加入到List中。
java.util.List journalList=catalog.getJournal();
journalList.add(journal);
使用ObjectFactory类的createArticle方法来创建journal中的article元素。ArticleImpl是Article接口的实现类。
ArticleImpl article=(ArticleImpl)(factory.createArticle());
使用ArticleImpl类中的setLevel方法来设置article元素的level属性。
article.setLevel("Intermediate");
用setDate方法设置article的date属性
article.setDate("January-2004");
用setTitle方法创建article元素的title属性
article.setTitle("Service Oriented Architecture Frameworks");
用setAuthor方法创建article元素的author属性
article.setAuthor("Naveen Balani");
将article元素加入journal元素中。从JournalImpl中得到ArticleImpl的java.util.List,并将article元素加入List中。
java.util.List articleList=journal.getArticle();
articleList.add(article);
与创建article元素的过程相类似,其它article元素也将被创建用来生成示例XML文档catalog.xml
将Java对象序列化为一个XML文档
用Marshaller类中的marshal方法来将CatalogImpl对象序列化为一个XML文档。CatalogImpl对象被序列化为一个OutputStream
marshaller.marshal(catalog, new FileOutputStream(xmlDocument));
xmlDocument是输出的XML的java.io.File对象,它代表的是本节一开始所展示的XML文档。JAXBConstrUCtor.java,这个程序用来从Java类中生成一个XML文档,也在这篇文章的示例代码文件中。
总结
JAXB提供了一个绑定编译器xjc, 从一个模式中生成Java对象,然后这些Java对象可以序列化为一个XML文档。但是,JAXB有一个限制:它不支持所有的XML模式结构。
资源
·" Java XML 绑定架构"
·"XML 模式结构"
·Java Web 服务开发包 1.5
·这篇文章的示例代码: jaxb-java-resources.zip:[下载文件]
Deepak Vohra 是一个NuBean的顾问和一个web开发者.