程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> JiBX 1.2,第2部分: 從XML模式到Java代碼(一)

JiBX 1.2,第2部分: 從XML模式到Java代碼(一)

編輯:關於JAVA

通過 XML 模式生成更干淨的自定義 Java 代碼

通過 XML 模式定義生成代碼被廣泛用於各種類型的 XML 數據交換,包括 Web 服務在內。大多數數據綁定工具都是根據模式嚴格地組織生成的代碼 — 甚至根據可能與應用程序不相關的模式方面。本教程是共兩部分的 系列教程 的第二部分,將介紹 JiBX 1.2 如何通過更好地解析模式和消除不必要的類混亂來生成更干淨的代碼。您還將看到如何自定義生成的代碼以更好地滿足需求,包括輕松地消除不必要的模式組件的自定義。

開始之前

關於本教程

JiBX 是 XML 數據與 Java™ 對象的綁定工具。JiBX 數據綁定一直以來被認為是綁定 Java 代碼與 XML 的最快且最靈活的方法。但是其綁定定義的復雜性及對於廣泛使用的 XML 模式定義的有限支持經常讓用戶感到失望。幸運的是,1.2 版的 JiBX 一直致力於消除這些問題。在本教程中,您將了解如何使用 JiBX 1.2 的新功能從 XML 模式定義輕松地生成 Java 代碼,並讀取和編寫匹配生成的模式定義的 XML 文檔 — 所有這一切都不需要詳細了解 JiBX 綁定定義。第 1 部分 將介紹相反的一面,即從 Java 代碼生成 XML 模式定義。

目標

本教程將指導您完成使用 JiBX 從 XML 模式定義生成 Java 代碼的過程。您將首先了解如何使用簡單的模式及生成匹配該模式的默認 Java 數據模型,然後使用該數據模型讀取和編寫 XML 文檔。接下來將看到如何使用自定義來修改代碼生成,以使其更好地滿足需求。最後,您將繼續轉向一個更復雜的行業標准模式示例,並探究自定義的強大之處以簡化為該模式生成的數據模型並提高可用性。在閱讀完本教程並且嘗試使用了提供的示例後,您將能夠使用 JiBX 為自己的模式生成自定義的 Java 數據模型。

通過 XML 模式定義生成代碼被廣泛用於各種類型的 XML 數據交換,包括 Web 服務在內。大多數數據綁定工具都是根據模式嚴格地組織生成的代碼 — 甚至根據可能與應用程序不相關的模式方面。本教程是共兩部分的 系列教程 的第二部分,將介紹 JiBX 1.2 如何通過更好地解析模式和消除不必要的類混亂來生成更干淨的代碼。您還將看到如何自定義生成的代碼以更好地滿足需求,包括輕松地消除不必要的模式組件的自定義。

開始之前

關於本教程

JiBX 是 XML 數據與 Java™ 對象的綁定工具。JiBX 數據綁定一直以來被認為是綁定 Java 代碼與 XML 的最快且最靈活的方法。但是其綁定定義的復雜性及對於廣泛使用的 XML 模式定義的有限支持經常讓用戶感到失望。幸運的是,1.2 版的 JiBX 一直致力於消除這些問題。在本教程中,您將了解如何使用 JiBX 1.2 的新功能從 XML 模式定義輕松地生成 Java 代碼,並讀取和編寫匹配生成的模式定義的 XML 文檔 — 所有這一切都不需要詳細了解 JiBX 綁定定義。第 1 部分 將介紹相反的一面,即從 Java 代碼生成 XML 模式定義。

目標

本教程將指導您完成使用 JiBX 從 XML 模式定義生成 Java 代碼的過程。您將首先了解如何使用簡單的模式及生成匹配該模式的默認 Java 數據模型,然後使用該數據模型讀取和編寫 XML 文檔。接下來將看到如何使用自定義來修改代碼生成,以使其更好地滿足需求。最後,您將繼續轉向一個更復雜的行業標准模式示例,並探究自定義的強大之處以簡化為該模式生成的數據模型並提高可用性。在閱讀完本教程並且嘗試使用了提供的示例後,您將能夠使用 JiBX 為自己的模式生成自定義的 Java 數據模型。

