Java 中文官方教程 2022 版(四十九)

原文:docs.oracle.com/javase/tutorial/reallybigindex.html

JAXB 示例

原文:docs.oracle.com/javase/tutorial/jaxb/intro/examples.html

以下部分描述如何使用包含在 JAXB RI 捆绑包中的示例应用程序。JAXB RI 捆绑包可从jaxb.java.net获取。下载并安装 JAXB RI 捆绑包。示例位于jaxb-ri-install/samples/目录中。这些示例演示并构建了关键的 JAXB 功能和概念。请按照呈现的顺序执行这些步骤。

阅读完本节后,您应该对 JAXB 感到足够自信,可以:

  • 从 XML 模式生成 JAXB Java 类

  • 在 Java 应用程序中使用基于模式的 JAXB 类解组和组合 XML 内容

  • 使用基于模式的 JAXB 类创建 Java 内容树

  • 在解组期间和运行时验证 XML 内容

  • 自定义 JAXB 模式到 Java 绑定

本文描述了三组示例:

  • 基本示例(修改 Marshal、Unmarshal Validate)演示了基本的 JAXB 概念,如使用默认设置和绑定来解组、组合和验证 XML 内容。

  • 自定义示例(Customize Inline、Datatype Converter、External Customize)演示了将 XML 模式默认绑定到 Java 对象的各种自定义方式。

  • java-to-schema 示例展示了如何使用注解将 Java 类映射到 XML 模式。


注意:基本和自定义示例基于采购订单场景。每个示例使用一个 XML 文档po.xml,根据一个 XML 模式po.xsd编写。这些文档源自由 David C. Fallside 编辑的W3C XML Schema Part 0: Primer


基本和自定义示例目录包含几个基本文件:

  • po.xsd是作为 JAXB 绑定编译器输入的 XML 模式,将从中生成基于模式的 JAXB Java 类。对于自定义内联和数据类型转换器示例,此文件包含内联绑定自定义。

  • po.xml是包含示例 XML 内容的采购订单 XML 文件,在每个示例中解组为 Java 内容树。这个文件在每个示例中几乎相同;为了突出不同的 JAXB 概念,存在轻微的内容差异。

  • Main.java是每个示例的主要 Java 类。

  • build.xml是一个 Ant 项目文件,为您提供方便。使用 Ant 工具自动生成、编译和运行基于模式的 JAXB 类。build.xml文件在示例之间有所不同。

  • inline-customize示例中的MyDatatypeConverter.java是一个 Java 类,用于提供自定义数据类型转换。

  • External Customize 示例中的binding.xjb是一个外部绑定声明文件,传递给 JAXB 绑定编译器以自定义默认的 JAXB 绑定。

以下表简要描述了基本、定制和 Java 到模式 JAXB 示例。

表:基本 JAXB 示例

示例名称 描述
Modify Marshal 演示如何修改 Java 内容树。
Unmarshal Validate 演示如何在解组期间启用验证。

表:定制 JAXB 示例

示例名称 描述
Customize Inline 演示如何通过在 XML 模式中使用内联注解来定制默认的 JAXB 绑定。
Datatype Converter 演示了将 XML simpleType定义绑定到 Java 数据类型的替代、更简洁的绑定方法,类似于内联定制示例。
External Customize 演示如何使用外部绑定声明文件来传递对 JAXB 绑定编译器的只读模式进行绑定自定义。

表:Java 到模式 JAXB 示例

示例名称 描述
Create Marshal 演示如何使用 ObjectFactory 类创建 Java 内容树并将其编组为 XML 数据。还演示了如何向 JAXB 列表属性添加内容。
XmlAccessorOrder 演示如何在 Java 类中使用@XmlAccessorOrder@XmlType.propOrder映射注解来控制 Java 类型在编组或解组 XML 内容时的顺序。
XmlAdapter 演示如何使用接口XmlAdapter和注解@XmlJavaTypeAdapter为使用整数(int)作为键和字符串(String)作为值的HashMap(字段)提供自定义映射 XML 内容的方法。
XmlAttribute 演示如何使用注解@XmlAttribute来定义一个属性或字段作为 XML 属性处理。
XmlRootElement 演示如何使用注解@XmlRootElement为相应类的 XML 模式类型定义 XML 元素名称。
XmlSchemaType Class 演示如何使用注解@XmlSchemaType来自定义属性或字段与 XML 内置类型的映射。
XmlType 演示如何使用注解@XmlType将一个类或enum类型映射到 XML 模式类型。

JAXB 编译器选项

JAXB XJC 模式绑定编译器将源 XML 模式转换或绑定到 Java 编程语言中的一组 JAXB 内容类。编译器类xjc提供为:在 Solaris/Linux 上为xjc.sh,在 Windows 上为xjc.bat在 JAXB RI 捆绑包中。xjc类包含在 JDK 类库中(在 tools.jar 中)。

xjc.shxjc.bat都接受相同的命令行选项。您可以通过在没有任何选项或使用-help开关的情况下调用脚本来显示快速使用说明。语法如下:

xjc [-options ...] <schema file/URL/dir/jar>... [-b >bindinfo<] ...

如果指定了dir,则将编译目录中的所有模式文件。如果指定了jar,将编译/META-INF/sun-jaxb.episode 绑定文件。

xjc命令行选项如下:

-nv

不执行输入模式或模式的严格验证。默认情况下,xjc 在处理之前会对源模式进行严格验证。请注意,这并不意味着绑定编译器不会执行任何验证;它只会执行较少严格的验证。

-extension

默认情况下,XJC 绑定编译器严格执行 JAXB 规范的兼容性章节中概述的规则。在默认(严格)模式下,您也只能使用规范中定义的绑定自定义。通过使用-extension开关,您可以使用 JAXB 供应商扩展。

-b file

指定一个或多个要处理的外部绑定文件。(每个绑定文件必须有自己的-b开关。)外部绑定文件的语法是灵活的。您可以有一个包含多个模式的自定义的单个绑定文件,或者您可以将自定义拆分为多个绑定文件。此外,命令行中模式文件和绑定文件的顺序无关紧要。

-d dir

默认情况下,XJC 绑定编译器在当前目录中生成 Java 内容类。使用此选项指定替代输出目录。目录必须已经存在;XJC 绑定编译器不会为您创建一个。

-p package

指定替代输出目录。默认情况下,XJC 绑定编译器将在当前目录中生成 Java 内容类。输出目录必须已经存在;XJC 绑定编译器不会为您创建一个。

-httpproxy proxy

指定 HTTP/HTTPS 代理。格式为[``*user*``[:``*password*``]@]``*proxyHost*``[:``*proxyPort*``]。旧的-host-port选项仍受参考实现支持以保持向后兼容性,但它们已被弃用。

-httpproxyfile f

类似于-httpproxy选项,但将参数放在文件中以保护密码。

-classpath arg

指定用于<jxb:javaType><xjc:superClass>自定义的客户端应用程序类文件的位置。

-catalog file

指定目录文件以解析外部实体引用。支持 TR9401、XCatalog 和 OASIS XML Catalog 格式。有关更多信息,请参阅 XML 实体和 URI 解析器文档或检查 catalog-resolver 示例应用程序。

-readOnly

强制 XJC 绑定编译器将生成的 Java 源文件标记为只读。默认情况下,XJC 绑定编译器不会写保护生成的 Java 源文件。

-npa

抑制将包级别注释生成到**/package-info.java中。使用此开关会导致生成的代码将这些注释内部化到其他生成的类中。

-no-header

抑制生成带有时间戳的文件头。

-target (2.0|2.1)

行为类似于 XJC 2.0 或 2.1,并生成不使用任何 XJC 2.2 功能的代码。

-enableIntrospection

启用正确生成布尔值 getter/setter 以启用 Bean Introspection api。

-contentForWildcard

为具有多个 xs:any 派生元素的类型生成内容属性。

-xmlschema

将输入模式视为 W3C XML 模式(默认)。 如果不指定此开关,则将处理输入模式为 W3C XML 模式。

-verbose

在编译器输出中更加详细。

-quiet

抑制编译器输出,如进度信息和警告。

-help

显示编译器开关的简要摘要。

-version

显示编译器版本信息。

-fullversion

显示编译器的完整版本信息。

-Xinject-code

将指定的 Java 代码片段注入生成的代码中。

-Xlocator

启用生成代码的源位置支持。

-Xsync-methods

生成带有synchronized关键字的访问器方法。

-mark-generated

使用-@javax.annotation.生成的注释标记生成的代码。

-episode *FILE*

为单独编译生成剧集文件。

JAXB 模式生成器选项

JAXB 模式生成器schemagen为您的 Java 类中引用的每个命名空间创建一个模式文件。 模式生成器可以通过使用适用于您平台的bin目录中的适当schemagen shell 脚本启动。 模式生成器仅处理 Java 源文件。 如果您的 Java 源引用其他类,则这些源必须从系统的 CLASSPATH 环境变量中访问; 否则,在生成模式时将出现错误。 无法控制生成的模式文件的名称。

通过调用脚本而不使用任何选项或使用-help选项,您可以显示快速使用说明。 语法如下:

