分享

Java & XML JAXB Tutorial from JWSDP

 9loong 2009-03-31
http://www./course/3_program/java/javajs/200853/112204.html
 
本文是对Java Web Service Development Pack 2.0中JAXB部分的翻译,如有转载,请声明!
Java Architecture for XML Binding README
Specification Version:2.0
Reference Implementation(RI) Version:2.0 ea3
 
JAXB提供了自动映射XML文档和Java对象的API和工具。
JAXB框架可以完成下面的操作:
®        将XML内容Unmarshal成Java表示
®        访问和更新Java表示
®        将XML内容的Java表示Marshal成XML内容
JAXB提供了XML和Java代码之间的高效并且标准的映射。Java开发人员可以使用JAXB来简化开发,提高效率,因为使用JAXB可以写很少的代码,并且不需要很精通XML。JAXB使得开发人员可以很容易的使用XML和Web Service技术来扩展应用程序。
1. Release Notes
JAXB Reference Implementation需要运行在J2SE 5.0或者更高的Java平台上。需要的JAR文件如下:
2.0运行环境:为Deploy JAXB2.0客户端所需要的JAR文件包括jaxb-api.jar,jaxb-impl.jar,jsr173-1.0_api.jar
1.0运行环境:为Deploy JAXB1.0客户端所需要的JAR文件包括2.0运行环境+jaxb1-impl.jar
2. XJC工具
虽然在笔者的其他文章中,包含了关于XJC脚本文件的使用,但是为了保持文章的完整性,将XJC脚本的内容再次追加在本文中。
绑定schema表示生成一系列的Java类,这些java类表示了schema。所有的JAXB实现都提供了一个工具叫做绑定编译器来将一个schema绑定。例如,JAXB参考实现提供了一个绑定编译器,允许通过脚本来执行(shell/bat)。假设需要将books.xsd文件进行绑定,并且假设是工作与*nix系统,那么绑定的命令如下:
    xjc.sh -p test.jaxb books.xsd -d work
选项说明:
-p:指定生成的类的包名
-d:指定存放类的目标目录
(译者注:其实绑定schema还有其他的选项和方法,例如Eclispe的xjc插件等)
C:\Documents and Settings\hp3643>xjc --help
 
Usage: xjc [-options ...] <schema file/URL/dir> ... [-b <bindinfo>] ...
Options:
 -nv                : 不进行输入schema的严格检查,默认情况下,XJC会进行严格的Schema检查,使用这个选项可以不进行严格的Schema检查,只是进行不太严格的检查
 -extension         : 默认情况下,XJC绑定编译器强制执行JAXB规范中的兼容性部分的规则,Appendix E.2定义了一些列JAXB v1.0所不支持的W3C XML Schema特性。这时,就可以使用-extension模式来支持这些特性。在默认情况下,只能使用规范中定义的绑定自定义。通过使用-extension选项,可以使用JAXB提供商扩展。
 -b <file>          : 指定外部绑定文件(每个<file>要有自己的-b,与出现顺序无关)
xjc schema1.xsd schema2.xsd schema3.xsd -b bindings123.xjb
xjc schema1.xsd schema2.xsd schema3.xsd -b bindings1.xjb -b bindings2.xjb -b bindings3.xjb
 -d <dir>           : 生成文件的目标路径,默认情况下在当前目录生成Java内容类,目标目录必须已经存在,XJC不会自动创建这些目录
 -p <pkg>           : 指定目标包名
 -httpproxy <proxy> : 设置HTTP/HTTPS代理,格式为[user[:password]@]proxyHost[:proxyPort]
 -classpath <arg>   : 指定用户的类路径
 -catalog <file>    : 指定范畴文件,用于处理外部实体应用
                        支持TR9401, XCatalog, and OASIS XML Catalog格式.
 -readOnly          : 生成的文件的状态为只读
 -npa               : 不生成包级别的annotations
 -xmlschema        : 将输入当作W3C XML Schema (默认)处理
 -relaxng           : 将输入当作RELAXNG (试验阶段,不支持)处理
 -relaxng-compact   : 将输入当作RELAXNG comapact语法 (试验阶段,不支持)处理
 -dtd               : 将输入当作XML DTD (experimental,unsupported)
 -wsdl              : 将输入当作WSDL处理(experimental,unsupported)
 -verbose           : 额外的显示
 -quiet             : 不输出编译结果
 -help              : 显示帮助信息
 -version           : 显示版本信息
 
Extensions:
 -Xlocator          : 对生成的代码启用源代码位置支持
 -Xsync-methods     : 生成访问的方法标志为''synchronized''关键字
 -mark-generated    : 将生成的代码标记为@javax.annotation.Generated