先決條件

要理解本教程,您至少要了解 Java 代碼和 XML 的基礎知識。您不需要詳細了解 XML 模式定義,但是略微熟悉模式將幫助您更好地理解示例。

系統要求

要運行示例,您需要安裝:

以下任意一個工具:

Sun's JDK 1.5.0_09(或更高版本)。

IBM Developer Kit for Java technology 1.5.0 SR3。

最新版本的 Apache Ant 構建工具。

本教程中包括 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®,將 dwcode2 目錄從 ZIP 文件中復制到 JiBX 安裝的根目錄中)。此操作應當在 jibx 目錄中創建 dwcode2 子目錄,而且 dwcode2 子目錄中包含示例文件(包括 build.xml、custom.xml 和其他文件)。

樣例代碼包括自動運行 JiBX 工具並處理示例涉及的其他步驟的 Ant 構建文件。如果直接將樣例代碼安裝到 JiBX 安裝目錄中,則構建可以訪問 JiBX JAR 而無需任何附加配置。如果在其他位置安裝樣例代碼,則仍然可以使用 Ant 構建。在這種情況下,您只需編輯樣例代碼目錄中的 build.properties 文件,然後將 jibx-home 屬性的值改為 JiBX 安裝路徑。

通過模式生成默認綁定和代碼

通過 XML 模式定義生成 JiBX 綁定定義及相應的 Java 代碼十分簡單。您將在本節中了解具體操作。

簡單示例模式簡介

我將使用 第 1 部分 中生成的一個模式作為一個簡單示例。清單 1 顯示了該模式的簡短版本,用於表示在線商店的訂單。樣例代碼的 dwcode2 目錄中的 starter.xsd 提供了完整的模式。

清單 1. 第一個示例模式

 
<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:enumeration value="STANDARD_MAIL"/>
   <xs:enumeration value="PRIORITY_MAIL"/>
   <xs:enumeration value="INTERNATIONAL_MAIL"/>
   ...
  </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: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:attribute>
  <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:complexType name="address">
  <xs:annotation>
   <xs:documentation>Address information.</xs:documentation>
  </xs:annotation>
  <xs:sequence>
   <xs:element type="xs:string" name="street1">
    <xs:annotation>
     <xs:documentation>First line of street information (required).
     </xs:documentation>
    </xs:annotation>
   </xs:element>
   ...
  </xs:sequence>
  <xs:attribute type="xs:string" name="state">
   <xs:annotation>
    <xs:documentation>State abbreviation (required for the U.S. and Canada,
    optional otherwise).</xs:documentation>
   </xs:annotation>
  </xs:attribute>
  <xs:attribute type="xs:string" name="postCode">
   <xs:annotation>
    <xs:documentation>Postal code (required for the U.S. and Canada, optional
    otherwise).</xs:documentation>
   </xs:annotation>
  </xs:attribute>
 </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: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 type="xs:long" name="orderNumber"/>
   <xs:element type="tns:customer" name="customer"/>
   <xs:element type="tns:address" name="billTo">
    <xs:annotation>
     <xs:documentation>Billing address information.</xs:documentation>
    </xs:annotation>
   </xs:element>
   ...
   <xs:element type="tns:item" name="item" minOccurs="0" maxOccurs="unbounded"/>
  </xs:sequence>
  <xs:attribute type="xs:date" use="required" name="orderDate">
   <xs:annotation>
    <xs:documentation>Date order was placed with server.</xs:documentation>
   </xs:annotation>
  </xs:attribute>
  ...
 </xs:complexType>
</xs:schema>

生成默認綁定和代碼

要通過 XML 模式生成 JiBX 綁定和 Java 類,您只需運行 JiBX 發行版中的 jibx-tools.jar 附帶的 org.jibx.schema.codegen.CodeGen 工具。您可以通過命令行直接運行該工具,也可以通過 Apache Ant 之類的構建工具間接運行該工具。

本教程的下載部分包括 Ant build.xml 腳本,其中 codegen 目標用於運行生成。

要嘗試使用此腳本,請打開已安裝下載的 dwcode2 目錄中的控制台,然後輸入 ant codegen。如果系統中安裝了 Ant 並且根據說明安裝了下載代碼,則應當會看到類似圖 1 所示的輸出:

圖 1. 使用 Ant 構建

您還可以直接從控制台運行 CodeGen。為此,您需要:

在 Java 類路徑中包括 jibx-tools.jar。

指定 org.jibx.schema.codegen.CodeGen 為要運行的類。

列出要生成的模式定義。

提供的 Ant codegen 目標將使用幾個附加參數告訴 CodeGen 使用 gen/src 目錄作為生成的數據模型包結構的根目錄,並且在運行生成前刪除該目錄中的所有現有文件。下面是用於從 dwcode2 目錄的控制台中復制 Ant codegen 目標的 Java 命令行(假定您遵循了推薦安裝說明):

java -cp ../lib/jibx-tools.jar org.jibx.schema.codegen.CodeGen -t gen/src -w starter.xsd

對於 Windows,該命令為:

java -cp ..\lib\jibx-tools.jar org.jibx.schema.codegen.CodeGen -t gen\src -w starter.xsd

您可以通過命令行向 CodeGen 傳遞許多其他選項。您稍後將在教程中看到這些選項。現在,讓我們看一看生成的 Java 代碼。

生成的工件

生成的代碼由五個類組成,分別對應於 清單 1 模式中的五個全局類型定義。清單 2 顯示了生成的代碼的一些樣例,其中包括 org.jibx.starter.Order 類的摘錄及整個 org.jibx.starter.Shipping 類:

清單 2. 生成的代碼

/**
 * Order information.
 *
 * Schema fragment(s) for this class:
 * <pre>
 * <xs:complexType xmlns:ns="http://jibx.org/starter" 
  xmlns:xs="http://www.w3.org/2001/XMLSchema" name="order">
 *  <xs:sequence>
 *   <xs:element type="xs:long" name="orderNumber"/>
 *   <xs:element type="ns:customer" name="customer"/>
 *   <xs:element type="ns:address" name="billTo"/>
 *   <xs:element type="ns:shipping" name="shipping"/>
 *   <xs:element type="ns:address" name="shipTo" minOccurs="0"/>
 *   <xs:element type="ns: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>
 * </pre>
 */
public class Order
{
  private long orderNumber;
  private Customer customer;
  private Address billTo;
  private Shipping shipping;
  private Address shipTo;
  private List<Item> itemList = new ArrayList<Item>();
  private Date orderDate;
  private Date shipDate;
  private Float total;
  ...
  /**
   * Get the 'shipTo' element value. Shipping address information. If missing, the 
   * billing address is also used as the shipping address.
   */
  public Address getShipTo() {
    return shipTo;
  }
  /**
   * Set the 'shipTo' element value. Shipping address information. If missing, the 
   * billing address is also used as the shipping address.
   */
  public void setShipTo(Address shipTo) {
    this.shipTo = shipTo;
  }
  /**
   * Get the list of 'item' element items.
   */
  public List<Item> getItems() {
    return itemList;
  }
  /**
   * Set the list of 'item' element items.
   */
  public void setItems(List<Item> list) {
    itemList = list;
  }
  ...
}
/**
 * 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.
 *
 * Schema fragment(s) for this class:
 * <pre>
 * <xs:simpleType xmlns:xs="http://www.w3.org/2001/XMLSchema" name="shipping">
 *  <xs:restriction base="xs:string">
 *   <xs:enumeration value="STANDARD_MAIL"/>
 *   <xs:enumeration value="PRIORITY_MAIL"/>
 *   <xs:enumeration value="INTERNATIONAL_MAIL"/>
 *   <xs:enumeration value="DOMESTIC_EXPRESS"/>
 *   <xs:enumeration value="INTERNATIONAL_EXPRESS"/>
 *  </xs:restriction>
 * </xs:simpleType>
 * </pre>
 */
public enum Shipping {
  STANDARD_MAIL, PRIORITY_MAIL, INTERNATIONAL_MAIL, DOMESTIC_EXPRESS, 
  INTERNATIONAL_EXPRESS
}