schemagen [-d *path*] 
    [*java-source-files*]

-d path 选项指定了处理器生成和javac生成的类文件的位置。

关于模式到 Java 绑定

当您针对基本示例中使用的po.xsd XML 模式运行 JAXB 绑定编译器(解组读取,修改编组,解组验证)时,JAXB 绑定编译器将生成一个名为primer.po的 Java 包,其中包含下表中描述的类。

表:基本示例中的基于模式的 JAXB 类

描述
primer/po/Items.java 公共接口,绑定到名为ItemscomplexType模式。
primer/po/ObjectFactory.java 公共类,扩展com.sun.xml.bind.DefaultJAXBContextImpl; 用于创建指定接口的实例。 例如,ObjectFactorycreateComment()方法实例化Comment对象。
primer/po/PurchaseOrderType.java 公共接口,绑定到名为PurchaseOrderTypecomplexType模式。
primer/po/USAddress.java 公共接口,绑定到名为USAddresscomplexType模式。

这些类及其与基本示例源 XML 模式的特定绑定在以下表中描述。

表:基本示例的模式到 Java 绑定

XML Schema JAXB Binding

|

<xsd:schema xmlns:xsd=
 "http://www.w3.org/2001/XMLSchema">

|

<xsd:complexType 
  name="PurchaseOrderType">
  <xsd:sequence>
    <xsd:element 
      name="shipTo" 
      type="USAddress"/>
    <xsd:element 
      name="billTo" 
      type="USAddress"/>
    <xsd:element 
      ref="comment" 
      minOccurs="0"/>
    <xsd:element 
      name="items"
      type="Items"/>
  </xsd:sequence>
  <xsd:attribute 
    name="orderDate"
    type="xsd:date"/>
</xsd:complexType>

PurchaseOrderType.java

|

<xsd:complexType 
  name="USAddress">
  <xsd:sequence>
    <xsd:element 
      name="name" 
      type="xsd:string"/>
    <xsd:element 
      name="street" 
      type="xsd:string"/>
    <xsd:element 
      name="city" 
      type="xsd:string"/>
    <xsd:element 
      name="state" 
      type="xsd:string"/>
    <xsd:element 
      name="zip" 
      type="xsd:decimal"/>
  </xsd:sequence>
  <xsd:attribute 
    name="country" 
    type="xsd:NMTOKEN" 
    fixed="US"/>
</xsd:complexType>

USAddress.java

|

<xsd:complexType 
  name="Items">
  <xsd:sequence>
    <xsd:element 
      name="item" 
      minOccurs="1" 
      maxOccurs="unbounded">

Items.java

|

<xsd:complexType>
  <xsd:sequence>
    <xsd:element 
      name="productName" 
      type="xsd:string"/>
    <xsd:element 
      name="quantity">
      <xsd:simpleType>
        <xsd:restriction 
          base="xsd:positiveInteger">
          <xsd:maxExclusive 
            value="100"/>
        </xsd:restriction>
      </xsd:simpleType>
    </xsd:element>
    <xsd:element 
      name="USPrice" 
      type="xsd:decimal"/>
    <xsd:element 
      ref="comment" 
      minOccurs="0"/>
    <xsd:element 
      name="shipDate" 
      type="xsd:date" 
      minOccurs="0"/>
  </xsd:sequence>
  <xsd:attribute 
    name="partNum" 
    type="SKU" 
    use="required"/>
</xsd:complexType>

Items.ItemType

|

</xsd:element>
</xsd:sequence>
</xsd:complexType>

|

<!-- Stock Keeping Unit, a code for 
    identifying products -->

|

<xsd:simpleType 
  name="SKU">
  <xsd:restriction 
    base="xsd:string">
    <xsd:pattern 
      value="\d{3}-[A-Z]{2}"/>
  </xsd:restriction>
</xsd:simpleType>

|

</xsd:schema>

基于模式的 JAXB 类

接下来的部分简要解释了 JAXB 绑定编译器为示例生成的以下各个单独类的功能:

  • Items

  • ObjectFactory

  • PurchaseOrderType

  • USAddress

Items

Items.java 中:

  • Items 类是 primer.po 包的一部分。

  • 该类为 ItemsItemType 提供了公共接口。

  • 此类的实例化内容绑定到 XML ComplexTypes Items 及其子元素 ItemType

  • Item 提供了 getItem() 方法。

  • ItemType 提供了以下方法:

    • getPartNum();

    • setPartNum(String value);

    • getComment();

    • setComment(java.lang.String value);

    • getUSPrice();

    • setUSPrice(java.math.BigDecimal value);

    • getProductName();

    • setProductName(String value);

    • getShipDate();

    • setShipDate(java.util.Calendar value);

    • getQuantity();

    • setQuantity(java.math.BigInteger value);

ObjectFactory

ObjectFactory.java 中:

  • ObjectFactory 类是 primer.po 包的一部分。

  • ObjectFactory 提供了用于在 Java 内容树中实例化表示 XML 内容的 Java 接口的工厂方法。

  • 方法名是通过连接生成的:

    • 字符串常量 create

    • 所有外部 Java 类名称,如果 Java 内容接口嵌套在另一个接口中。

    • Java 内容接口的名称。

例如,在这种情况下,对于 Java 接口 primer.po.Items.ItemTypeObjectFactory 创建了方法 createItemsItemType()

PurchaseOrderType

PurchaseOrderType.java 中:

  • PurchaseOrderType 类是 primer.po 包的一部分。

  • 此类的实例化内容绑定到名为 PurchaseOrderType 的 XML 模式子元素。

  • PurchaseOrderType 是一个公共接口,提供以下方法:

    • getItems();

    • setItems(primer.po.Items value);

    • getOrderDate();

    • setOrderDate(java.util.Calendar value);

    • getComment();

    • setComment(java.lang.String value);

    • getBillTo();

    • setBillTo(primer.po.USAddress value);

    • getShipTo();

    • setShipTo(primer.po.USAddress value);

USAddress

USAddress.java 中:

  • USAddress 类是 primer.po 包的一部分。

  • 此类的实例化内容绑定到名为 USAddress 的 XML 模式元素。

  • USAddress 是一个公共接口,提供以下方法:

    • getState();

    • setState(String value);

    • getZip();

    • setZip(java.math.BigDecimal value);

    • getCountry();

    • setCountry(String value);

    • getCity();

    • setCity(String value);

    • getStreet();

    • setStreet(String value);

    • getName();

    • setName(String value);

基本示例

原文:docs.oracle.com/javase/tutorial/jaxb/intro/basic.html

本节描述了基本的 JAXB 示例(修改 Marshal、Unmarshal Validate),演示了如何:

  • 将 XML 文档解组为 Java 内容树,并访问其中包含的数据。

  • 修改 Java 内容树。

  • 使用 ObjectFactory 类创建 Java 内容树,然后将其编组为 XML 数据。

  • 在解组期间执行验证。

  • 在运行时验证 Java 内容树。

修改 Marshal 示例

修改 Marshal 示例演示了如何修改 Java 内容树。

  1. jaxb-ri-install/samples/modify-marshal/src/Main.java 类声明导入了三个标准 Java 类,五个 JAXB 绑定框架类和 primer.po 包:

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.math.BigDecimal;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBElement;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    
    import primer.po.*;
    
    
  2. 创建一个用于处理在 primer.po 中生成的类的 JAXBContext 实例。

    
    JAXBContext jc = JAXBContext.newInstance( "primer.po" );
    
    
  3. 创建一个 Unmarshaller 实例,并解组 po.xml 文件。

    Unmarshaller u = jc.createUnmarshaller();
    PurchaseOrder po = (PurchaseOrder)
        u.unmarshal(new FileInputStream("po.xml"));
    
    
  4. 使用 set 方法修改内容树中 address 分支中的信息。

    USAddress address = po.getBillTo();
    address.setName("John Bob");
    address.setStreet("242 Main Street");
    address.setCity("Beverly Hills");
    address.setState("CA");
    address.setZip(new BigDecimal
    address.setName("John Bob");
    address.setStreet("242 Main Street");
    address.setCity("Beverly Hills");
    address.setState("CA");
    address.setZip(new BigDecimal("90210"));
    
    
  5. 创建一个 Marshaller 实例,并将更新后的 XML 内容编组到 system.out。使用 setProperty API 指定输出编码;在本例中为格式化(易读)的 XML。

    Marshaller m = jc.createMarshaller();
    m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
    m.marshal(po, System.out);
    
    

使用 Ant 构建和运行修改 Marshal 示例

要使用 Ant 编译和运行修改 Marshal 示例,在终端窗口中,转到 jaxb-ri-install/samples/modify-marshal/ 目录,并输入以下内容:

ant

Unmarshal Validate 示例

Unmarshal Validate 示例演示了如何在解组期间启用验证。请注意,JAXB 提供了在解组期间进行验证但不在编组期间进行验证的功能。有关验证的更多详细信息,请参阅更多关于验证。

  1. jaxb-ri-install/samples/unmarshal-validate/src/Main.java 类声明导入了一个标准 Java 类,十一个 JAXB 绑定框架类和 primer.po 包:

    import java.io.File;
    
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.UnmarshalException;
    import javax.xml.bind.Unmarshaller;
    import javax.xml.bind.ValidationEvent;
    import javax.xml.bind.ValidationEventHandler;
    import javax.xml.bind.ValidationEventLocator;
    
    import static javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI;
    import javax.xml.validation.SchemaFactory;
    import javax.xml.validation.Schema;
    
    import primer.po.*;
    
    
  2. 创建一个用于处理在 primer.po 包中生成的类的 JAXBContext 实例。

    JAXBContext jc = JAXBContext.newInstance("primer.po");
    
    
  3. 创建一个 Unmarshaller 实例。

    Unmarshaller u = jc.createUnmarshaller();
    
    
  4. 默认的 JAXB Unmarshaller ValidationEventHandler 已启用,以将验证警告和错误发送到 system.out。默认配置导致在遇到第一个验证错误时解组操作失败。

    u.setValidating( true );
    
    
  5. 尝试将 po.xml 文件解组为 Java 内容树。在此示例中,po.xml 文件包含一个故意的错误。

    PurchaseOrder po = (PurchaseOrder)u.unmarshal(
        new FileInputStream("po.xml"));
    
    
  6. 默认验证事件处理程序处理验证错误,生成输出到 system.out,然后抛出异常。

    } catch( UnmarshalException ue ) {
        System.out.println("Caught UnmarshalException");
    } catch( JAXBException je ) { 
        je.printStackTrace();
    } catch( IOException ioe ) {
        ioe.printStackTrace();
    }
    
    