windows下运行命令:
F:\eclipse\workspace\JAXBTutorial\src>xjc -p test.jaxb -d . text/jaxp/book.xsd
(译者注:译者的系统中安装了Java(TM) Web Services Developer Pack 2.0,安装目录为C:\Sun\jwsdp-2.0,并将C:\Sun\jwsdp-2.0\jaxb\bin添加到了系统的path环境属性中)
parsing a schema...
compiling a schema...
test\jaxb\BookCategoryType.java
test\jaxb\BookType.java
test\jaxb\Collection.java
test\jaxb\ObjectFactory.java
运行完上述命令后,会生成一些类。
 
3. XJC Ant Task
在jwsdp或者其他的jaxb ri库中,都包含了jaxb-xjc.jar这个文件,在这个文件中,包含了XJCTask.class文件,这个文件可以应用于Ant构建工具中。在Ant构建脚本(一般为build.xml)中包含如下的语句:
<taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">
 <classpath>
    <fileset dir="path/to/jaxb/lib" includes="*.jar" />
 </classpath>
</taskdef>
上面的task定义将XJCTask映射到Ant task,并命名为xjc。在样例程序中包含了如何使用xjc任务。
该任务的语法如下:
环境变量:
ANT OPTS –将命令行参数传递给JVM。例如定义系统属性或者设置最大的Java堆大小。
参数属性:
xjc支持以下的参数属性:
schema:xml schema文件。这个属性或者<schema>子元素必须包含一个。
binding:外部绑定文件,应用于schema文件。
package:如果指定了的话,那么生成的java文件会放在这个包下,与命令行参数-p一样。
destdir:目标目录,与命令行参数-d一样。必须属性。
readonly:是否以只读方式生成java源文件,默认为false。
extension:如果设置为true,那么XJC绑定表一起会以扩展方式运行,否则的话,会按照严格的方式运行。和命令行工具的-extension参数一样。
catalog:指定分类文件来处理外部实体引用。
removeOldOutput:和<produces>子元素承兑使用。当设置为yes时,由<produces>元素指向的文件会在运行XJC编译器之前删除。
source:指定使用哪个版本的编译器。可以是1.0或者2.0.生成的Java代码会参考JAXB1.0或者JAXB2.0规范制定的规则。
xjc支持下面的嵌套元素:
schema:同时编译一个或者多个schema,schema子元素的语法和<fileset>相同。
binding:可以同时指定一个或者多个外部绑定文件,binding子元素的语法和<fileset>相同。
classpath:指定由用户指定的类路径。
arg:一些额外的命令行参数。这个元素可以指定多个选项:
-nv
-use-runtime
-schema
-dtd
-relaxng
-Xlocator
-Xsync-methods
下面是一些使用XJC Task的例子:
编译src/myschema.xmd,目标目录为src,包名为org.acme.foo:
<xjc schema="src/myschema.xsd" target="src" package="org.acme.foo"/>
编译src下面的所有schema文件,目标目录为src,包名默认:
<xjc target="src">
 <schema dir="src" includes="*.xsd"/>
</xjc>
编译src下面的所有schema文件,目标目录为src,绑定为src目录下的所有xjb文件:
<xjc target="src">
 <schema dir="src" includes="*.xsd"/>
 <binding dir="src" includes="*.xjb"/>
</xjc>
由于ant默认需要fileset中的文件夹必须存在,所以mkdir是必须的,下面的例子做了一个up-to-date的检查,如果abc.xsd有更新的话,那么src/org/acme/foo和其impl子目录的文件在编译之前就会被删除,所以不要将自己编写的类文件放在上述两个目录中。
<mkdir dir="src/org/acme/foo" />
<xjc target="src" schema="abc.xsd" removeOldOutput="yes" package="org.acme.foo">
 <produces dir="src/org/acme/foo" includes="* impl/*" />
</xjc>
更加复杂的up-to-date检查,如果xsd进行了更新,或者dtd文件进行了更新,都需要进行重新的编译schema。
<mkdir dir="src/org/acme/foo" />
<xjc target="src" removeOldOutput="yes" package="org.acme.foo">
 <schema dir="schema" includes="*.xsd" />
 <depends dir="schema" includes="*.dtd" />
 <produces dir="build/generated-src/org/acme/foo" includes="**/*" />
</xjc>
使用arg子元素:
<xjc target="src">
 <schema dir="src" includes="**/*.xsd" excludes="**/debug.xsd"/>
 <arg value="-nv" />
</xjc>
设置环境变量或者系统属性:
> set ANT_OPTS=-Dhttp.proxyHost=webcache.east
> set ANT_OPTS=%ANT_OPTS% -Dhttp.proxyPort=8080
> ant
 
4. SchemaGen工具
schema生成器可以通过schemagen shell脚本或者bat批处理文件来运行。目前schema生成器可以处理java源文件或者class文件。
    同时,也提供了Ant task的方式来运行Schema生成器。
