JiBX 1.2,第 1 部分: 从 Java 代码到 XML 模式

通过 Java 数据模型与 XML 文档之间的自定义转换提高模式质量

XML 模式定义是许多数据交换类型(包括大多数 Web 服务形式)的基础。但是 XML Schema 是一种十分复杂的标准,并且与处理 Java™ 代码的工具相比,用于创建和修改模式定义的大多数工具在功能性和易用性方面要逊色一些。您将在本教程 — 共两部分的 系列教程 的第 1 部分 — 中了解到 JiBX 1.2 的新功能,它将允许您从 Java 代码入手并轻松地生成优秀的模式定义来匹配数据结构。然后,无论您是否使用 JiBX 数据绑定,都可以直接使用这些模式。

Dennis Sosnoski, 首席顾问, Sosnoski Software Associates Ltd

Dennis Sosnoski 的照片Dennis Sosnoski 是专门从事基于 Java 的 SOA 和 Web 服务的顾问兼培训师。他有 30 多年的专业软件开发经验,最近几年一直致力于服务器端 XML 和 Java 技术方面的工作。Dennis 是 JiBX XML 开源数据绑定工具的首席开发人员,并且为 Apache Axis2 Web 服务框架做出了贡献。他还是 JAX-WS 2.0 和 JAXB 2.0 规范的专家组成员之一。有关培训及咨询服务的信息,请访问 他的 Web 站点



2009 年 4 月 14 日

开始之前

关于本教程

JiBX 是 XML 数据与 Java 对象的绑定工具。JiBX 数据绑定一直以来被认为是绑定 Java 代码与 XML 的最快且最灵活的方法。但是其绑定定义的复杂性及对于广泛使用的 XML 模式定义的有限支持经常让用户感到失望。幸运的是,1.2 版的 JiBX 一直致力于消除这些问题。在本教程中,您将了解如何使用 JiBX 1.2 的新功能从现有的 Java 代码轻松地生成 XML 模式定义,并读取和编写匹配生成的模式定义的 XML 文档 — 所有这一切都不需要详细了解 JiBX 绑定定义。第 2 部分 将介绍相反的一面,即从 XML 模式定义生成 Java 代码。

目标

本教程将指导您完成使用 JiBX 从 Java 代码生成 XML 模式定义的过程。您将首先看到如何从一个简单的 Java 数据模型入手,然后生成匹配该模型的默认模式。在此基础上,您将了解如何轻松地通过应用一系列的自定义来控制 Java 类所使用的实际值及其访问方法,以及这些类是必要的还是可选的,XML 中使用的名称及名称空间,甚至生成的模式定义的结构。在此过程中,您将看到 JiBX 如何利用您在 Javadoc 中的成果自动归档模式定义,从而使生成的模式更有价值。在阅读本教程并且实践了提供的示例之后,您将可以使用 JiBX 从您自己的 Java 数据结构类生成优秀的 XML 模式定义。

先决条件

要理解本教程,您至少要了解 Java 代码和 XML 的基础知识。您不需要详细了解 XML 模式定义,但是略微熟悉模式将帮助您更好地理解示例。

系统要求

要运行示例,您需要安装:

本教程中包括 JiBX 下载及安装说明。


开始

在本节中,您将初步了解 JiBX,并安装 JiBX 及教程样例代码。

JiBX 简介

JiBX 是用于转换 Java 数据结构与 XML 文档的众多工具之一(请参阅 参考资料)。性能与灵活的功能是使 JiBX 脱颖而出的原因。JiBX 的性能一直处于领先地位,在一项、两项甚至多项参数上优于其他常见工具(例如 JAXB 2.0)。JiBX 还比几乎所有其他 Java-XML 工具都灵活,它使用绑定定义解除 Java 结构与 XML 表示的绑定,这样两者可以相互独立地进行更改。

在 1.2 发行版中,JiBX 添加了支持 XML 模式定义的主要功能。您可以使用 JiBX 发行版中附带的工具生成匹配 Java 代码的模式定义,或者生成匹配模式定义的 Java 代码。不管怎样操作,您还将得到一个绑定定义,它将允许您使用 JiBX 转换 Java 代码与匹配模式定义的 XML 文档。在本教程中,您将看到如何应用第一类生成:从 Java 代码生成模式定义。

安装 JiBX

在继续学习本教程之前,您需要先安装 JiBX。下载 最新的 1.2.x 发行版 ZIP 并将其解压缩到系统中便于访问的位置。您将得到名为 jibx 的目录,其中包含所有的 JiBX JAR、文档、示例,甚至源代码。

安装教程代码

现在下载教程 样例代码,也是以 ZIP 文件的形式提供的。在系统中安装样例代码的最简单方法是在 JiBX 安装的根目录中解压缩 ZIP(或者对于 Windows®,将 dwcode1 目录从 ZIP 文件中复制到 JiBX 安装的根目录中)。此操作应当在 jibx 目录中创建 dwcode1 子目录,而且 dwcode1 子目录中包含示例文件(包括 build.xml、custom1.xml 和其他文件)。

样例代码包括自动运行 JiBX 工具并处理示例涉及的其他步骤的 Apache Ant 构建文件。如果直接将样例代码安装到 JiBX 安装目录中,则构建可以访问 JiBX JAR 而无需任何附加配置。如果在其他位置安装样例代码,则仍然可以使用 Ant 构建。在这种情况下,您只需将 JIBX_HOME 环境变量设为 JiBX 的安装路径。或者,您可以编辑样例代码目录中的 build.xml 文件,然后对靠近文件顶部的直接设置 jibx-home 属性的代码行取消注释。


通过代码生成默认绑定和模式

非 Java 5 用法

教程示例代码使用 Java 5 类型的集合和枚举功能,但是 JiBX 本身完全兼容更早的 Java 版本。标准的 JiBX 运行时可以与 1.3 及更高版本的 JVM 结合使用,并且还可以构建与 J2ME 兼容的产品。大多数其他 JiBX 组件(包括 BindGen)都可以在 1.4.1 和更高版本的 JVM 上运行。JiBX 下载中的 BindGen 文档包括一个示例,展示自定义如何能够在使用 Java 5 以前的代码的情况下为 BindGen 提供等效的类型集合。

