# Java-to-Schema 示例

> 原文： [https://docs.oracle.com/javase/tutorial/jaxb/intro/j2schema.html](https://docs.oracle.com/javase/tutorial/jaxb/intro/j2schema.html)

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

## j2s-create-marshal 示例

j2s-create-marshal 示例说明了 Java 到模式的数据绑定。它演示了 JAXB 注释类的编组和解组，还展示了如何使用从 JAXB 映射类生成的模式文件在解组时启用 JAXP 1.3 验证。

使用以下命令生成模式文件 `bc.xsd` ：

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

```

注意 `schema1.xsd` 被复制到 `bc.xsd` ; `schemagen` 不允许您指定所选的架构名称。

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

要在终端窗口中使用 Ant 编译和运行 j2s-create-marshal 示例，请转到 _jaxb-ri-install_ `/ samples / j2s-create-marshal /` 目录，输入以下内容：

```
ant 

```

## j2s-xmlAccessorOrder 示例

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

使用 Java 到模式映射，JavaBean 的属性和字段将映射到 XML 模式类型。类元素映射到 XML Schema 复杂类型或 XML Schema 简单类型。当前未指定生成的模式类型的默认元素顺序，因为 Java 反射不会强制返回订单。缺乏可靠的元素排序会对应用程序的可移植性产生负面影响您可以使用两个注释 `@XmlAccessorOrder` 和 `@XmlType.propOrder` 来定义必须可跨 JAXB 提供程序移植的应用程序的架构元素排序。

### 使用 `@XmlAccessorOrder` Annotation 定义模式元素排序

`@XmlAccessorOrder` 注释强加了两种元素排序算法之一， `AccessorOrder.UNDEFINED` 或 `AccessorOrder.ALPHABETICAL` 。 `AccessorOrder.UNDEFINED` 是默认设置。顺序取决于系统的反射实现。 `AccessorOrder.ALPHABETICAL` 算法按照 `java.lang.String.CompareTo（String anotherString）`确定的字典顺序对元素进行排序。

您可以在类对象上为注释类型 `ElementType.PACKAGE` 定义 `@XmlAccessorOrder` 注释。当在包上定义 `@XmlAccessorOrder` 注释时，格式化规则的范围对于包中的每个类都是活动的。在类上定义时，该规则对该类的内容有效。

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

### 使用 `@XmlType` Annotation 定义模式元素排序

可以为类定义 `@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` 将 `@XmlAccessorOrder` 定义为包的 `ALPHABETICAL` 。类 `PurchaseOrderType` 中的公共字段 `shipTo` 和 `billTo` 受此规则在生成的模式内容顺序中受到影响。类 `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` 注释来提供 XML 内容到 `HashMap` 的自定义映射（字段）使用 `int` 作为键， `String` 作为值。

接口 `XmlAdapter` 和注释 `@XmlJavaTypeAdapter` 用于在解组和编组期间对数据类型进行特殊处理。有多种 XML 数据类型，其表示不容易映射到 Java（例如， `xs：DateTime` 和 `xs：Duration` ），以及不映射的 Java 类型适当地进入 XML 表示。例如， `java.util.Collection` （如 `List` ）和 `java.util.Map` （如 `HashMap` ）的实现或者用于非 JavaBean 类。

`XmlAdapter` 接口和 `@XmlJavaTypeAdapter` 注释是为这些情况提供的。这种组合提供了一种便携式机制，用于在 Java 应用程序中读写 XML 内容。

`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` 实现与`目标`类型， `PACKAGE` ， `FIELD` 相关联]， `METHOD` ， `TYPE` 或 `PARAMETER` 。

j2s-xmlAdapter 示例演示了如何使用 `XmlAdapter` 将 XML 内容映射到（自定义） `HashMap` 中。 `HashMap` 对象，`篮子`，在类 `KitchenWorldBasket` 中，使用 `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 类， `PurchaseList` 和 `PartEntry` ，它们反映了解组和编组内容所需的模式格式。为这些类生成的 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` `篮子`配对。这种配对导致 `AdapterPurchaseListToHashMap` 的编组或解组方法被调用 `KitchenWorldBasket` 上的任何相应的编组或解组动作。

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

要在终端窗口中使用 Ant 编译和运行 j2s-xmlAdapter 示例，请转到 _jaxb-ri-install_ `/ samples / j2s-xmlAdapter /` 目录并键入以下内容：

```
ant

```

## j2s-xmlAttribute 示例

j2s-xmlAttribute 示例显示如何使用 `@XmlAttribute` 批注定义要作为 XML 属性处理的属性或字段。

`@XmlAttribute` 批注将字段或 JavaBean 属性映射到 XML 属性。实现以下规则：

*   静态 final 字段映射到 XML 固定属性。
*   当字段或属性是集合类型时，集合类型的项必须映射到模式简单类型。
*   当字段或属性不是集合类型时，类型必须映射到模式简单类型。

遵循 JavaBean 编程范例时，属性由字段名称上的 `get` 和`设置`前缀定义。

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

```

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

XmlAttribute 示例演示如何在静态 final 字段，字段而不是相应的 bean 方法之一，bean 属性（方法）和字段上使用 `@XmlAttribute` 注释。除了集合类型。在类 `USAddress` 中，字段，国家和 zip 被标记为属性。 `setZip` 方法被禁用以避免编译错误。属性状态被标记为 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` 注释将类或`枚举`类型映射到 XML 元素。每个用于解组和编组的顶级 Java 类型至少需要一个元素定义。如果没有元素定义，则没有 XML 内容处理的起始位置。

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

`@XmlRootElement` 批注的 namespace 属性用于定义元素的命名空间。

### 使用 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` 有两个字段， `orderDate` 和 `deliveryDate` ，它们被定义为 `XMLGregorianCalendar` 类型。生成的模式将这些元素定义为 XML 内置类型 `gMonthDay` 。此关系在文件 `package-info.java` 中的包上定义。文件`中的字段 `shipDate` TrackingOrder` 也被定义为 `XMLGregorianCalendar` 类型，但 `@XmlSchemaType` 注释语句覆盖包定义并指定字段为`日期`。属性方法 `getTrackingDuration` 定义要定义为基本类型`持续时间`而不是 Java 类型 `String` 的模式元素。

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

要使用 Ant 编译并运行 j2s-xmlSchemaType 示例，请在终端窗口中转到 _jaxb-ri-install_ `/ samples / j2s-xmlSchemaType /` 目录并键入以下内容：

```
ant 

```

## j2s-xmlType 示例

j2s-xmlType 示例演示了 `@XmlType` 注释的使用。 `@XmlType` 注释将类或`枚举`类型映射到 XML 架构类型。

类必须具有公共零参数构造函数或静态零参数工厂方法才能通过此批注进行映射。在解组期间使用这些方法之一来创建类的实例。工厂方法可以位于工厂类或现有类中。

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

*   如果在注释中标识了工厂类，则还必须标识该类中的相应工厂方法，并且将使用该方法。
*   如果在注释中标识了工厂方法但未标识工厂类，则工厂方法必须位于当前类中。即使存在公共零参数构造函数方法，也使用工厂方法。
*   如果注释中未标识工厂方法，则该类必须包含公共零参数构造函数方法。

在此示例中，工厂类为多个类提供零 arg 工厂方法。类 `OrderContext` 上的 `@XmlType` 注释引用工厂类。 unmarshaller 在此类中使用已识别的工厂方法。

```
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

```