对于不同的操作系统,使用这个工具的例子如下:
For Solaris/Linux
      % path/to/jaxb/bin/schemagen.sh Foo.java Bar.java ...
     
For WindowsNT/2000/XP
      > path\to\jaxb\bin\schemagen.bat Foo.java Bar.java ...
注意:默认的schema文件的文件名为schema1.xsd。
如果Java源文件或者类文件需要参考其他的类,那么必须可以通过系统的CLASSPATH来访问,或者需要指定-classpath选项,否则的话,会发生错误。
命令行参数:
Usage: schemagen [options ...] <java files>
Options:
    -d <path>           :指定将处理器和javac生成的类文件放在哪个目录中
    -cp <path>          :用户指定文件的目录
    -classpath <path>   :用户指定文件的目录
    -help               :显示帮助信息
目前schema生成器为Java类文件使用的名称空间生成schema文件。没有办法控制生成的schema文件的名字,可以使用Ant任务来完成这个功能。
 
5. Schema生成器的Ant Task
jaxb-xjc.jar文件中包含了SchemaGenTask.class文件,这样就可以在Ant构建工具中使用schema生成器了。SchemaGenTask的定义如下:
<taskdef name="schemagen" classname="com.sun.tools.jxc.SchemaGenTask">
 <classpath>
    <fileset dir="path/to/jaxb/lib" includes="*.jar" />
 </classpath>
</taskdef>
参数属性:
schemagen支持javac定义的大多数属性。并且支持下面的参数属性:
destdir:生成的schema文件的基准目录。
classpath:和子元素<classpath>功能相同。
 
schemagen支持所有的javac任务定义的子元素。
schema:控制生成的schema文件的名字。这个元素必须设置namespace属性和file属性。当这个元素存在的时候,指定的namespace的schema文件的名字和file属性指定的名字相同。文件名和destdir属性指定的文件名是相对的。当不存在destdir时,将项目basedir作为destdir。可以多次设置schema元素。
classpath:和路径类似的结构来表示classpath。
 
下面是一些schemagen生成器的例子:
将src目录下的源文件生成schema文件,保存在build/schemas目录。
<schemagen srcdir="src" destdir="build/schemas">     
使用javac的子元素:
<schemagen destdir="build/schemas">
 <src path="src" />
 <exclude name="Main.java"/>
</schemagen>
 
6. JAXB RI Extensions
运行时属性:
JAXB RI提供了一些在JAXB规范中没有定义的额外的Marshaller属性,这些属性可以更好的控制marshalling过程。但是,这只适用于JAXB RI,不一定适用于其他的JAXB提供者。
名称前缀映射
属性名:com.sun.xml.bind.namespacePrefixMapper
类型:com.sun.xml.bind.marshaller.NamespacePrefixMapper
默认值:无
JAXB RI提供了一个方法来将URI名称空间映射到前缀。下面是通常的过程:
    应用程序开发人员提供一个com.sun.xml.bind.marshaller.NamespacePrefixMapper的实现
    接着将这个类设置为RI指定的com.sun.xml.bind.namespacePrefixMapper属性
    每当marshaller遇到一个URI,都会回调映射
    当mapper返回值时,marshaller就会使用这个值
com.sun.xml.bind.marshaller.NamespacePrefixMapper类需要实现下面的方法:
public abstract class NamespacePrefixMapper {
    /**
     * Returns a preferred prefix for the given namespace URI.
     *
     * This method is intended to be overrided by a derived class.
     *
     * @param namespaceUri
     *      The namespace URI for which the prefix needs to be found.
     *      Never be null. "" is used to denote the default namespace.
     * @param suggestion
     *      When the content tree has a suggestion for the prefix
     *      to the given namespaceUri, that suggestion is passed as a
     *      parameter. Typically this value comes from QName.getPrefix()
     *      to show the preference of the content tree. This parameter
     *      may be null, and this parameter may represent an already
     *      occupied prefix.
     * @param requirePrefix
     *      If this method is expected to return non-empty prefix.
     *      When this flag is true, it means that the given namespace URI
     *      cannot be set as the default namespace.
     *
     * @return
     *      null if there''s no preferred prefix for the namespace URI.
     *      In this case, the system will generate a prefix for you.
     *
     *      Otherwise the system will try to use the returned prefix,
     *      but generally there''s no guarantee if the prefix will be
     *      actually used or not.
     *
     *      return "" to map this namespace URI to the default namespace.
     *      Again, there''s no guarantee that this preference will be
     *      honored.
     *
     *      If this method returns "" when requirePrefix=true, the return
     *      value will be ignored and the system will generate one.
     */
    public abstract String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix);
}
    如果这个属性被设置为null的话,下面默认的属性就会返回:
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
    return suggestion;
}
缩进
属性名:com.sun.xml.bind.indentString
类型:java.lang.String
默认值:”    ”四个空格
这个属性用来控制XML的缩进。
注意需要设置jaxb.formatted.output属性来启用缩进。
 