通過 清單 2 可以看到,CodeGen 在生成的代碼中將模式文檔自動轉換為 Javadoc(在此處顯示為每個類 Javadoc 中的前導注釋,以及顯示為 getShipTo() 和 setShipTo() 方法的注釋部分)。默認情況下,CodeGen 還合並類 Javadoc 中的實際模式定義,而對於 get/set 屬性訪問方法,它將描述與屬性對應的模式組件。

對於重復值,例如清單 1 訂單 complexType 定義中的重復項目元素,CodeGen 將默認生成 Java 5 類型的列表。對於 simpleType 限制枚舉,例如清單 1 中的送貨類型,CodeGen 將默認生成 Java 5 枚舉類型。清單 2 中顯示了為這兩個實例生成的代碼。

生成的 JiBX 綁定

除了生成的代碼之外,CodeGen 還將產生 JiBX 綁定定義(在本例中為 binding.xml 文件),該綁定定義將告訴 JiBX 綁定編譯器如何在 Java 類與 XML 之間進行轉換。綁定定義包含 JiBX 所完成的轉換的完整信息,因此它們必然非常復雜。幸運的是,使用 CodeGen 綁定和代碼生成,您無需了解綁定定義即可使用 JiBX,因此本教程不會介紹這部分的詳細信息。

處理 XML 文檔

在本節中,您將了解如何在運行時運行 JiBX 綁定編譯器和使用 JiBX,從而處理 XML 文檔。

運行 JiBX 綁定編譯器

要在處理 XML 文檔時使用生成的綁定定義,首先需要運行 JiBX 綁定編譯器。按照綁定定義的指定,綁定編譯器將把字節碼添加到編譯後的類文件,這些文件實際實現了與 XML 之間的來回轉換。每次重新編譯 Java 類或修改綁定定義時,都必須運行綁定編譯器,因此一般最好把綁定編譯器步驟添加到項目的標准構建流程中。

jibx-bind.jar 中的 JiBX 發行版附帶了綁定編譯器。JiBX 文檔將提供通過各種方法運行綁定編譯器的完整信息,包括如何在運行應用程序時(而非在構建時)調用綁定編譯器。JiBX 還提供了 Eclipse 和 IntelliJ IDEA 的插件,這樣在使用這些 IDE 時將自動運行綁定編譯器。

根據本教程的目的,您將把一切簡單化並且只通過 Ant 運行綁定編譯器。build.xml 的 compile 目標將通過編譯生成的代碼和提供的測試程序來為綁定做准備,而 bind 目標實際運行綁定編譯器。假定您已經運行了 codegen 目標,圖 2 將顯示運行這些目標時應當會看到的輸出(您還可以通過在命令行中按順序列出這些目標來運行全部三個目標:ant codegen compile bind)。

圖 2. Ant 構建 compile 和 bind 任務

在運行時使用 JiBX

清單 3 顯示了匹配模式的簡單測試文檔,包含在教程的代碼下載中,名為 starter.xml:

清單 3. 訂單模式的測試文檔

 
<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="FA9498349851"/>
 <item quantity="2" price="9.50" id="GC1234905049"/>
 <item quantity="1" price="8.95" id="AX9300048820"/>
</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 任務

這是 第 1 部分 中使用的同一個測試程序,並且同樣具有第一部分教程中討論的限制。就像在第 1 部分中一樣,out.xml 文件包含了將解組原始文檔獲得的訂單數據重新編組後生成的輸出。

CodeGen 自定義簡介

在本節中,您將了解自定義 CodeGen 以控制通過簡單模式生成的代碼結構的基礎知識。

簡單自定義示例

CodeGen 支持在代碼和綁定生成的許多方面進行豐富的自定義。要應用的自定義集將作為 XML 文檔傳遞給 CodeGen,其中包括與模式或模式組件相關的嵌套元素。清單 5 給出了一個簡單示例:

清單 5. 簡單自定義示例

 
<schema prefer-inline="true" show-schema="false" enumeration-type="simple"
 generate-all="false" includes="order item"/>