通过 Java 代码生成 JiBX 绑定定义和相应的 XML 模式定义非常容易。您将在本节中了解具体操作。

Java 示例代码简介

作为示例,我将使用表示在线商店订单的一组 bean 样式(私有字段、公共 get 和 set 访问方法)的类的 Java 代码。 清单 1 显示了简短版本的代码,其中大多数 get/set 方法已省去。完整的样例代码位于样例代码的 src 目录中。

清单 1. 基本 Java 代码
package org.jibx.starter;

/**
 * Order information.
 */
public class Order
{
    private long orderNumber;
    private Customer customer;

    /** Billing address information. */
    private Address billTo;
    private Shipping shipping;

    /** Shipping address information. If missing, the billing address is also used as the
     shipping address. */
    private Address shipTo;
    private List<Item> items;

    /** Date order was placed with server. */
    private Date orderDate;

    /** Date order was shipped. This will be <code>null</code> if the order has not
     yet shipped. */
    private Date shipDate;
    private Float total;

    public long getOrderNumber() {
        return orderNumber;
    }
    ...
}
/**
 * Customer information.
 */
public class Customer
{
    private long customerNumber;

    /** Personal name. */
    private String firstName;

    /** Family name. */
    private String lastName;

    /** Middle name(s), if any. */
    private List<String> middleNames;
    ...
}
/**
 * Address information.
 */
public class Address
{
    /** First line of street information (required). */
    private String street1;

    /** Second line of street information (optional). */
    private String street2;
    private String city;

    /** State abbreviation (required for the U.S. and Canada, optional otherwise). */
    private String state;

    /** Postal code (required for the U.S. and Canada, optional otherwise). */
    private String postCode;

    /** Country name (optional, U.S. assumed if not supplied). */
    private String country;
    ...
}
/**
 * Order line item information.
 */
public class Item
{
    /** Stock identifier. This is expected to be 12 characters in length, with two
     leading alpha characters followed by ten decimal digits. */
    private String id;

    /** Text description of item. */
    private String description;

    /** Number of units ordered. */
    private int quantity;

    /** Price per unit. */
    private float price;
    ...
}
/**
 * Supported shipment methods. The "INTERNATIONAL" shipment methods can only be used for
 * orders with shipping addresses outside the U.S., and one of these methods is required
 * in this case.
 */
public enum Shipping
{
    STANDARD_MAIL, PRIORITY_MAIL, INTERNATIONAL_MAIL, DOMESTIC_EXPRESS,
    INTERNATIONAL_EXPRESS
}

生成默认绑定和模式

要通过一些 Java 类生成 JiBX 绑定和 XML 模式,首先需要编译这些类,然后运行 JiBX 发行版的 jibx-tools.jar 中附带的 org.jibx.binding.generator.BindGen 工具。您可以通过命令行直接运行该工具,也可以通过 Ant 之类的构建工具间接运行该工具。

本教程的下载部分包括 Ant build.xml 脚本,其中 compile 目标用于编译示例代码,bindgen 目标用于在编译后的代码上运行 BindGen 程序。

要尝试使用此脚本,请打开已安装下载的 dwcode1 目录中的控制台,然后输入 ant compile bindgen。如果系统中安装了 Ant 并且根据说明安装了下载代码,则应当会看到类似图 1 中所示的输出:

图 1. 使用 Ant 构建
通过代码生成的 Ant 构建输出

您还可以直接从控制台运行 BindGen。为此,需要在 Java 类路径中包括 jibx-tools.jar,以及用作生成输入的编译后的类文件路径。如果需要复制 Ant bindgen 目标的效果,则还需要在命令行中传递类的源文件的根目录。最后,需要列出希望用于生成的根类。在 UNIX® 和 Linux® 系统中,用于在 dwcode1 目录(假定您遵循了推荐安装说明)中通过控制台复制 Ant bindgen 目标的 Java 命令行(包含单独的一行代码,即使它在显示屏中显示为多行)为:

java -cp ../lib/jibx-tools.jar:bin org.jibx.binding.generator.BindGen 
   -s src org.jibx.starter.Order

On Windows, the command (a single line, regardless of its appearance here) is:

java -cp ..\lib\jibx-tools.jar;bin org.jibx.binding.generator.BindGen 
   -s src org.jibx.starter.Order

许多其他选项可以通过命令行传递给 BindGen。您稍后将在教程中看到这些选项。现在,让我们看一看生成的模式。

生成的工件

清单 2 显示了通过 BindGen(即 starter.xsd)生成的模式输出,其中进行了略微调整以适应页面宽度,并且删除了一些细节。匹配各个 Java 类的模式定义的开始标记用粗体显示以强调结构。