转义字符
属性名:com.sun.xml.bind.characterEscapeHandler
类型:com.sun.xml.bind.marshaller.CharacterEscapeHandler
默认值:null
默认情况下,JAXB RI的实现会试着转义字符,这样的话,就可以安全的表示输出编码。
不过,由于各种技术原因,默认的操作可能不会满足要求。如果需要处理更敏捷的处理转义,那么可以按照如下过程进行操作:
    实现com.sun.xml.bind.marshaller.CharacterEscapeHandler接口
    创建创建一个实例
    将实例设置为marshaller的属性
默认情况下的转义是和J2SE SDK的版本相关,如果运行J2SE SDK 版本1.3或者之前的版本不能满足转义需求的话,可以使用版本1.4或者之后的版本。
 
XML声明控制
属性名:com.sun.xml.bind.xmlDeclaration
类型:java.lang.Boolean
默认值:Boolean.TRUE
这是JAXB RI 1.0.x的实验属性,并且被JAXB 2.0标准所采用。2.0 RI会继续支持这个属性,但是客户端的代码应该使用Marshaller.JAXB_FRAGMENT属性。
在JAXB 2.0中,调用:
marshaller.setProperty("com.sun.xml.bind.xmlDeclaration", Boolean.FALSE);
和调用
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
是等价的。
 
启用片段marshalling可以使得将一个片段输出到另外一个XML的时候。同样,当需要输出类似DOCTYPE声明或者XML样式表处理指示,参考如下的代码:
PrintWriter out = ...;
// print out the prolog part by ourselves
out.println("<xml version=''1.0''?>");
out.println("<!DOCTYPE foo SYSTEM ''dummy.dtd''>");
marshaller.setProperty("com.sun.xml.bind.xmlDeclaration", Boolean.FALSE);
marshaller.marshal( jaxbObject, out );
 
JAXB RI提供了JAXB规范没有定义的自定义内容。
这些特性只有在-extension模式下运行绑定编译器时才可以使用
    所有JAXB RI供应商扩展都定义在http://java./xml/ns/jaxb/xjc名称空间
    名称空间中包含了扩展绑定声明,这将使得全局属性@jaxb:extensionBindingPrefixes在<xs:schema>元素。这个属性的值是以空格分隔的名称空间前缀。
扩展普通的超类
<xjc:superClass>自定义属性可以指定一个full qualified name作为Java类名来作为所有的生成类的超类。<xjc:superClass>只可以在<jaxb:globalBindings>:
<xs:schema xmlns:xs="http://www./2001/XMLSchema"
           xmlns:jaxb="http://java./xml/ns/jaxb"
           xmlns:xjc="http://java./xml/ns/jaxb/xjc"
           jaxb:extensionBindingPrefixes="xjc"
           jaxb:version="1.0">
    <xs:annotation>
       <xs:appinfo>
          <jaxb:globalBindings>
           <xjc:superClass name="org.acme.RocketBooster"/>
          </jaxb:globalBindings>
       </xs:appinfo>
    </xs:annotation>
.
.
.
</xs:schema>
还可以扩展共同的接口
和扩展共同的类类似,只是使用<xjc:superInterface>来代替<xjc:superClass>。
<xs:schema xmlns:xs="http://www./2001/XMLSchema"
           xmlns:jaxb="http://java./xml/ns/jaxb"
           xmlns:xjc="http://java./xml/ns/jaxb/xjc"
           jaxb:extensionBindingPrefixes="xjc"
           jaxb:version="1.0">
 
    <xs:annotation>
       <xs:appinfo>
          <jaxb:globalBindings generateValueClass="false">
           <xjc:superInterface name="org.acme.RocketBooster"/>
          </jaxb:globalBindings>
       </xs:appinfo>
    </xs:annotation>
.
.
.
</xs:schema>
 
7. 关于Schema
JAXB RI目前支持下面所列举的Schema语言。下面的一些特性并没有在JAXB规范中描述,只是在JAXB RI中才是可用的。
W3C Schema:JAXB 2.0 RI FCS会100%的支持W3C XML Schema。但是,现在的版本只是一个临时版本,还没有实现全部的功能。本节描述了JAXB 2.0规范。Section 8 描述了Java to XML,Section 6和7描述了XML to Java。
RELAX NG:目前还没有支持。
DTD:JAXB RI目前试着支持DTD,但是不能保证没有问题。可以使用下面的工具来编译XML的DTD。
$xjc.sh –dtd test.dtd

 
 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多