清單 5 自定義包含單個無名稱空間的模式元素,以及針對特定自定義的幾個不同屬性(到目前為止,您只是在使用單個模式定義,因此可以使用這種非常簡單的自定義形式。稍後在本教程中,您將看到使用多個模式的自定義示例)。第一個自定義屬性 — prefer-inline="true" — 將告訴 CodeGen 內聯只引用一次的模式定義,而不是執行將其保留為單獨類的默認行為。第二個屬性 — show-schema="false" — 將阻止在類 Javadoc 中嵌入模式定義。enumeration-type="simple" 將生成簡單的類型安全枚舉而非 Java 5 枚舉。

最後一對屬性將一起工作。默認情況下,CodeGen 將為指定為輸入的模式中的每個全局類型定義都生成一個單獨的頂級類,並且在為每個 complexType 生成的 JiBX 綁定中生成對應的抽象映射。generate-all="false" 屬性將更改這種默認行為,只顯式地生成特別包括的或引用自 included 類型的那些 complexType。隨後,includes="order item" 屬性將給出要生成的名稱,選擇這些名稱以保持與測試程序的兼容性 — 需要 <order> 元素,原因是它是實例文檔的根元素,並且需要 complexType 項,因為測試程序期望在計算訂單總數時找到此類型的獨立頂級類。

通過使用 Ant custgen 任務而非 codegen 任務(或者只使用 full 任務,該任務將運行完整的 clean custgen compile bind run 目標序列),您可以嘗試這些自定義。清單 6 顯示了生成的代碼片段,您可以將其與 清單 2 所示的默認生成的代碼相比較。除了簡化的類 Javadoc 之外,最大的差別是 Customer 類現在是內聯的,而 Shipping 類現在是使用自定義的類型安全枚舉類的內部類。

清單 6. 用自定義生成的代碼

 
/**
 * Order information.
 */