清单 2. 生成的模式
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:tns="http://jibx.org/starter" elementFormDefault="qualified"
  targetNamespace="http://jibx.org/starter">
 <xs:complexType name="address">
  <xs:annotation>
   <xs:documentation>Address information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
   <xs:element type="xs:string" name="street1" minOccurs="0">
    <xs:annotation>
     <xs:documentation>First line of street information (required).</xs:documentation>
    </xs:annotation>
   </xs:element>
   ...
  </xs:sequence>
 </xs:complexType>
 <xs:element type="tns:order" name="order"/>
 <xs:complexType name="order">
  <xs:annotation>
   <xs:documentation>Order information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
   <xs:element name="customer" minOccurs="0">
    <xs:complexType>
     ...
    </xs:complexType>
   </xs:element>
   <xs:element type="tns:address" name="billTo" minOccurs="0">
    <xs:annotation>
     <xs:documentation>Billing address information.</xs:documentation>
    </xs:annotation>
   </xs:element>
   <xs:element name="shipping" minOccurs="0">
    <xs:simpleType>
     <xs:annotation>
      <xs:documentation>Supported shipment methods. The "INTERNATIONAL" shipment methods
        can only be used for orders with shipping addresses outside the U.S., and one of
        these methods is required in this case.</xs:documentation>
     </xs:annotation>
     <xs:restriction base="xs:string">
      <xs:enumeration value="STANDARD_MAIL"/>
      ...
     </xs:restriction>
    </xs:simpleType>
   </xs:element>
   <xs:element type="tns:address" name="shipTo" minOccurs="0">
    <xs:annotation>
     <xs:documentation>Shipping address information. If missing, the billing address is
       also used as the shipping address.</xs:documentation>
    </xs:annotation>
   </xs:element>
   <xs:element name="item" minOccurs="0" maxOccurs="unbounded">
    <xs:complexType>
     <xs:sequence>
      <xs:element type="xs:string" name="id" minOccurs="0">
       <xs:annotation>
        <xs:documentation>Stock identifier. This is expected to be 12 characters in
          length, with two leading alpha characters followed by ten decimal
          digits.</xs:documentation>
       </xs:annotation>
      </xs:element>
      <xs:element type="xs:string" name="description" minOccurs="0">
       <xs:annotation>
        <xs:documentation>Text description of item.</xs:documentation>
       </xs:annotation>
      </xs:element>
     </xs:sequence>
     <xs:attribute type="xs:int" use="required" name="quantity">
      <xs:annotation>
       <xs:documentation>Number of units ordered.</xs:documentation>
      </xs:annotation>
     </xs:attribute>
     <xs:attribute type="xs:float" use="required" name="price">
      <xs:annotation>
       <xs:documentation>Price per unit.</xs:documentation>
      </xs:annotation>
     </xs:attribute>
    </xs:complexType>
   </xs:element>
  </xs:sequence>
  <xs:attribute type="xs:long" use="required" name="orderNumber"/>
  <xs:attribute type="xs:date" name="orderDate">
   <xs:annotation>
    <xs:documentation>Date order was placed with server.</xs:documentation>
   </xs:annotation>
  </xs:attribute>
  <xs:attribute type="xs:date" name="shipDate">
   <xs:annotation>
    <xs:documentation>
     <![CDATA[Date order was shipped. This will be <code>null</code> if the order
       has not yet shipped.]]></xs:documentation>
   </xs:annotation>
  </xs:attribute>
 </xs:complexType>
</xs:schema>

默认情况下,BindGen 将为只使用一次的类型生成带有嵌套的 complexTypesimpleType 定义的模式,并为使用多次的类型生成带有各种定义的模式。在这种情况下,嵌套的样式将得到只有 3 个全局定义的模式:addressorder 复杂类型以及 order 元素。Order 类在两个位置使用了 Address 类(表示帐单地址和送货地址),因此该类在模式中是由单独的全局定义表示的(仅当定义为全局定义时,模式才允许您重用定义)。Java 数据结构中的其他类(CustomerItemShipping)都只在 Order 类中被引用了一次,因此相应的类型定义是直接嵌入到 order 模式类型定义中的。

可以通过输入类中的 Javadoc 生成模式文档,这是 BindGen 比较棒的功能之一。在 清单 2 中,您可以看到 清单 1 中带有 Javadoc 的各个字段的模式文档,以及与带有 Javadoc 的类对应的各个全局类型的模式文档。BindGen 的默认处理并不能使所有形式的 Javadoc 与模式组件相匹配 — 并且某些 Javadoc(例如关于 “get” 访问方法的 Javadoc)在转换成模式文档后可能看上去很奇怪 — 但是得到的模式文档对于阐明 XML 表示的正确用法极为有用。如果需要在转换过程中对文本进行某些更改(例如从 “get” 方法 Javadoc 中去掉 “Get the ...” 引导语句),您甚至可以为用作模式文档的 Javadoc 定义您自己的 formatter 类。

仅当您可以获得类的源代码并且为 BindGen 提供一个实参告诉它根目录路径时,才可以使用这项 Javadoc 转换功能。在我先前提供的命令行样例中(请参阅 生成默认绑定和模式),提供的源代码路径为 -s src

生成的 JiBX 绑定

除了模式定义之外,BindGen 还将生成 JiBX 绑定定义(在本例中为 binding.xml 文件),该绑定定义将告诉 JiBX 绑定编译器如何在 Java 类与 XML 之间进行转换。实际上,该绑定定义是 BindGen 的主要输出,同时通过绑定生成了模式。绑定定义包含 JiBX 所完成的转换的完整信息,因此它们必然非常复杂。幸运的是,使用 BindGen 绑定和模式生成,您无需了解绑定定义即可使用 JiBX,因此本教程不会介绍这部分详细信息。


处理 XML 文档

在本节中,您将了解如何在运行时运行 JiBX 绑定编译器和使用 JiBX,从而处理 XML 文档。

运行 JiBX 绑定编译器

要在处理 XML 文档时使用生成的绑定定义,首先需要运行 JiBX 绑定编译器工具。按照绑定定义的指定,绑定编译器将把字节码添加到编译后的类文件,这些文件实际实现了与 XML 之间的来回转换。每次重新编译 Java 类或修改绑定定义时,都必须运行绑定编译器,因此一般最好把绑定编译器步骤添加到项目的标准构建流程中。

jibx-bind.jar 中的 JiBX 发行版附带了绑定编译器。JiBX 文档将提供通过各种方法运行绑定编译器的完整信息,包括如何在运行时而非在构建时运行绑定编译器。JiBX 还提供了 Eclipse 和 IntelliJ IDEA 的插件,这样在使用这些 IDE 时将自动运行绑定编译器。

根据本教程的目的,您将把一切简单化并且只通过 Ant 使用 build.xml 的 bind 目标运行绑定编译器。假定您已经运行了 compilebindgen 目标,图 2 将显示运行此目标时应当会看到的输出(您还可以通过在命令行中按顺序列出这些目标来运行全部三个目标:ant compile bindgen bind)。

图 2. Ant 构建 bind 任务
绑定编译器的 Ant 构建输出

在运行时使用 JiBX

清单 3 显示了匹配生成模式的简单测试文档,包含在教程的代码下载中,名为 data.xml:

清单 3. 默认绑定测试文档
<order orderNumber="12345678" orderDate="2008-10-18" shipDate="2008-10-22"
    xmlns="http://jibx.org/starter">
  <customer customerNumber="5678">
    <firstName>John</firstName>
    <lastName>Smith</lastName>
  </customer>
  <billTo>
    <street1>12345 Happy Lane</street1>
    <city>Plunk</city>
    <state>WA</state>
    <postCode>98059</postCode>
    <country>USA</country>
  </billTo>
  <shipping>PRIORITY_MAIL</shipping>
  <shipTo>
    <street1>333 River Avenue</street1>
    <city>Kirkland</city>
    <state>WA</state>
    <postCode>98034</postCode>
    <country>USA</country>
  </shipTo>
  <item quantity="1" price="5.99">
    <id>AC4983498512</id>
    <description>Left-handed widget</description>
  </item>
  <item quantity="2" price="9.50">
    <id>IW2349050499</id>
    <description>Right-handed widget</description>
  </item>
  <item quantity="1" price="8.95">
    <id>RC3000488209</id>
    <description>High-speed MP3 rewinder</description>
  </item>
</order>

下载包还包括一个简单测试程序,它在本文中显示为 清单 4,用于演示如何使用 JiBX 解组编组 文档(编组是在内存中生成对象的 XML 表示的过程,可能包括从初始对象链接的对象;解组是编组的反向过程,它将通过 XML 表示在内存中构建一个对象(还有可能是一些链接的对象)。Ant run 目标将执行此测试程序,使用 清单 3 文档作为输入并把编组后的文档副本写到名为 out.xml 的文件中。

清单 4. 测试程序
public class Test
{
    /**
     * Unmarshal the sample document from a file, compute and set order total, then
     * marshal it back out to another file.
     * 
     * @param args 
     */
    public static void main(String[] args) {
        if (args.length < 2) {
            System.out.println("Usage: java -cp ... " +
                "org.jibx.starter.Test in-file out-file");
            System.exit(0);
        }
        try {
            
            // unmarshal customer information from file
            IBindingFactory bfact = BindingDirectory.getFactory(Order.class);
            IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
            FileInputStream in = new FileInputStream(args[0]);
            Order order = (Order)uctx.unmarshalDocument(in, null);
            
            // compute the total amount of the order
            float total = 0.0f;
            for (Iterator<Item> iter = order.getItems().iterator(); iter.hasNext();) {
                Item item = iter.next();
                total += item.getPrice() * item.getQuantity();
            }
            order.setTotal(new Float(total));
            
            // marshal object back out to file (with nice indentation, as UTF-8)
            IMarshallingContext mctx = bfact.createMarshallingContext();
            mctx.setIndent(2);
            FileOutputStream out = new FileOutputStream(args[1]);
            mctx.setOutput(out, null);
            mctx.marshalDocument(order);
            System.out.println("Processed order with " +  order.getItems().size() +
                " items and total value " + total);
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            System.exit(1);
        } catch (JiBXException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
}

图 3 显示了运行 run 目标时应当会看到的输出:

图 3. Ant 构建 run 任务
运行测试程序得到的 Ant 构建输出

您可以检查生成的 out.xml 文件,查看它与 清单 3 所示的初始输入之间的匹配程度。除了名称空间声明和属性顺序以及输出中添加的 total 属性(由测试程序计算和设置)之外,两个文档应当完全相同。情况不会永远是这样!像大多数形式的数据绑定一样,JiBX 只处理文档中的 “重要” 数据(意味着应用程序所使用的那些值)。在解组文档时,文档的不重要部分(例如开始或结束标记内的空白,元素之间的文本及注释)将丢失。在本例中,输入文档和输出文档之所以如此相似,部分原因是 清单 4 中的代码把输出格式设为在每个元素嵌套级别使用两个空格的缩进,这与输入文档相匹配。

细心的读者会注意到,在输出文档的项目清单部分(如清单 5 所示)中,输入与输出之间似乎 存在一个很大的差异:

清单 5. 输出文档的项目清单
<item quantity="1" price="5.99">
    <id>AC4983498512</id>
    <description>Left-handed widget</description>
  </item>
  <item quantity="2" price="9.5">
    <id>IW2349050499</id>
    <description>Right-handed widget</description>
  </item>
  <item quantity="1" price="8.95">
    <id>RC3000488209</id>
    <description>High-speed MP3 rewinder</description>
  </item>

如果将 清单 5 中用粗体显示的行与 清单 3 初始文档中的对应行相比较,您可以看到价格已经从 9.50 变为 9.5,小数点最后位的零被去掉了。可是,这并不是错误。价格值使用的表示是 float,并且根据 Java 和 XML 模式,小数点前面的零和后面的零对于 float 来说并不重要。


BindGen 自定义

在本节中,您将了解如何自定义 BindGen 操作以控制数据的 XML 表示、更改名称及名称空间的样式以及控制模式结构的某些方面。

自定义 BindGen 操作

BindGen 支持对绑定和模式生成的各个方面进行大量自定义。要应用的自定义集将作为 XML 文档传递给 BindGen,该文档中拥有与 Java 代码结构对应的嵌套元素。清单 6 给出了简单示例:

清单 6. 简单的自定义示例
<custom>
  <package name="org.jibx.starter" property-access="true">
    <class name="Address" includes="street1 street2 city state postCode country"/>
    <class name="Item" excludes="description"/>
  </package>
</custom>

本例将处理单个 Java 代码包,因此 清单 6 仅使用 <custom> 根元素的一个 <package> 子元素。<package><class> 自定义元素将使用与所有被包含的 <package> 元素相关的名称属性,因此在 清单 6 示例中,每个 <class> 元素仅需要一个简单的类名。<package> 元素可以相互嵌套,因此如果跨越包的层次结构处理类,则使用嵌套的 <package> 元素处理所有选项将十分轻松。嵌套结构尤为便利,因为正如我稍后将在本节中讨论的那样,许多自定义属性都是通过元素嵌套继承的。可是,使用嵌套是可选的 — 如果需要,您也可以完全跳过 <package> 元素,并直接使用拥有完全限定类名的 <class> 元素。

使用 -c file-path 命令格式,把自定义文件作为命令行参数传递给 BindGen。自定义永远是可选的,并且您永远不需要使用自定义文件,除非需要更改默认的 BindGen 行为。

控制 BindGen 使用代码的方式

BindGen 通过对 Java 类的默认处理可以完成某种程度的工作,但是在没有用户指导的情况下,可以完成的工作是有限的。例如,默认处理是在 XML 表示中包括除了 static、transient 或 final 字段以外的所有字段。使用这种方法对于表示简单数据对象的类来说没有问题;但是,如果类包括状态信息或计算值,则最终的 XML 表示可能包括不想公开到类之外的值。

自定义允许您通过两种方式控制 BindGen 在 XML 表示中使用的内容。首先,您可以轻松地使用 bean 样式的 getXXX()setXXX()isXXX() 访问方法,而不是直接访问字段。其次,您可以选择是列出需要在类的 XML 表示中包括的值,还是列出需要排除的值。清单 6 中的自定义演示了这两个技巧。

单向转换

本教程使用 JiBX 进行 Java 数据结构与 XML 文档之间的双向转换。BindGen 还支持生成单向转换,在某些情况下生成单向转换可能会更方便。例如,值对象类通常是不可修改的,并且只定义 final 字段和读取(“get”)访问方法。这使得值对象类很难用于 BindGen 的双向转换。如果改为告诉 BindGen 生成仅执行输出的转换,它将轻松地处理您需要的字段或属性。要生成单向转换,请在自定义的根 <custom> 元素中使用 direction="output"direction="input"

清单 6 中的 <package> 元素将使用 property-access="true" 属性来告诉 BindGen,当确定要在 XML 表示中包含哪些值时,查找公共的非静态访问方法定义的 bean 样式的属性,而不是查找字段定义的 bean 样式的属性。此属性是继承自定义设置的一个例子,继承的自定义设置将应用到带有该属性的元素内嵌套的所有内容中。在 清单 6 示例中,设置将应用到两个嵌套的 <class> 元素中。它还将应用到包中的所有其他类中,即使其他类中没有 <class> 自定义元素。除了确定如何从类表示中找到值之外,property-access 设置还将控制如何通过生成的 JiBX 代码访问值 — 直接通过字段还是通过调用访问方法。

清单 6 中的第一个 <class> 元素将使用 includes="street1 street2 city state postCode country" 属性列出 BindGen 需要包含在 XML 表示中的类的特定值。清单中的第二个 <class> 元素将使用 excludes="description" 属性,该属性将列出要从 XML 表示中排除的值。由于对于值使用的是属性访问而非字段访问,因此这些名称与 get/set/is 访问方法所定义的属性相匹配。如果使用字段,则值名称将与字段名称相匹配。

custgen1 Ant 目标将使用 清单 6 中的自定义操作运行 BindGen。此目标是先前所示的 bindgen 目标的替代目标,因此要运行完整的构建,您最好使用 Ant 命令行:ant compile custgen1 bind。清单 7 显示了在此目标运行时生成的模式中的项目类型定义:

清单 7. 自定义模式输出片段
<xs:element name="item" minOccurs="0" maxOccurs="unbounded">
  <xs:complexType>
    <xs:sequence>
      <xs:element type="xs:string" name="id" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:int" use="required" name="quantity"/>
    <xs:attribute type="xs:float" use="required" name="price"/>
  </xs:complexType>
</xs:element>

您可以从 清单 7 中看出,模式表示现在缺少了描述值,正如自定义指定的那样。

在使用此自定义时,您需要使用其他 XML 文档作为输入,因为不再使用初始 XML 中提供的 <description> 元素。Ant run1 目标将运行使用 data1.xml 作为输入并生成 out1.xml 作为输出的测试程序。您还可以用 custom1 Ant 目标运行从编译源代码到运行测试程序的整个过程。

控制实例创建

还可以使用自定义控制解组期间的实例创建。默认情况下,JiBX 期望为每个类定义无实参(默认)的构造函数(Java 编译器将自动生成这些构造函数,如果您不定义任何其他构造函数的话)。在解组过程中需要类的新实例时,JiBX 将使用无实参构造函数创建实例。如果您的某些类只定义带有实参的构造函数,则可以使用 BindGen 自定义,将这些构造函数变成 JiBX 可以使用的构造函数。实现此目的一种方法是定义创建类实例时使用的工厂方法,其中在 <class> 自定义元素中使用 factory="xxx" 属性,以提供返回类实例的静态方法的完全限定名称(带有前导包和类信息)。您还可以在根 <custom> 元素中添加 add-constructors="true",它将生成一个根据需要向类中添加无实参构造函数的绑定。这第二种方法对于普通数据类是起作用的,但是您仍然需要提供所有实例或抽象类的工厂(因为它是绝不可以直接构造的)。当然,如果要生成仅执行输出的绑定(请参阅 单向转换 侧栏),则实例创建不成问题,并且您不需要考虑构造函数。

处理输入类的其他自定义

BindGen 支持许多其他类型的自定义,用于控制 BindGen 处理 Java 输入类的方式。例如,如果对 Java 字段名使用命名约定,则可以通过使用 strip-prefixesstrip-suffixes 属性将 BindGen 配置为忽略特殊的前缀或后缀字符串(例如,如果要忽略前导的 m_s_ 前缀,则需使用 strip-prefixes="m_ s_")。这些对字段名的修改需要在将字段匹配到其他自定义中使用的值名称之前应用,并且在通过字段名生成 XML 名称时也将应用这些修改。

您还可以使用嵌套的 <value> 元素自定义类中各个字段或 bean 属性的处理方式。您将在后面的示例中看到如何使用这些值自定义元素。

控制 XML 表示

除了控制 BindGen 解析 Java 代码的方法之外,您还可以使用自定义控制数据的 XML 表示。无论值是可选的还是必要的,这些 XML 自定义都包括值的实际表示(作为元素或属性)、元素和属性的顺序和名称等等。

前面 清单 6 中的自定义示例演示了对于第一个 <class> 元素使用的 includes="street1 street2 city state postCode country" 属性形式的一个 XML 自定义。我讨论了此自定义如何从类中选择包含在 XML 表示中的值。它还将控制 XML 表示,因为列出值的顺序将成为它们在 XML 表示中的顺序。这对于在 XML 中总是被视为无序的属性来说不是重要的问题,但是对于元素来说十分重要。

如果没有<class> 自定义中使用 includes 属性指定值的顺序,BindGen 将对类使用 Java 反射,按照值的分发顺序生成值。对于大多数 Java 编译器和 JVM,此反射顺序将与 Java 源代码中的定义顺序将匹配。但是,Java 编译器和 JVM 不是必须 要保留来自源代码的这个顺序,因此某些编译器或 JVM 可能导致 BindGen 更改子元素的顺序。如果您希望在无论使用哪个 Java 编译器和 JVM 的情况下都确保 XML 表示始终相同,使用 includes 属性可以帮助您轻松地固定顺序。

您还可以使用 includes 属性控制值的 XML 表示。BindGen 允许在列表中的各个名称上使用前导标志字符以指名表示:@ 表示属性,/ 表示属性。因此如果把 清单 6 的自定义更改为 includes="street1 street2 city state @postCode country",则邮政编码值的表示将从子元素变为属性。

控制必需状态

另一项轻松的自定义是使用 <class> 元素的 requiredsoptionals 属性,可以控制是否将值设为可选值,还是设为必需值。和使用 includes 属性一样,您可以在 requiredsoptionals 列表中的名称前面加一个标志字符,表示是将它们设为子元素,还是设为属性。

默认情况下,BindGen 将把所有原语值和简单对象值(带有直接的 XML 等效类型而非 String 的类)处理为属性,并把所有复杂对象值处理为子元素。所有原语值都将被处理为必需值,而所有对象值都将被处理为可选值。除了通过使用 includesrequiredsoptionals 元素在 <class> 自定义级别覆盖这些默认值之外,您还可以通过在任意自定义级别(<custom><package><class> 元素)中设置 value-style="element" 属性,将默认表示改为对所有值使用元素。您还可以使用 require 属性来控制:在 XML 中,哪些类型应当被处理为必需值:

  • require="none" 将把??有内容都处理为可选值。
  • require="primitives" 是默认值,仅将原语值处理为必需值。
  • require="objects" 与默认值相反,将把原语值设为可选值,将对象类型处理为必需值。
  • require="all" 将把所有值默认处理为必需值。

清单 8 显示了教程下载部分的 dwcode1 目录中的 custom2.xml 自定义文件,演示了我在本节中讨论过的几项功能:

清单 8. 自定义顺序、必需状态及表示
<custom property-access="true">
  <package name="org.jibx.starter">
    <class name="Address" includes="street1 street2 city @state @postCode country"
        requireds="street1 city"/>
    <class name="Customer" includes="customerNumber firstName lastName"
        requireds="lastName firstName /customerNumber"/>
    <class name="Item" excludes="description" requireds="@id quantity price"/>
    <class name="Order" requireds="/orderNumber customer billTo shipping orderDate"/>
  </package>
</custom>

您可以通过使用 Ant custgen2 目标(ant compile custgen2 bind,用于运行完整的构建)尝试这组自定义。清单 9 显示了使用这些自定义的生成模式的一部分,显示了结果顺序、必需状态(minOccurs="0" 在模式中被默认为是必需的,表示可选的元素,use="required" 在模式中被默认为是可选的,表示必需的属性)和元素或属性表示:

清单 9. 使用自定义生成的模式
<xs:complexType name="order">
  <xs:annotation>
    <xs:documentation>Order information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
    <xs:element type="xs:long" name="orderNumber">
      <xs:annotation>
        <xs:documentation>Get the order number.</xs:documentation>
      </xs:annotation>
    </xs:element>
    <xs:element name="customer">
      <xs:complexType>
        <xs:sequence>
          <xs:element type="xs:long" name="customerNumber"/>
          <xs:element type="xs:string" name="firstName"/>
          <xs:element type="xs:string" name="lastName"/>
        </xs:sequence>
      </xs:complexType>
    </xs:element>
    ...
  </xs:sequence>
  <xs:attribute type="xs:date" use="required" name="orderDate"/>
  <xs:attribute type="xs:date" name="shipDate"/>
  <xs:attribute type="xs:float" name="total"/>
</xs:complexType>
<xs:element type="tns:order" name="order"/>
<xs:complexType name="address">
  <xs:annotation>
    <xs:documentation>Address information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
    <xs:element type="xs:string" name="street1"/>
    <xs:element type="xs:string" name="street2" minOccurs="0"/>
    <xs:element type="xs:string" name="city"/>
    <xs:element type="xs:string" name="country" minOccurs="0"/>
  </xs:sequence>
  <xs:attribute type="xs:string" name="state"/>
  <xs:attribute type="xs:string" name="postCode"/>
</xs:complexType>

在使用 bind Ant 任务编译绑定之后,您可以使用以 data2.xml 测试文档为输入并生成输出 out2.xml 的 run2 任务测试此模式。您还可以从编译开始运行整个过程以用 custom2 目标进行测试。清单 10 显示了测试文档:

清单 10. 匹配自定义的测试文档
<order orderDate="2008-10-18" shipDate="2008-10-22" xmlns="http://jibx.org/starter">
  <orderNumber>12345678</orderNumber>
  <customer>
    <customerNumber>5678</customerNumber>
    <firstName>John</firstName>
    <lastName>Smith</lastName>
  </customer>
  <billTo state="WA" postCode="98059">
    <street1>12345 Happy Lane</street1>
    <city>Plunk</city>
    <country>USA</country>
  </billTo>
  <shipping>PRIORITY_MAIL</shipping>
  <shipTo state="WA" postCode="98034">
    <street1>333 River Avenue</street1>
    <city>Kirkland</city>
  </shipTo>
  <item quantity="1" price="5.99" id="8394983498512"/>
  <item quantity="2" price="9.50" id="9912349050499"/>
  <item quantity="1" price="8.95" id="1293000488209"/>
</order>

比较 清单 10清单 3 所示的初始测试文档,看一看自定义如何改变数据的 XML 表示(包括将排列项表示改为空元素,这是一种比原来更紧凑的表示)。

控制名称和名称空间

Java 名称通常使用 “大小写混合" 样式:名称大部分是小写的,但是每个单词的首字母是大写的。对于字段或属性名称,首字母大写只适用于第一个单词之后的单词(得到诸如 postCodecustomerNumber 之类的名称)。XML 名称不是标准化的,并且通常使用几种不同的样式。这些样式包括首字母小写的大小写混合样式(Java 字段和属性名称样式)、首字母大写的大小写混合(Java 类名样式)、连字符分隔符(用连字符分隔单词)样式、点分隔符(用点分隔单词)样式以及下划线分隔符(用下划线分隔单词)样式。

默认情况下,BindGen 对 XML 名称采取大小写混合样式,但是您可以通过在任意自定义级别中设置 name-style 属性(<custom><package><class> 元素)轻松地更改此样式。此属性允许的值与上面列出的各种 XML 样式相匹配:

  • camel-case(默认)
  • upper-camel-case
  • hyphenated
  • dotted
  • underscored

您还可以使用专门针对值的自定义设置该值的 XML 名称。使用单独的值自定义将使您可以完全控制该值的访问方法及在 XML 中的表示方法。基于您已经在前面示例中看到的相同示例代码,清单 11 将给出若干个将自定义元素用于单独值的示例:

清单 11. 自定义名称和名称空间
<custom property-access="true" name-style="hyphenated" namespace="http://jibx.org/custom"
    namespace-style="fixed">
  <package name="org.jibx.starter">
    <class name="Address" includes="street1 street2 city @state @postCode country"
        requireds="street1 city"/>
    <class name="Customer" includes="customerNumber firstName lastName"
        requireds="lastName firstName /customerNumber"/>
    <class name="Item" excludes="description" requireds="@id quantity price"/>
    <class name="Order" requireds="orderNumber customer billTo shipping orderDate">
     <value property-name="orderNumber" element="order-num"/>
      <value property-name="items" item-name="line-item" element="order-items"/>
    </class>
  </package>
</custom>

清单 11 中的第一个值自定义用于 <class name="Order"...> 元素中的 orderNumber 属性。通过使用 element="order-num" 属性,orderNumber 自定义将告诉 BindGen 将值表示为元素,而不是原语值使用的默认属性形式。第二个自定义用于 items 集合属性。此自定义将使用 item-nameelement 属性。item-name 属性将控制集合所表示的各个值使用的名称,而 element 属性将强制使用提供的名称作为集合中的值的封装元素。

没有名称空间的 XML

所有教程示例都使用 XML 名称空间,因为通常把使用名称空间视为数据交换的最佳实践。如果需要使用没有名称空间的 XML,您可以在任意自定义级别使用 namespace-style="none" 属性彻底关闭所有嵌套组件的名称空间。

清单 11 中的自定义还定义要在 XML 文档中使用的名称空间。前面的示例依赖于 BindGen 对名称空间的默认处理:从 Java 包派生出在 Java 代码的 XML 表示中使用的名称空间 URI。此默认处理把 org.jibx.starter 包转换成了名称空间 URI http://jibx.org/starter。在 清单 11 中,名称空间是通过在根 <custom> 元素中添加一对属性 —namespace="http://jibx.org/custom"namespace-style="fixed" — 来自定义的。这些属性中的第一个属性将定义基本名称空间,而第二个属性将防止根据 Java 包修改名称空间的一般行为。这些属性都是通过嵌套自定义元素继承的,因此可以将其轻松地放到 <package> 元素中,而不是放在 <custom> 元素中。

您可以通过使用 Ant custgen3 目标生成绑定和模式,并使用 run3 目标运行测试(在使用标准 bind 目标运行 JiBX 绑定编译器后 — 或者使用 full3 目标执行整个过程),尝试执行 清单 11 中的自定义。清单 12 显示了用于测试代码的输入文档:

清单 12. 带有自定义名称及名称空间的 XML 样例
<order order-date="2008-10-18" ship-date="2008-10-22" xmlns="http://jibx.org/custom">
  <order-num>12345678</order-num>
  <customer>
    <customer-number>5678</customer-number>
    <first-name>John</first-name>
    <last-name>Smith</last-name>
  </customer>
  <bill-to state="WA" post-code="98059">
    <street1>12345 Happy Lane</street1>
    <city>Plunk</city>
    <country>USA</country>
  </bill-to>
  <shipping>PRIORITY_MAIL</shipping>
  <ship-to state="WA" postCode="98034">
    <street1>333 River Avenue</street1>
    <city>Kirkland</city>
  </ship-to>
  <order-items>
    <line-item quantity="1" price="5.99" id="AC4983498512"/>
    <line-item quantity="2" price="9.50" id="IW2349050499"/>
    <line-item quantity="1" price="8.95" id="RC3000488209"/>
  </order-items>
</order>

如果比较 清单 12清单 10 中的样例,您将看到最新的自定义如何更改了表示。

自定义模式表示

现在,您已经了解了 BindGen 自定义如何更改 Java 数据的 XML 表示。自定义还可用于控制实际模式结构的某些方面。

回想一下,BindGen 默认对全局类型和元素优先使用嵌套定义。如果回顾 清单 9 生成的模式,您将看到此嵌套结构。模式仅使用三个全局定义:addressorder 复杂类型以及 order 元素。Java 数据结构中的其他类(CustomerItemShipping)都只在 Order 类中引用一次,因此相应的类型定义是直接嵌入在 order 模式类型定义中的。

您可以在任意嵌套自定义元素中使用 force-mapping="true" 属性来更改模式样式。清单 13 显示了 custom4.xml 自定义文件,该文件将把此更改添加到匹配 清单 9 生成的模式的 custom2.xml 自定义中:

清单 13. 模式结构的自定义
<custom property-access="true" force-mapping="true">
  <package name="org.jibx.starter">
    <class name="Address" includes="street1 street2 city @state @postCode country"
        requireds="street1 city"/>
    <class name="Customer" includes="customerNumber firstName lastName"
        requireds="lastName firstName /customerNumber"/>
    <class name="Item" excludes="description" requireds="@id quantity price"/>
    <class name="Order" requireds="/orderNumber customer billTo shipping orderDate"/>
  </package>
</custom>

清单 14 显示了得到的模式结构(通过运行 custgen4 Ant 目标生成为 starter.xsd)。此版本的模式表示的 XML 文档结构与 清单 9 模式相同,但是包括匹配每个 Java 类的单独类型定义。

清单 14. 自定义的模式结构
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:tns="http://jibx.org/starter" elementFormDefault="qualified"
    targetNamespace="http://jibx.org/starter">
  <xs:simpleType name="shipping">
    <xs:annotation>
      <xs:documentation>Supported shipment methods. The "INTERNATIONAL" shipment
      methods can only be used for orders with shipping addresses outside the U.S., and
      one of these methods is required in this case.</xs:documentation>
    </xs:annotation>
    <xs:restriction base="xs:string">
      ...
    </xs:restriction>
  </xs:simpleType>
  <xs:complexType name="item">
    <xs:annotation>
      <xs:documentation>Order line item information.</xs:documentation>
    </xs:annotation>
    <xs:sequence/>
    <xs:attribute type="xs:string" use="required" name="id"/>
    <xs:attribute type="xs:int" use="required" name="quantity"/>
    <xs:attribute type="xs:float" use="required" name="price"/>
  </xs:complexType>
  <xs:element type="tns:order" name="order"/>
  <xs:complexType name="address">
    <xs:annotation>
      <xs:documentation>Address information.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:string" name="street1"/>
      <xs:element type="xs:string" name="street2" minOccurs="0"/>
      <xs:element type="xs:string" name="city"/>
      <xs:element type="xs:string" name="country" minOccurs="0"/>
    </xs:sequence>
    <xs:attribute type="xs:string" name="state"/>
    <xs:attribute type="xs:string" name="postCode"/>
  </xs:complexType>
  <xs:complexType name="customer">
    <xs:annotation>
      <xs:documentation>Customer information.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:long" name="customerNumber"/>
      <xs:element type="xs:string" name="firstName"/>
      <xs:element type="xs:string" name="lastName"/>
    </xs:sequence>
  </xs:complexType>
  <xs:complexType name="order">
    <xs:annotation>
      <xs:documentation>Order information.</xs:documentation>
    </xs:annotation>
    <xs:sequence>
      <xs:element type="xs:long" name="orderNumber">
        <xs:annotation>
          <xs:documentation>Get the order number.</xs:documentation>
        </xs:annotation>
      </xs:element>
      <xs:element type="tns:customer" name="customer"/>
      <xs:element type="tns:address" name="billTo"/>
      <xs:element type="tns:shipping" name="shipping"/>
      <xs:element type="tns:address" name="shipTo" minOccurs="0"/>
      <xs:element type="tns:item" name="item" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
    <xs:attribute type="xs:date" use="required" name="orderDate"/>
    <xs:attribute type="xs:date" name="shipDate"/>
    <xs:attribute type="xs:float" name="total"/>
  </xs:complexType>
</xs:schema>

清单 14 所示的类型模式称为 “Venetian Blind” 样式模式,常用于复杂的 XML 结构定义。通过分隔各个类型定义,这种模式样式使您可以在修改或扩展模式时轻松地重用组件结构。如果只是计划使用 Java 代码作为进一步更改的基础(每次代码更改时都要再次运行 BindGen),则 Venetian Blind 样式的灵活性可能并不重要,但是如果想要使用模式作为以后开发的基础,则非常适合使用 Venetian Blind。


BindGen 命令行参数

除了在教程代码中使用的那些命令行参数之外,BindGen 还支持若干个命令行参数。表 1 列出了最重要的选项:

表 1. BuildGen 命令行选项
命令用途
-b name生成根绑定定义文件名(默认名称为 binding.xml)
-c path输入自定义文件的路径
-n uri=name,...提供模式名称空间 URI 和文件名对(默认通过模式名称空间 URI 生成文件名)
-p path,...载入 Java 类文件的路径(默认值为运行 BindGen 所使用的类路径)
-s path,...载入 Java 源文件的路径(默认情况下不使用源代码)
-t path生成输出的目标目录路径(默认值为当前目录)
-w在生成输出前从目标目录中删除所有文件(如果目标目录就是当前目录,则忽略)

通过使用 -- 作为自定义属性值的特殊前缀,您还可以将全局定义作为命令行参数传递给 BindGen,而无需创建自定义文件。因此要设置 清单 13 自定义中所使用的全局选项,您需要向 BindGen 命令行中添加 --property-access=true --force-mapping=true。在使用这项技巧时,不需要对属性值使用引号。如果需要设置获取多个值的列表的自定义,只需使用逗号而不要使用空格作为各个值之间的分隔符(这样可以忽略字段名中的前缀 m_s_,例如,使用命令行参数 --strip-prefixes=m_,s_)。


结束语

在本教程中,您了解了使用 JiBX 通过 Java 代码生成 XML 模式定义,然后将匹配该模式的文档与 Java 数据结构来回转换。除了本教程中介绍的自定义之外,还有许多其他自定义可用于控制模式生成。JiBX 文档将提供所有这些自定义选项的完整信息,以及通过代码生成模式的更多示例。

通过使用实际的绑定定义,您可以进一步使用 JiBX,这将使您可以控制转换过程的每一个步骤。使用绑定定义中构建的用户扩展钩(hook),您可以轻松地将自己的代码添加到转换过程中,作为其中的一部分执行。您甚至可以创建自己的自定义编组和解组代码,这些代码可以有选择性地从 JiBX 所生成的代码处接管控制权,以处理独特的 XML 或 Java 数据结构。JiBX 文档包括演示使用绑定定义的各个方面的教程,包括这些扩展功能,以及有关所有详细信息的参考文档。

当您需要快速地为数据交换开发模式定义,而不希望了解有关模式的大量信息时,使用 JiBX 尤为方便。XML Schema 标准十分复杂,并且用于处理模式定义的工具为重构模式提供的支持很少。如本教程所示,通过使用 Java 代码和 BindGen 作为模式开发的基础,您可以应用 Java IDE 的全部灵活性快速而轻松地创建模式定义,而无需费心研究如何使用 JiBX。

JiBX 还提供了一个基于 Java 代码为 Web 服务生成完整 WSDL 和模式定义的工具。此工具名为 Jibx2Wsdl,构建在 BindGen 之上。您可以将本文中讨论的所有 BindGen 自定义用于数据类,作为您自己的服务方法的输入和输出,这样生成的模式将反映您的偏好。JiBX 文档将提供如何使用 Jibx2Wsdl 的详细信息。

第 2 部分 中,您将了解如何使用 JiBX 通过 XML 模式定义生成 Java 代码。


下载

描述名字大小
本教程的样例代码j-jibx1.zip13 KB

参考资料

学习

获得产品和技术

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology, XML, Open source
ArticleID=381822
ArticleTitle=JiBX 1.2,第 1 部分: 从 Java 代码到 XML 模式
publish-date=04142009