使用 Ant 构建和运行 Unmarshal Validate 示例。

要使用 Ant 编译和运行 Unmarshal Validate 示例,在终端窗口中,转到 jaxb-ri-install/samples/unmarshal-validate/ 目录,并输入以下内容:

ant 

自定义 JAXB 绑定

原文:docs.oracle.com/javase/tutorial/jaxb/intro/custom.html

以下部分描述了几个示例,这些示例是基于基本示例中演示的概念构建的。

本节的目标是演示如何使用自定义绑定声明来自定义 JAXB 绑定,可以通过以下两种方式之一进行:

  • 作为内联注释在 XML 模式中

  • 作为传递给 JAXB 绑定编译器的外部文件中的语句

与基本 JAXB 示例中的示例不同,该示例侧重于在生成基于模式的 Java 绑定类之前对 XML 模式进行的自定义。


注意: JAXB 绑定自定义目前必须手动完成。JAXB 技术的目标之一是标准化绑定声明的格式,从而可以创建自定义工具,并在 JAXB 实现之间提供标准的交换格式。


本节介绍了可以对 JAXB 绑定和验证方法进行的自定义。更多信息,请参见JAXB 规范

为什么要自定义?

在大多数情况下,由 JAXB 绑定编译器生成的默认绑定就足够了。然而,有些情况下,您可能希望修改默认绑定。其中一些情况包括:

  • 为基于模式的 JAXB 包、类、方法和常量创建 API 文档:通过向您的模式添加自定义 Javadoc 工具注释,您可以解释与您的实现特定的概念、指南和规则。

  • 为默认的 XML 名称到 Java 标识符映射无法自动处理的情况提供语义上有意义的自定义名称;例如:

    • 为解决名称冲突(如 JAXB 规范 的附录 D.2.1 中所述)。请注意,JAXB 绑定编译器会检测并报告所有名称冲突。

    • 为类型安全枚举常量提供名称,这些名称不是有效的 Java 标识符;例如,枚举整数值。

    • 为未命名模型组的 Java 表示提供更好的名称,当它们绑定到 Java 属性或类时。

    • 提供比默认从目标命名空间 URI 派生的包名称更有意义的名称。

  • 覆盖默认绑定;例如:

    • 指定模型组必须绑定到类而不是列表。

    • 指定一个固定属性可以绑定到一个 Java 常量。

    • 覆盖 XML 模式内置数据类型到 Java 数据类型的指定默认绑定。在某些情况下,您可能希望引入一个替代的 Java 类,该类可以表示内置 XML 模式数据类型的其他特征。

自定义概述

本节解释了一些核心的 JAXB 自定义概念:

  • 内联和外部自定义

  • 范围、继承和优先级

  • 自定义语法

  • 定制命名空间前缀

内联和外部定制

对默认 JAXB 绑定的定制以传递给 JAXB 绑定编译器的绑定声明的形式进行。这些绑定声明可以通过以下两种方式进行:

  • 作为源 XML 模式中的内联注释

  • 作为外部绑定定制文件中的声明

对于一些人来说,使用内联定制更容易,因为您可以在应用于的模式的上下文中看到您的定制。相反,使用外部绑定定制文件使您能够定制 JAXB 绑定而无需修改源模式,并且使您能够轻松地将定制应用于多个模式文件。


注意: 您可以结合两种类型的定制。例如,您可以在内联注释中包含对外部绑定定制文件的引用。但是,您不能在同一模式元素上同时声明内联和外部定制。


这些类型的定制在以下各节中有更详细的描述:

内联定制

通过在 XML 模式文件中使用内联绑定声明进行的 JAXB 绑定定制采用了嵌入在模式<xsd:annotation>元素中的<xsd:appinfo>元素的形式(xsd:是 XML 模式命名空间前缀,在 W3C XML Schema Part 1: Structures中定义)。内联定制的一般形式如下例所示:

<xs:annotation>
    <xs:appinfo>
        <!--
        ...
        binding declarations     .
        ...
        -->
    </xs:appinfo>
</xs:annotation>

定制是应用在模式中声明的位置。例如,对特定元素级别的声明仅适用于该元素。请注意,必须在<annotation><appinfo>声明标签中使用 XML 模式命名空间前缀。在前面的例子中,xs:被用作命名空间前缀,因此声明被标记为<xs:annotation><xs:appinfo>

外部绑定定制文件

通过使用包含绑定声明的外部文件进行的 JAXB 绑定定制,采用了以下示例中显示的一般形式:

<jxb:bindings schemaLocation = "xs:anyURI">
    <jxb:bindings node = "xs:string">*
        <!-- binding declaration -->
    <jxb:bindings>
</jxb:bindings>

  • schemaLocation是指向远程模式的 URI 引用。

  • node是一个 XPath 1.0 表达式,用于标识与给定绑定声明相关联的schemaLocation中的模式节点。

例如,在 JAXB 绑定声明文件中,第一个schemaLocation/node声明指定了模式名称和根模式节点:

<jxb:bindings schemaLocation="po.xsd" node="/xs:schema">
</jxb:bindings>

后续的schemaLocation/node声明,例如前一个模式示例中名为ZipCodeTypesimpleType元素,采用以下形式:

<jxb:bindings node="//xs:simpleType [@name=’ZipCodeType’]">

绑定定制文件格式

绑定定制文件必须是 ASCII 文本。名称或扩展名并不重要;尽管在本章中使用的典型扩展名是.xjb

将定制文件传递给 JAXB 绑定编译器

包含绑定声明的定制文件通过以下语法传递给 JAXB 绑定编译器xjc

xjc -b file schema

其中file是绑定自定义文件的名称,schema是要传递给绑定编译器的模式的名称。

您可以拥有一个包含多个模式的自定义的单个绑定文件,或者您可以将自定义分成多个绑定文件;例如:

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

请注意,命令行上模式文件和绑定文件的顺序无关紧要;尽管每个绑定自定义文件在命令行上必须在其自己的-b开关之前。

有关xjc编译器选项的更多信息,请参见 JAXB 编译器选项。

外部绑定自定义的限制

有几条规则适用于在外部绑定自定义文件中进行的绑定声明,而不适用于在源模式中内联进行的类似声明:

  • 绑定自定义文件必须以jxb:bindings version属性开头,以及 JAXB 和 XMLSchema 命名空间的属性:

    <jxb:bindings version="1.0" 
    
        >
    
    
  • 绑定声明适用的远程模式必须通过使用jxb:bindings声明明确在 XPath 表示法中标识,指定schemaLocationnode属性:

    • schemaLocation指定远程模式的 URI 引用。

    • node指定一个 XPath 1.0 表达式,用于标识schemaLocation中的模式节点,给定的绑定声明与之相关联;在绑定自定义文件中的初始jxb:bindings声明的情况下,此节点通常为"/xs:schema"

同样,必须使用 XPath 表示法指定要应用自定义的模式中的各个节点;例如:

<jxb:bindings node="//xs:complexType [@name=’USAddress’]">

在这种情况下,绑定编译器将自定义应用于节点,就好像声明被嵌入在节点的<xs:appinfo>元素中一样。

总结这些规则,外部绑定元素<jxb:bindings>仅在以下三种情况下被 JAXB 绑定编译器识别并处理:

  • 当其父元素是<xs:appinfo>元素时。

  • 当它是另一个<jxb:bindings>元素的祖先时。

  • 当它是文档的根元素时。将<jxb:bindings>元素作为其根的 XML 文档称为外部绑定声明文件。

范围、继承和优先级

默认的 JAXB 绑定可以在四个不同级别或范围上进行自定义或覆盖。

以下图示了自定义声明的继承和优先级。具体来说,金字塔顶部的声明继承并取代下面的声明。

组件声明继承并取代定义声明;定义声明继承并取代模式声明;模式声明继承并取代全局声明。

图:自定义范围继承和优先级

自定义范围继承和优先级

自定义语法

JAXB 绑定声明的四种类型的语法,XML 到 Java 数据类型绑定声明的语法,以及自定义命名空间前缀的语法在以下部分中描述。

  • 全局绑定声明

  • 模式绑定声明

  • 类绑定声明

  • 属性绑定声明

  • javaType 绑定声明

  • Typesafe 枚举绑定声明

  • javadoc 绑定声明

全局绑定声明

全局范围的自定义使用 <globalBindings> 声明。全局范围自定义的语法如下:

<globalBindings>
    [ collectionType = "collectionType" ]
    [ fixedAttributeAsConstantProperty = "true" | "false" | "1" | "0" ]
    [ generateIsSetMethod = "true" | "false" | "1" | "0" ]
    [ enableFailFastCheck = "true" | "false" | "1" | "0" ]
    [ choiceContentProperty = "true" | "false" | "1" | "0" ]
    [ underscoreBinding = "asWordSeparator" | "asCharInWord" ]
    [ typesafeEnumBase = "typesafeEnumBase" ]
    [ typesafeEnumMemberName = "generateName" | "generateError" ]
    [ enableJavaNamingConventions = "true" | "false" 
    | "1" | "0" ]
    [ bindingStyle = "elementBinding" | "modelGroupBinding" ]
    [ <javaType> ... </javaType> ]*
</globalBindings>

  • collectionType 可以是 indexed 或实现 java.util.List 的任何完全限定类名。

  • fixedAttributeAsConstantProperty 可以是 true, false, 1, 或 0。默认值为 false

  • generateIsSetMethod 可以是 true, false, 1, 或 0。默认值为 false

  • enableFailFastCheck 可以是 true, false, 1, 或 0。如果 enableFailFastChecktrue1,并且 JAXB 实现支持此可选检查,那么在设置属性时将执行类型约束检查。默认值为 false。请注意,JAXB 实现不支持快速失败验证。

  • choiceContentProperty 可以是 true, false, 1, 或 0。默认值为 false。当 bindingStyleelementBinding 时,choiceContentProperty 不相关。因此,如果指定 bindingStyleelementBinding,那么 choiceContentProperty 必须导致无效的自定义。

  • underscoreBinding 可以是 asWordSeparatorasCharInWord。默认值为 asWordSeparator

  • typesafeEnumBase 可以是一组 QNames,每个都必须解析为简单类型定义。默认值为 xs:NCName。有关将 simpleType 定义本地化映射到 Java typesafe enum 类的信息,请参见 Typesafe 枚举绑定声明。

  • typesafeEnumMemberName 可以是 generateErrorgenerateName。默认值为 generateError

  • enableJavaNamingConventions 可以是 true, false, 1, 或 0。默认值为 true

  • bindingStyle 可以是 elementBindingmodelGroupBinding。默认值为 elementBinding

  • <javaType> 可以是零个或多个 javaType 绑定声明。有关更多信息,请参见 javaType 绑定声明。

<globalBindings> 声明仅在顶层 schema 元素的 annotation 元素中有效。在任何给定的模式或绑定声明文件中只能有一个 <globalBindings> 声明的实例。如果一个源模式包含或导入第二个源模式,则 <globalBindings> 声明必须在第一个源模式中声明。

模式绑定声明

模式范围的自定义使用 <schemaBindings> 声明。模式范围自定义的语法如下:

<schemaBindings>
[ <package> package </package> ]
[ <nameXmlTransform> ... </nameXmlTransform> ]*
</schemaBindings>

<package 
    [ name = "packageName" ]
    [ <javadoc> ... </javadoc> ]
</package>

<nameXmlTransform>
[ <typeName 
    [ suffix="suffix" ]
    [ prefix="prefix" ] /> ]
[ <elementName 
    [ suffix="suffix" ]
    [ prefix="prefix" ] /> ]
[ <modelGroupName 
    [ suffix="suffix" ]
    [ prefix="prefix" ] /> ]
[ <anonymousTypeName 
    [ suffix="suffix" ]
    [ prefix="prefix" ] /> ]
</nameXmlTransform>

如上所示,<schemaBinding> 声明包括两个子组件:

  • <package>...</package> 指定了包的名称,如果需要的话,还可以指定模式派生类的 API 文档的位置。

  • <nameXmlTransform>...</nameXmlTransform> 指定要应用的自定义。

类绑定声明

<class> 绑定声明使您能够自定义模式元素与 Java 内容接口或 Java Element 接口的绑定。<class> 声明可用于自定义:

  • 用于模式派生的 Java 接口的名称

  • 用于模式派生的 Java 内容接口的实现类

<class> 自定义的语法是:

<class 
    [ name = "className"]
    [ implClass= "implClass" ] >
    [ <javadoc> ... </javadoc> ]
</class>

  • name 是派生 Java 接口的名称。它必须是有效的 Java 接口名称,不能包含包前缀。包前缀从当前包的值继承。

  • implClassclassName 的实现类的名称,必须包含完整的包名称。

  • <javadoc> 元素为模式派生的 Java 接口指定了 Javadoc 工具注释。在此输入的字符串必须使用 CDATA< 来转义嵌入的 HTML 标记。

属性绑定声明

<property> 绑定声明使您能够自定义 XML 模式元素与其 Java 表示作为属性的绑定。自定义的范围可以是在定义级别或组件级别,具体取决于 <property> 绑定声明的指定位置。

<property> 自定义的语法是:

<property
    [ name = "propertyName"]
    [ collectionType = "propertyCollectionType" ]
    [ fixedAttributeAsConstantProperty = "true" |
    "false" | "1" | "0" ]
    [ generateIsSetMethod = "true" | 
    "false" | "1" | "0" ]
    [ enableFailFastCheck ="true" | 
    "false" | "1" | "0" ]
    [ <baseType> ... </baseType> ]
    [ <javadoc> ... </javadoc> ]
</property>

<baseType>
    <javaType> ... </javaType>
</baseType>

  • name 定义了自定义值 propertyName;它必须是有效的 Java 标识符。

  • collectionType 定义了自定义值 propertyCollectionType,即属性的集合类型 propertyCollectionType。如果指定,属性可以是 indexed 或任何实现 java.util.List 的完全限定类名。

  • fixedAttributeAsConstantProperty 定义了自定义值 fixedAttributeAsConstantProperty。该值可以是 truefalse10

  • generateIsSetMethod 定义了自定义值 generateIsSetMethod。该值可以是 truefalse10

  • enableFailFastCheck 定义了自定义值 enableFailFastCheck。该值可以是 truefalse10。请注意,JAXB 实现不支持快速失败验证。

  • <javadoc> 自定义了属性的 getter 方法的 Javadoc 工具注释。

javaType 绑定声明

<javaType> 声明提供了一种自定义将 XML 数据类型转换为 Java 数据类型的方法。XML 提供的数据类型比 Java 更多,因此当默认的 JAXB 绑定无法充分表示您的模式时,<javaType> 声明使您能够指定自定义数据类型绑定。

目标 Java 数据类型可以是 Java 内置数据类型或特定于应用程序的 Java 数据类型。如果将特定于应用程序的 Java 数据类型用作目标,则您的实现还必须为解组和组合数据提供解析和打印方法。为此,JAXB 规范支持 parseMethodprintMethod

  • parseMethod 在解组过程中被调用,将输入文档中的字符串转换为目标 Java 数据类型的值。

  • 在组合过程中,printMethod 被调用以将目标类型的值转换为词法表示。

如果您更喜欢定义自己的数据类型转换,JAXB 定义了一个静态类 DatatypeConverter,以帮助解析和打印 XML Schema 内置数据类型的有效词法表示。

<javaType> 自定义的语法为:

<javaType name= "*javaType*"
    [ xmlType= "*xmlType*" ]
    [ hasNsContext = "true" | "false" ]
    [ parseMethod= "*parseMethod*" ]
    [ printMethod= "*printMethod*" ]>

  • name 是要将 xmlType 绑定到的 Java 数据类型。

  • xmlType 是要将 javaType 绑定到的 XML Schema 数据类型的名称;当 <javaType> 声明的父级为 <globalBindings> 时,此属性是必需的。

  • hasNsContext 允许指定命名空间上下文作为打印或解析方法的第二个参数;可以是 truefalse10。默认情况下,此属性为 false,在大多数情况下,无需更改。

  • parseMethod 是在解组过程中调用的解析方法的名称。

  • printMethod 是在组合过程中调用的打印方法的名称。

<javaType> 声明可用于:

  • 一个 <globalBindings> 声明

  • 用于简单类型定义、GlobalBindings<basetype> 声明的注释元素

  • 一个 <property> 声明

请参见MyDatatypeConverter 类 ,了解在自定义数据类型转换器类中如何实现 <javaType> 声明和 DatatypeConverterInterface 接口的示例。

类型安全枚举绑定声明

类型安全枚举声明提供了一种将 XML simpleType 元素映射到 Java typesafe enum 类的本地化方式。您可以进行两种类型的类型安全枚举声明:

  • <typesafeEnumClass> 允许您将整个 simpleType 类映射到 typesafe enum 类。

  • <typesafeEnumMember> 允许您将 simpleType 类的选定成员映射到 typesafe enum 类。

在这两种情况下,对此类型的自定义有两个主要限制:

  • 只有具有枚举约束的 simpleType 定义才能使用此绑定声明进行自定义。

  • 此自定义仅适用于一次仅有一个 simpleType 定义。要在全局级别映射一组相似的 simpleType 定义,请在 <globalBindings> 声明中使用 typesafeEnumBase 属性,如全局绑定声明中所述。

<typesafeEnumClass> 自定义的语法为:

<typesafeEnumClass 
    [ name = "enumClassName" ]
    [ <typesafeEnumMember> ... </typesafeEnumMember> ]*
    [ <javadoc> enumClassJavadoc </javadoc> ]
</typesafeEnumClass>

  • name 必须是有效的 Java 标识符,并且不能有包前缀。

  • 您可以在<typesafeEnumClass>声明中嵌入零个或多个<typesafeEnumMember>声明。

  • <javadoc>定制了枚举类的 Javadoc 工具注释。

<typesafeEnumMember>定制的语法是:

<typesafeEnumMember 
    name = "enumMemberName">
    [ value = "enumMemberValue" ]
    [ <javadoc> enumMemberJavadoc </javadoc> ]
</typesafeEnumMember>

  • name必须始终指定,并且必须是有效的 Java 标识符。

  • value必须是源模式中指定的枚举值。

  • <javadoc>定制了枚举常量的 Javadoc 工具注释。

对于内联注释,必须在<simpleType>元素的注释元素中指定<typesafeEnumClass>声明。必须在枚举成员的注释元素中指定<typesafeEnumMember>。这使得枚举成员可以独立于枚举类进行定制。

有关类型安全枚举设计模式的信息,请参阅Joshua Bloch 的Effective Java Programming在 Oracle Technology Network 上的示例章节。

javadoc 绑定声明

<javadoc>声明允许您向基于模式的 JAXB 包、类、接口、方法和字段添加自定义 Javadoc 工具注释。请注意,<javadoc>声明不能全局应用;它们只能作为其他绑定定制的子元素有效。

<javadoc>定制的语法是:

<javadoc>
    Contents in <b>Javadoc<\b> format.
</javadoc>

<javadoc>
    <<![CDATA[Contents in <b>Javadoc<\b> format ]]>
</javadoc>

请注意,应用于包级别的<javadoc>声明中的文档字符串必须包含<body>开放和关闭标签;例如:

<jxb:package 
    name="primer.myPo">
    <jxb:javadoc>
        <![CDATA[<body>
            Package level documentation for generated package primer.myPo.
        </body>]]>
    </jxb:javadoc>
</jxb:package>

定制命名空间前缀

所有标准的 JAXB 绑定声明必须以映射到 JAXB 命名空间 URI java.sun.com/xml/ns/jaxb 的命名空间前缀为前缀。例如,在此示例中,使用了jxb:。为此,您想要使用标准 JAXB 绑定声明自定义的任何模式必须在模式文件的顶部包含 JAXB 命名空间声明和 JAXB 版本号。例如,在 Customize Inline 示例的po.xsd中,命名空间声明如下:

<xsd:schema 
    xmlns:xsd= "http://www.w3.org/2001/XMLSchema"
    xmlns:jxb= "http://java.sun.com/xml/ns/jaxb"
    jxb:version="1.0">

具有jxb命名空间前缀的绑定声明采用以下形式:

<xsd:annotation>
    <xsd:appinfo>
    <jxb:globalBindings 
        *binding declarations* />
    <jxb:schemaBindings>
        ...
        *binding declarations*         .
        ...
    </jxb:schemaBindings>
    </xsd:appinfo>
</xsd:annotation>

请注意,在此示例中,globalBindingsschemaBindings声明用于分别指定全局范围和模式范围的定制。这些定制范围在范围、继承和优先级中有更详细的描述。

内联定制示例

Customize Inline 示例演示了通过内联注释对名为po.xsd的 XML 模式进行的一些基本定制。此外,该示例实现了一个自定义数据类型转换器类MyDatatypeConverter.java,展示了处理自定义数据类型转换的<javaType>定制中的打印和解析方法。

总结这个示例:

  1. po.xsd是一个包含内联绑定定制的 XML 模式。

  2. MyDatatypeConverter.java 是一个 Java 类文件,实现了 po.xsd<javaType> 自定义中指定的打印和解析方法。

  3. Main.java 是自定义内联示例中的主要类文件,使用了由 JAXB 编译器生成的模式派生类。

使用 Ant 构建和运行自定义内联示例

要使用 Ant 编译和运行自定义内联示例,在终端窗口中,转到 jaxb-ri-install/samples/inline-customize/ 目录并输入以下内容:

ant 

此示例中的关键自定义和自定义的 MyDatatypeConverter.java 类在下一节中有更详细的描述。

自定义模式

在自定义内联示例中使用的自定义模式位于文件 jaxb-ri-install/samples/inline-customize/po.xsd 中。自定义内容位于 <xsd:annotation> 标签中。

全局绑定声明

以下代码示例显示了 po.xsd 中的 globalBindings 声明:

<jxb:globalBindings
    fixedAttributeAsConstantProperty="true"
    collectionType="java.util.Vector"
    typesafeEnumBase="xsd:NCName"
    choiceContentProperty="false"
    typesafeEnumMemberName="generateError"
    bindingStyle="elementBinding"
    enableFailFastCheck="false"
    generateIsSetMethod="false"
    underscoreBinding="asCharInWord"/>

在此示例中,除了 collectionType 外,所有值都设置为默认值。

  • fixedAttributeAsConstantProperty 设置为 true 表示所有固定属性应绑定到 Java 常量。默认情况下,固定属性映射到更合适的简单属性或集合属性。

  • collectionType 设置为 java.util.Vector 指定生成实现类中所有列表在内部表示为向量。请注意,您为 collectionType 指定的类名必须实现 java.util.List 并且可以通过 newInstance 调用。

  • 如果将 typesafeEnumBase 设置为 xsd:string,这是一种全局方式,指定所有直接或间接从 xsd:string 派生并具有枚举约束的 simple 类型定义默认绑定到 typesafe enum。如果将 typesafeEnumBase 设置为空字符串 (""),则不会将任何 simple 类型定义默认绑定到 typesafe enum 类。typesafeEnumBase 的值可以是除 xsd:boolean 和两种二进制类型之外的任何原子简单类型定义。

  • JAXB 实现不支持 enableFailFastCheck 属性。


    注意: 使用类型安全的枚举类使您能够将模式枚举值映射到 Java 常量,这样就可以对 Java 常量进行比较,而不是对字符串值进行比较。


模式绑定声明

以下代码显示了 po.xsd 中的模式绑定声明:

<jxb:schemaBindings>
<jxb:package name="primer.myPo">
    <jxb:javadoc>
        <![CDATA[<body>
            Package level documentation for generated package primer.myPo.
        </body>]]>
    </jxb:javadoc>
</jxb:package>
    <jxb:nameXmlTransform>
        <jxb:elementName suffix="Element"/>
    </jxb:nameXmlTransform>
</jxb:schemaBindings>

  • <jxb:package name="primer.myPo"/> 指定 primer.myPo 作为生成模式派生类的包。

  • <jxb:nameXmlTransform>指定所有生成的 Java 元素接口默认附加Element到生成的名称。例如,当针对此模式运行 JAXB 编译器时,将生成元素接口CommentElementPurchaseOrderElement。相比之下,没有此自定义, 默认绑定会生成CommentPurchaseOrder。如果模式在不同的符号空间中使用相同的名称,例如在全局元素和类型定义中,此自定义可帮助您解决冲突,而不必使用单独的绑定声明逐个解决每个冲突。

  • <jxb:javadoc>指定了primer.myPo包的自定义 Javadoc 工具注释。请注意,与在类级别显示的<javadoc>声明不同,当在包级别进行<javadoc>声明时,必须包含开头和结尾的<body>标签。

类绑定声明

以下代码显示了po.xsd中的类绑定声明:

<xsd:complexType name="PurchaseOrderType">
    <xsd:annotation>
        <xsd:appinfo>
            <jxb:class name="POType">
                <jxb:javadoc>
                    A &lt;b>Purchase Order&lt;/b>
                    consists of addresses and items.
                </jxb:javadoc>
            </jxb:class>
        </xsd:appinfo>
    </xsd:annotation>
    <!-- ... -->
</xsd:complexType>

为基于模式的POType类编写的 Javadoc 工具注释将包含描述"一个&lt;b>采购订单&lt;/b>包括地址和商品。" 其中&lt;用于转义<b> HTML 标签中的开括号。


注意: 当在complexType定义的appinfo元素中指定<class>自定义时,如前面的示例所示,complexType定义将绑定到 Java 内容接口。


po.xsd中,另一个<javadoc>自定义在此类级别声明,但这次使用CDATA转义 HTML 字符串:

<xsd:annotation>
    <xsd:appinfo>
        <jxb:class>
            <jxb:javadoc>
                <![CDATA[
                    First line of documentation for a
                    <b>USAddress</b>.]]>
            </jxb:javadoc>
        </jxb:class>
    </xsd:appinfo>
</xsd:annotation>


注意: 如果要在<jaxb:javadoc>自定义中包含 HTML 标签,必须将数据放在CDATA部分中或使用&lt;转义所有左尖括号。有关更多信息,请参阅XML 1.0 第 2 版


属性绑定声明

这里特别感兴趣的是generateIsSetMethod自定义,它导致生成两个额外的属性方法,isSetQuantityunsetQuantity。这些方法使客户端应用程序能够区分模式默认值和在实例文档中明确出现的值。

例如,在po.xsd中:

<xsd:complexType name="Items">
    <xsd:sequence>
        <xsd:element name="item" 
            minOccurs="1"  
            maxOccurs="unbounded">
            <xsd:complexType>
                <xsd:sequence>
                    <xsd:element 
                        name="productName" 
                        type="xsd:string"/>
                    <xsd:element 
                        name="quantity" 
                        default="10">
                        <xsd:annotation>
                            <xsd:appinfo>
                                <jxb:property 
                                    generateIsSetMethod="true"/>
                            </xsd:appinfo>
                        </xsd:annotation>
                        <!-- ... -->
                    </xsd:complexType>
            </xsd:element>
    </xsd:sequence>
</xsd:complexType>

@generateIsSetMethod适用于quantity元素,该元素绑定到Items.ItemType接口中的属性。在Items.ItemType接口中生成了unsetQuantityisSetQuantity方法。

MyDatatypeConverter

jaxb-ri-install/samples/inline-customize/src/inlinecustomize/primer/MyDatatypeConverter,如下例所示,提供了一种自定义将 XML 数据类型与 Java 数据类型之间的转换的方法,使用<javaType>自定义。

package primer;
import java.math.BigInteger;
import javax.xml.bind.DatatypeConverter;

public class MyDatatypeConverter {

    public static short parseIntegerToShort(String value) {
        BigInteger result = DatatypeConverter.parseInteger(value);
        return (short)(result.intValue());
    }

    public static String printShortToInteger(short value) {
        BigInteger result = BigInteger.valueOf(value);
        return DatatypeConverter.printInteger(result);
    }

    public static int parseIntegerToInt(String value) {
        BigInteger result = DatatypeConverter.parseInteger(value);
        return result.intValue();
    }

    public static String printIntToInteger(int value) {
        BigInteger result = BigInteger.valueOf(value);
        return DatatypeConverter.printInteger(result);
    }
};

以下代码显示了如何在 po.xsd 中的 <javaType> 声明中引用 MyDatatypeConverter 类:

<xsd:simpleType name="ZipCodeType">
<xsd:annotation>
    <xsd:appinfo>
    <jxb:javaType name="int"
        parseMethod="primer.MyDatatypeConverter.parseIntegerToInt"
        printMethod="primer.MyDatatypeConverter.printIntTo Integer" />
    </xsd:appinfo>
</xsd:annotation>
    <xsd:restriction base="xsd:integer">
    <xsd:minInclusive value="10000"/>
    <xsd:maxInclusive value="99999"/>
    </xsd:restriction>
</xsd:simpleType>

在此示例中,jxb:javaType 绑定声明覆盖了此类型的默认 JAXB 绑定为 java.math.BigInteger。对于 Customize Inline 示例,ZipCodeType 的限制(特别是有效的美国邮政编码限于五位数字)使得所有有效值都可以适应 Java 基本数据类型 int。还要注意,因为 <jxb:javaType name="int"/>ZipCodeType 中声明,所以该定制适用于所有引用此 simpleType 定义的 JAXB 属性,包括 getZipsetZip 方法。

DataType Converter 示例

DataType Converter 示例类似于 Customize Inline 示例。与 Customize Inline 示例一样,DataType Converter 示例中的定制是通过在应用程序的 XML 模式 po.xsd 中使用内联绑定声明来实现的。

Customize Inline 和 DataType Converter 示例的全局、模式和包以及大多数类自定义是相同的。DataType Converter 示例与 Customize Inline 示例不同之处在于用于将 XML 数据转换为 Java int 数据类型的 parseMethodprintMethod

具体而言,DataType Converter 示例不是使用自定义的 MyDataTypeConverter 类中的方法执行这些数据类型转换,而是使用 javax.xml.bind.DatatypeConverter 提供的内置方法:

<xsd:simpleType name="ZipCodeType">
    <xsd:annotation>
        <xsd:appinfo>
            <jxb:javaType 
                name="int"
                parseMethod="javax.xml.bind.DatatypeConverter.parseInt"
                printMethod="javax.xml.bind.DatatypeConverter.printInt"/>
        </xsd:appinfo>
    </xsd:annotation>
    <xsd:restriction base="xsd:integer">
        <xsd:minInclusive value="10000"/>
        <xsd:maxInclusive value="99999"/>
    </xsd:restriction>
</xsd:simpleType>

使用 Ant 构建和运行 DataType Converter 示例

要使用 Ant 编译和运行 DataType Converter 示例,在终端窗口中,转到 jaxb-ri-install/samples/datatypeconverter/ 目录,并输入以下内容:

ant

绑定声明文件

以下各节提供有关绑定声明文件的信息:

  • JAXB 版本、命名空间和模式属性

  • 全局和模式绑定声明

  • 类声明

JAXB 版本、命名空间和模式属性

所有 JAXB 绑定声明文件必须以以下内容开头:

  • JAXB 版本号

  • 命名空间声明

  • 模式名称和节点

bindings.xjb 中的版本、命名空间和模式声明如下:

<jxb:bindings 
    version="1.0"

    >
    <jxb:bindings 
        schemaLocation="po.xsd" 
        node="/xs:schema">
            <!-- ...
            *binding-declarations* 
            ... -->
    </jxb:bindings>
    <!-- 
    schemaLocation="po.xsd" 
    node="/xs:schema" -->
</jxb:bindings>

JAXB 版本号

具有根元素 <jaxb:bindings> 的 XML 文件被视为外部绑定文件。根元素必须指定其绑定声明必须遵守的 JAXB 版本属性;具体来说,根 <jxb:bindings> 元素必须包含 <jxb:version> 声明或 version 属性。相比之下,当进行内联绑定声明时,JAXB 版本号作为 <xsd:schema> 声明的属性:

<xsd:schema 

    jxb:version="1.0">

命名空间声明

如 JAXB 版本、命名空间和模式属性中所示,外部绑定声明文件中的命名空间声明包括 JAXB 命名空间和 XMLSchema 命名空间。请注意,此示例中使用的前缀实际上可以是任何您想要的;重要的是在文件中后续声明中一致使用您在此定义的任何前缀。

模式名称和模式节点

代码中的第四行在 JAXB 版本、命名空间和模式属性中指定了此绑定声明文件适用的模式的名称,以及首次生效的模式节点。此文件中的后续绑定声明可以引用模式中的特定节点,但此第一个声明应该涵盖整个模式;例如,在bindings.xjb中:

<jxb:bindings schemaLocation="po.xsd" node="/xs:schema">

全局和模式绑定声明

bindings.xjb中的全局模式绑定声明与数据类型转换器示例中的po.xsd中的相同。唯一的区别是,因为po.xsd中的声明是内联完成的,您必须将它们嵌入到<xs:appinfo>元素中,而这些元素又嵌入到<xs:annotation>元素中。以这种方式嵌入声明在外部绑定文件中是不必要的。

<jxb:globalBindings
    fixedAttributeAsConstantProperty="true"
    collectionType="java.util.Vector"
    typesafeEnumBase="xs:NCName"
    choiceContentProperty="false"
    typesafeEnumMemberName="generateError"
    bindingStyle="elementBinding"
    enableFailFastCheck="false"
    generateIsSetMethod="false"
    underscoreBinding="asCharInWord"/>
    <jxb:schemaBindings>
        <jxb:package name="primer.myPo">
            <jxb:javadoc>
                <![CDATA[<body>
                    Package level documentation for generated package
                    primer.myPo.</body>]]>
                </jxb:javadoc>
        </jxb:package>
        <jxb:nameXmlTransform>
            <jxb:elementName suffix="Element"/>
        </jxb:nameXmlTransform>
    </jxb:schemaBindings>

相比之下,数据类型转换器示例中po.xsd中使用的语法是:

<xsd:annotation>
    <xsd:appinfo>
        <jxb:globalBindings
            ...
            *binding-declarations*
            ...
        <jxb:schemaBindings>
            ...
            *binding-declarations*
            ...
        </jxb:schemaBindings>
    </xsd:appinfo>
</xsd:annotation>

类声明

bindings.xjb中的类级绑定声明与数据类型转换器示例中的po.xsd中的类似声明有两个不同之处:

  • bindings.xjb中的所有其他绑定声明一样,您不需要将自定义嵌入到模式<xsd:appinfo>元素中。

  • 您必须指定应用自定义的模式节点。此类型声明的一般语法为:

    <jxb:bindings node="//*node-type*[@name=’*node-name*’]">
    
    

例如,以下代码显示了名为USAddresscomplexType的绑定声明。

<jxb:bindings node="//xs:complexType [@name=’USAddress’]">
    <jxb:class>
        <jxb:javadoc>
            <![CDATA[
                First line of documentation for a <b>USAddress</b>.
            ]]>
        </jxb:javadoc>
    </jxb:class>

<jxb:bindings node=".//xs:element [@name=’name’]">
    <jxb:property name="toName"/>
</jxb:bindings>

<jxb:bindings node=".//xs:element [@name=’zip’]">
    <jxb:property name="zipCode"/>
</jxb:bindings>
</jxb:bindings>
<!-- 
    node="//xs:complexType
    [@name=’USAddress’]" -->

请注意,在此示例中,USAddress是子元素namezip的父元素,因此</jxb:bindings>标签将子元素和类级javadoc声明的bindings声明括起来。

外部自定义示例

外部自定义示例与数据类型转换器示例相同,只是外部自定义示例中的绑定声明是使用外部绑定声明文件而不是内联在源 XML 模式中完成的。

外部自定义示例中使用的绑定自定义文件是jaxb-ri-install/samples/external-customize/binding.xjb

本节将bindings.xjb中的自定义声明与 XML 模式po.xsd中的数据类型转换器示例中使用的类似声明进行比较。这两组声明实现完全相同的结果。

使用 Ant 构建和运行外部自定义示例

要使用 Ant 编译和运行外部自定义示例,在终端窗口中,转到jaxb-ri-install/samples/external-customize/目录,并输入以下内容:

ant

Java-to-Schema 示例

原文:docs.oracle.com/javase/tutorial/jaxb/intro/j2schema.html

Java-to-Schema 示例展示了如何使用注解将 Java 类映射到 XML 模式。

j2s-create-marshal 示例

j2s-create-marshal 示例演示了 Java-to-schema 数据绑定。它演示了对带有 JAXB 注解的类进行编组和解组,并展示了如何在解组时使用从 JAXB 映射类生成的模式文件启用 JAXP 1.3 验证。

schema 文件bc.xsd是通过以下命令生成的:

schemagen src/cardfile/*.java
cp schema1.xsd bc.xsd

请注意,schema1.xsd被复制到bc.xsdschemagen不允许您指定自己选择的模式名称。

使用 Ant 构建和运行 j2s-create-marshal 示例

要使用 Ant 编译和运行 j2s-create-marshal 示例,在终端窗口中,转到jaxb-ri-install/samples/j2s-create-marshal/目录并输入以下内容:

ant 

j2s-xmlAccessorOrder 示例

j2s-xmlAccessorOrder 示例展示了如何使用@XmlAccessorOrder@XmlType.propOrder注解来指定 Java 类型在编组和解组时的 XML 内容顺序。

使用 Java-to-schema 映射,JavaBean 的属性和字段被映射到 XML 模式类型。类元素被映射为 XML 模式复杂类型或 XML 模式简单类型。生成的模式类型的默认元素顺序目前未指定,因为 Java 反射不强制返回顺序。可靠的元素排序的缺失对应用程序的可移植性产生负面影响。您可以使用两个注解@XmlAccessorOrder@XmlType.propOrder,为必须跨 JAXB 提供程序可移植的应用程序定义模式元素排序。

使用@XmlAccessorOrder注解定义模式元素排序

@XmlAccessorOrder注解强制执行两种元素排序算法,AccessorOrder.UNDEFINEDAccessorOrder.ALPHABETICALAccessorOrder.UNDEFINED是默认设置。顺序取决于系统的反射实现。AccessorOrder.ALPHABETICAL算法按java.lang.String.CompareTo(String anotherString)确定的字典顺序对元素进行排序。

您可以为注解类型ElementType.PACKAGE的类对象定义@XmlAccessorOrder注解。当@XmlAccessorOrder注解定义在包上时,格式规则的范围对包中的每个类都有效。当定义在类上时,规则对该类的内容有效。

一个包中可以有多个 @XmlAccessorOrder 注解。最内层(类)注解优先于外部注解。例如,如果在一个包中定义了 @XmlAccessorOrder(AccessorOrder.ALPHABETICAL),并且在该包中的一个类上定义了 @XmlAccessorOrder(AccessorOrder.UNDEFINED),则该类的生成的模式类型的内容将以未指定的顺序排列,而该包中的其他每个类的生成的模式类型的内容将按字母顺序排列。

使用 @XmlType 注解定义模式元素顺序

@XmlType 注解可以定义在一个类上。@XmlType 注解中的 propOrder() 元素使您能够指定生成的模式类型中的内容顺序。当您在一个类上使用 @XmlType.propOrder 注解来指定内容顺序时,类中的所有公共属性和公共字段必须在参数列表中指定。您希望保留在参数列表之外的任何公共属性或字段必须用 @XmlAttribute@XmlTransient 注解进行标注。

@XmlType.propOrder 的默认内容顺序为 {}{""},不活动。在这种情况下,活动的 @XmlAccessorOrder 注解优先。当类内容顺序由 @XmlType.propOrder 注解指定时,它优先于类或包上的任何活动的 @XmlAccessorOrder 注解。如果在一个类上指定了 @XmlAccessorOrder@XmlType.propOrder(A, B, ...) 注解,那么 propOrder 总是优先,不管注解语句的顺序如何。例如,在以下代码段中,@XmlAccessorOrder 注解在 @XmlType.propOrder 注解之前。

@XmlAccessorOrder(AccessorOrder.ALPHABETICAL)
@XmlType(propOrder={"name", "city"})

public class USAddress {
    // ...
    public String getCity() {return city;}
    public void setCity(String city) {this.city = city;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    // ...
}

在以下代码段中,@XmlType.propOrder 注解在 @XmlAccessorOrder 注解之前。

@XmlType(propOrder={"name", "city"})
@XmlAccessorOrder(AccessorOrder.ALPHABETICAL)
public class USAddress {
    // ...
    public String getCity() {return city;}
    public void setCity(String city) {this.city = city;}
    public String getName() {return name;}
    public void setName(String name) {this.name = name;}
    // ...
}

在两种情况下,propOrder 优先,并生成以下相同的模式内容:

<xs:complexType name="usAddress">
    <xs:sequence>
        <xs:element 
            name="name" 
            type="xs:string" 
            minOccurs="0"/>
        <xs:element 
            name="city" 
            type="xs:string" 
            minOccurs="0"/>
    </xs:sequence>
</xs:complexType>

示例中的模式内容排序

采购订单代码示例演示了使用包和类级别的 @XmlAccessorOrder 注解以及在类上使用 @XmlType.propOrder 注解来定义模式内容顺序的效果。

package-info.java 定义了包中 @XmlAccessorOrderALPHABETICAL。类 PurchaseOrderType 中的公共字段 shipTobillTo 受此规则影响,生成的模式内容顺序由此规则确定。类 USAddress 在类上定义了 @XmlType.propOrder 注解,演示了用户定义的属性顺序优先于生成的模式中的 ALPHABETICAL 顺序。

生成的模式文件可以在 jaxb-ri-install/samples/j2s-xmlAccessorOrder/build/schemas/ 目录中找到。

使用 Ant 构建和运行 j2s-xmlAccessorOrder 示例

要使用 Ant 编译和运行 j2s-xmlAccessorOrder 示例,在终端窗口中,转到 jaxb-ri-install/samples/j2s-xmlAccessorOrder/ 目录,并输入以下内容:

ant 

j2s-xmlAdapter 示例

j2s-xmlAdapter 示例演示了如何使用XmlAdapter接口和@XmlJavaTypeAdapter注解为使用int作为键和String作为值的HashMap(字段)提供自定义映射的 XML 内容的组合和解组。

接口XmlAdapter和注解@XmlJavaTypeAdapter用于在解组和组合期间对数据类型进行特殊处理。有各种 XML 数据类型,其表示方式不容易映射到 Java(例如,xs:DateTimexs:Duration),以及 Java 类型不正确地映射到 XML 表示。例如,java.util.Collection(如List)和java.util.Map(如HashMap)的实现,或非 JavaBean 类。

为这类情况提供了XmlAdapter接口和@XmlJavaTypeAdapter注解。这种组合提供了一个可移植的机制,用于将 XML 内容读取和写入 Java 应用程序。

XmlAdapter接口定义了数据读取和写入的方法。

/*
 *  ValueType - Java class that provides an 
 *  XML representation of the data. 
 *  It is the object that is used for marshalling and 
 *  unmarshalling.
 *
 *  BoundType - Java class that is used to 
 *  process XML content.
 */

public abstract class XmlAdapter<ValueType,BoundType> {

    // Do-nothing constructor for the derived classes.
    protected XmlAdapter() {}

    // Convert a value type to a bound type.
    public abstract BoundType unmarshal(ValueType v);

    // Convert a bound type to a value type.
    public abstract ValueType marshal(BoundType v);
}

您可以使用@XmlJavaTypeAdapter注解将特定的XmlAdapter实现与Target类型PACKAGEFIELDMETHODTYPEPARAMETER关联。

j2s-xmlAdapter 示例展示了如何使用XmlAdapter将 XML 内容映射到(自定义)HashMap中并从中组合出来。类KitchenWorldBasket中的HashMap对象basket使用int类型的键和String类型的值。这些数据类型应该反映在读取和写入的 XML 内容中,因此 XML 内容应如下示例所示:

<basket>
    <entry key="9027">glasstop stove in black</entry>
    <entry key="288">wooden spoon</entry>
</basket>

为 Java 类型HashMap生成的默认模式不反映所需的格式。

<xs:element name="basket">
    <xs:complexType>
        <xs:sequence>
            <xs:element 
                name="entry" 
                minOccurs="0" 
                maxOccurs="unbounded">
                <xs:complexType>
                    <xs:sequence>
                        <xs:element 
                            name="key" 
                            minOccurs="0"
                            type="xs:anyType"/>
                        <xs:element 
                            name="value" 
                            minOccurs="0" 
                            type="xs:anyType"/>
                    </xs:sequence>
                </xs:complexType>
            </xs:element>
        </xs:sequence>
    </xs:complexType>
</xs:element>

在默认的HashMap模式中,键和值都是元素,并且是anyType数据类型。XML 内容如下所示:

<basket>
    <entry>
        <key>9027</key>
        <value>glasstop stove in black</value>
    </entry>
    <entry>
        <key>288</key>
        <value>wooden spoon</value>
    </entry>
</basket>

要解决这个问题,示例使用了两个 Java 类,PurchaseListPartEntry,它们反映了用于解组和组合内容的所需模式格式。为这些类生成的 XML 模式如下:

<xs:complexType name="PurchaseListType">
    <xs:sequence>
        <xs:element 
            name="entry" 
            type="partEntry"
            nillable="true" 
            maxOccurs="unbounded"
            minOccurs="0"/>
    </xs:sequence>
</xs:complexType>

<xs:complexType name="partEntry">
    <xs:simpleContent>
        <xs:extension base="xs:string">
            <xs:attribute
                name="key" 
                type="xs:int"
                use="required"/>
        </xs:extension>
    </xs:simpleContent>
</xs:complexType>

AdapterPurchaseListToHashMap实现了XmlAdapter接口。在类KitchenWorldBasket中,使用@XmlJavaTypeAdapter注解将AdapterPurchaseListToHashMap与字段HashMap basket配对。这种配对导致在KitchenWorldBasket上进行任何对应的组合或解组操作时,将调用AdapterPurchaseListToHashMap的组合或解组方法。

使用 Ant 构建和运行 j2s-xmlAdapter 示例

要使用 Ant 编译和运行 j2s-xmlAdapter 示例,在终端窗口中,转到jaxb-ri-install/samples/j2s-xmlAdapter/目录,然后输入以下内容:

ant

j2s-xmlAttribute 示例

j2s-xmlAttribute 示例展示了如何使用@XmlAttribute注解来定义一个属性或字段被视为 XML 属性。

@XmlAttribute注解将字段或 JavaBean 属性映射到 XML 属性。强加以下规则:

  • 静态最终字段映射到 XML 固定属性。

  • 当字段或属性是集合类型时,集合类型的项目必须映射到模式简单类型。

  • 当字段或属性不是集合类型时,类型必须映射到模式简单类型。

遵循 JavaBean 编程范式时,属性由字段名上的getset前缀定义。

int zip;
public int getZip(){return zip;}
public void setZip(int z){zip=z;}

在 bean 类中,您可以选择在三个组件之一上设置@XmlAttribute注解:字段、setter 方法或 getter 方法。如果在字段上设置@XmlAttribute注解,则必须重命名 setter 方法,否则将在编译时出现命名冲突。如果在其中一个方法上设置@XmlAttribute注解,则必须在 setter 或 getter 方法上设置,但不能同时设置在两者上。

XmlAttribute 示例展示了如何在静态最终字段上使用@XmlAttribute注解,在字段而不是相应的 bean 方法上使用,在 bean 属性(方法)上使用,以及在不是集合类型的字段上使用。在类USAddress中,字段 country 和 zip 被标记为属性。setZip方法被禁用以避免编译错误。属性 state 在 setter 方法上被标记为属性。您也可以使用 getter 方法。在类PurchaseOrderType中,字段cCardVendor是非集合类型。它符合简单类型的要求;它是一个enum类型。

使用 Ant 构建和运行 j2s-xmlAttribute 示例

要使用 Ant 编译和运行 j2s-xmlAttribute 示例,在终端窗口中,转到jaxb-ri-install/samples/j2s-xmlAttribute/目录并键入以下内容:

ant

j2s-xmlRootElement 示例

j2s-xmlRootElement 示例演示了如何使用@XmlRootElement注解为相应类的 XML 模式类型定义 XML 元素名称。

@XmlRootElement注解将类或enum类型映射到 XML 元素。每个用于解组和组装的顶级 Java 类型都需要至少一个元素定义。如果没有元素定义,XML 内容处理就没有起始位置。

@XmlRootElement注解使用类名作为默认元素名。您可以通过使用注解属性name来更改默认名称。如果这样做,指定的名称将用作元素名和类型名。元素和类型名称不同是常见的模式实践。您可以使用@XmlType注解来设置元素类型名称。

@XmlRootElement注解的命名空间属性用于为元素定义命名空间。

使用 Ant 构建和运行 j2s-xmlRootElement 示例

要使用 Ant 编译和运行 j2s-xmlRootElement 示例,在终端窗口中,转到jaxb-ri-install/samples/j2s-xmlRootElement/目录并输入以下内容:

ant

j2s-xmlSchemaType 示例

j2s-xmlSchemaType 示例演示了如何使用注解@XmlSchemaType自定义将属性或字段映射到 XML 内置类型的映射。

@XmlSchemaType注解可用于将 Java 类型映射到 XML 内置类型之一。此注解在将 Java 类型映射到九种日期/时间原始数据类型之一时最有用。

当在包级别定义@XmlSchemaType注解时,标识需要同时包含 XML 内置类型名称和相应的 Java 类型类。在字段或属性上的@XmlSchemaType定义优先于包定义。

XmlSchemaType 类示例展示了如何在包级别、字段和属性上使用@XmlSchemaType注解。文件TrackingOrder有两个字段,orderDatedeliveryDate,它们被定义为XMLGregorianCalendar类型。生成的模式将定义这些元素为 XML 内置类型gMonthDay。此关系在文件package-info.java中在包中定义。文件TrackingOrder中的shipDate字段也被定义为XMLGregorianCalendar类型,但@XmlSchemaType注解语句覆盖了包定义,并指定该字段为date类型。属性方法getTrackingDuration定义模式元素被定义为原始类型duration而不是 Java 类型String

使用 Ant 构建和运行 j2s-xmlSchemaType 示例

要使用 Ant 编译和运行 j2s-xmlSchemaType 示例,在终端窗口中,转到jaxb-ri-install/samples/j2s-xmlSchemaType/目录并输入以下内容:

ant 

j2s-xmlType 示例

j2s-xmlType 示例演示了如何使用@XmlType注解。@XmlType注解将一个类或一个enum类型映射到一个 XML Schema 类型。

一个类必须具有公共零参数构造函数或静态零参数工厂方法,以便通过此注解进行映射。在解组期间,其中一个方法用于创建类的实例。工厂方法可以位于工厂类中或现有类中。

有一个关于解组使用哪种方法的优先顺序:

  • 如果注解中标识了工厂类,则该类中还必须标识相应的工厂方法,并且该方法将被使用。

  • 如果注解中标识了工厂方法但未标识工厂类,则工厂方法必须位于当前类中。即使存在公共零参数构造方法,也将使用工厂方法。

  • 如果注解中未标识工厂方法,则类必须包含一个公共零参数构造方法。

在这个例子中,一个工厂类为几个类提供了零参数的工厂方法。类OrderContext上的@XmlType注解引用了工厂类。解组器在这个类中使用了标识的工厂方法。

public class OrderFormsFactory {

    public OrderContext newOrderInstance() {
        return new OrderContext()
    }

    public PurchaseOrderType {
        newPurchaseOrderType() {
            return new newPurchaseOrderType();
        }
    }

    @XmlType(name="oContext",
        factoryClass="OrderFormsFactory",
        factoryMethod="newOrderInstance")
    public class OrderContext {
        public OrderContext() {
            // ...
        }
    }
}

在这个例子中,一个工厂方法在一个类中被定义,该类还包含一个标准的类构造。因为factoryMethod的值被定义了,而没有定义factoryClass,所以在解组时会使用工厂方法newOrderInstance

@XmlType(name="oContext", 
    factoryMethod="newOrderInstance")
public class OrderContext {

    public OrderContext() {
        // ...
    }

    public OrderContext newOrderInstance() {
        return new OrderContext();
    }
}

使用 Ant 构建和运行 j2s-xmlType 示例

要使用 Ant 编译和运行 j2s-xmlType 示例,在终端窗口中,进入jaxb-ri-install/samples/j2s-xmlType/目录,并输入以下内容:

ant

posted @ 2024-04-12 15:17  绝不原创的飞龙  阅读(22)  评论(0编辑  收藏  举报