public class Order
{
  private long orderNumber;
  private long customerCustomerNumber;
  private String customerFirstName;
  private String customerLastName;
  private Address billTo;
  private Shipping shipping;
  private Address shipTo;
  private List<Item> itemList = new ArrayList<Item>();
  private Date orderDate;
  private Date shipDate;
  private Float total;
  ...
  /**
   * 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 static class Shipping
  {
    private final String value;
    public static final Shipping STANDARD_MAIL = new Shipping(
        "STANDARD_MAIL");
    public static final Shipping PRIORITY_MAIL = new Shipping(
        "PRIORITY_MAIL");
    public static final Shipping INTERNATIONAL_MAIL = new Shipping(
        "INTERNATIONAL_MAIL");
    public static final Shipping DOMESTIC_EXPRESS = new Shipping(
        "DOMESTIC_EXPRESS");
    public static final Shipping INTERNATIONAL_EXPRESS = new Shipping(
        "INTERNATIONAL_EXPRESS");
    private static final String[] values = new String[]{"DOMESTIC_EXPRESS",
        "INTERNATIONAL_EXPRESS", "INTERNATIONAL_MAIL", "PRIORITY_MAIL",
        "STANDARD_MAIL"};
    private static final Shipping[] instances = new Shipping[]{
        DOMESTIC_EXPRESS, INTERNATIONAL_EXPRESS, INTERNATIONAL_MAIL,
        PRIORITY_MAIL, STANDARD_MAIL};
 
    private Shipping(String value) {
      this.value = value;
    }
 
    public String toString() {
      return value;
    }
 
    public static Shipping convert(String value) {
      int index = java.util.Arrays.binarySearch(values, value);
      if (index >= 0) {
        return instances[index];
      } else {
        return null;
      }
    }
 
    public static Shipping fromValue(String text) {
      Shipping value = convert(text);
      if (value == null) {
        throw new IllegalArgumentException("Value \'" + text
            + "\' is not allowed");
      } else {
        return value;
      }
    }
  }
}

還有許多其他的自定義也可用於 CodeGen。您稍後將在本教程中看到這些自定義的一些示例,但是為了更好地說明這些自定義的強大之處,有必要繼續介紹一個更復雜的模式。

嘗試一個實際的模式

獨立的模式定義非常適合用於簡單演示,但是在應用到企業應用程序中廣泛使用的復雜模式定義時,它無法讓用戶了解工具的工作原理。現在將以一個符合行業標准的 HR-XML 模式定義為例,繼續介紹一個更實際的示例。

HR-XML TimeCard 模式

HR-XML Consortium 是為開發針對人力資源的 XML 表示的開放標准而成立的組織。它代表著 110 多家企業成員,並且幾乎有 50 家技術公司通過了符合其標准的認證。

本教程中使用的 HR-XML 模式包含 157 個模式,其中混合了頂級文檔定義和常用組件。CodeGen 可以輕松地處理這些模式,但是生成的類數目和相互關系的復雜度掩蓋了模式處理的更有趣方面。為了關注這些細節,這裡使用的 HR-XML 的子集包括 TimeCard 元素的一個頂級文檔定義,以及作為 TimeCard 定義的一部分引用的常用組件 — 總計七個模式定義。

您可以在 hrxml/schemas 目錄下找到本教程中使用的 HR-XML 模式定義子集。清單 7 顯示了經過編輯的 TimeCard 元素定義的主要模式。這將給出一個 HR-XML 模式樣式樣例,該樣例將同時使用嵌套及全局類型的定義,並且比第一個示例包含更廣泛的模式結構,包括:

<xs:choice> 組合器(compositor)(如 TimeCardType 定義中的某些嵌入式 complexType 所示)

<xs:any> 粒子(particle)(查看清單開始部分的 AdditionalDataType 定義)

<xs:simpleType> <union>(查看清單末尾的 TimeCardDuration 定義)

非枚舉型 <xs:simpleType> 限制

清單 7. HR-XML TimeCard 模式

<xs:schema targetNamespace="http://ns.hr-xml.org/2007-04-15" ...
elementFormDefault="qualified" version="2007-04-15">
<xs:import namespace="http://www.w3.org/XML/1998/namespace" ...>
<xs:include schemaLocation="../CPO/EntityIdType.xsd"/>
...
<xs:complexType name="AdditionalDataType" mixed="true">
...
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:any namespace="##any" processContents="strict" minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string"/>
</xs:complexType>
...
<xs:element name="TimeCard" type="TimeCardType"/>
<xs:complexType name="TimeCardType">
<xs:sequence>
<xs:element name="Id" type="EntityIdType" minOccurs="0"/>
<xs:element name="ReportedResource">
<xs:complexType>
<xs:choice>
<xs:element name="Person" type="TimeCardPersonType"/>
<xs:element name="Resource">
<xs:complexType>
<xs:sequence>
<xs:element name="Id" type="EntityIdType"
minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="ResourceName" type="xs:string" minOccurs="0"/>
<xs:element name="AdditionalData" type="AdditionalDataType" minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="ReportedTime" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="PeriodStartDate" type="AnyDateTimeType"/>
<xs:element name="PeriodEndDate" type="AnyDateTimeType"/>
<xs:element name="ReportedPersonAssignment" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="Id" type="EntityIdType" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:choice maxOccurs="unbounded">
<xs:element name="TimeInterval">
<xs:complexType>
<xs:sequence>
<xs:element name="Id" type="EntityIdType" minOccurs="0"/>
<xs:element name="StartDateTime" type="AnyDateTimeType"/>
<xs:choice>
<xs:sequence>
<xs:element name="EndDateTime" type="AnyDateTimeType"/>
<xs:element name="Duration" type="TimeCardDuration" minOccurs="0"/>
</xs:sequence>
<xs:element name="Duration" type="TimeCardDuration"/>
</xs:choice>
<xs:element name="PieceWork" minOccurs="0" maxOccurs="unbounded">
...
</xs:element>
<xs:element name="RateOrAmount" minOccurs="0" maxOccurs="unbounded">
...
</xs:element>
<xs:element name="Allowance" minOccurs="0" maxOccurs="unbounded">
...
</xs:element>
...
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required"/>
...
</xs:complexType>
</xs:element>
<xs:element name="TimeEvent">
...
</xs:element>
<xs:element name="Expense">
...
</xs:element>
<xs:element name="Allowance">
...
</xs:element>
</xs:choice>
...
</xs:sequence>
...
</xs:complexType>
</xs:element>
...
</xs:sequence>
<xs:attribute ref="xml:lang"/>
</xs:complexType>
...
<xs:simpleType name="TimeCardDuration">
<xs:union memberTypes="xs:duration xs:decimal"/>
</xs:simpleType>
</xs:schema>
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved