JiBX 1.2, Phần 1: Từ mã Java thành lược đồ XML
Cải thiện chất lượng lược đồ bằng phép biến đổi tùy chỉnh các mô hình dữ liệu
Java thành tài liệu XML và từ tài liệu XML
Dennis Sosnoski, Nhà tư vấn, Sosnoski Software Solutions, Inc.
Tóm tắt: Các định nghĩa lược đồ XML là cơ sở cho nhiều kiểu trao đổi dữ liệu,
bao gồm hầu hết các dạng dịch vụ web. Nhưng lược đồ XML là một tiêu chuẩn
phức tạp và hầu hết các công cụ để tạo và sửa đổi các định nghĩa lược đồ không đủ
mạnh mẽ hay dễ sử dụng như các công cụ để làm việc với mã Java™. Các đặc tính
mới của JiBX 1.2 mà bạn sẽ tìm hiểu về nó trong hướng dẫn này — Phần 1 của
một loạt bài viết có hai phần — cho phép bạn bắt đầu từ mã Java và dễ dàng tạo ra
các định nghĩa lược đồ có chất lượng khớp với các cấu trúc dữ liệu của bạn. Sau
đó bạn có thể sử dụng trực tiếp các lược đồ này, dù bạn có sử dụng liên kết dữ liệu
JiBX hay không.
Trước khi bạn bắt đầu
Về hướng dẫn này
JiBX là một công cụ để liên kết dữ liệu XML với các đối tượng Java. Liên kết dữ
liệu JiBX đã được biết đến từ lâu như là cách tiếp cận nhanh nhất và linh hoạt nhất
để liên kết mã Java tới XML. Nhưng sự phức tạp của các định nghĩa liên kết JiBX
và sự hỗ trợ còn hạn chế của nó với các định nghĩa lược đồ XML đang được sử
dụng ngày càng rộng rãi hơn đã làm cho những người dùng thất vọng nhiều lần.
May mắn thay, phiên bản 1.2 của JiBX đã tiến một bước dài theo hướng loại bỏ
những vấn đề này. Trong hướng dẫn này, bạn sẽ tìm hiểu về việc sử dụng các đặc
tính mới của JiBX 1.2 để tạo ra các định nghĩa lược đồ XML một cách dễ dàng từ
mã Java hiện có và để đọc và viết các tài liệu khớp với các định nghĩa lược đồ đã
tạo ra — hoàn toàn không cần phải đi vào các chi tiết của các định nghĩa liên kết
của JiBX. Phần 2 trình bày nửa còn lại của vấn đề: bắt đầu từ các định nghĩa lược
đồ XML và tạo mã Java.
Mục tiêu
Hướng dẫn này chỉ dẫn cho bạn về quá trình sử dụng JiBX để tạo ra các định
nghĩa lược đồ XML từ mã Java. Đầu tiên, bạn sẽ thấy làm thế nào để bắt đầu với
một mô hình dữ liệu Java đơn giản và tạo ra một lược đồ mặc định khớp với mô
hình đó. Trên cơ sở đó, bạn sẽ tìm hiểu cách làm thế nào để bạn có thể dễ dàng áp
dụng một loạt các tuỳ chỉnh để kiểm soát các giá trị thực tế đã sử dụng trong các
lớp Java của bạn và cách làm thế nào để truy cập chúng, cho dù chúng là cần phải
có (required) hay tùy chọn (optional); để kiểm soát các tên và các không gian tên
(namespaces) được sử dụng trong XML và thậm chí để kiểm soát cấu trúc của các
định nghĩa lược đồ đã tạo ra. Đồng thời, bạn sẽ thấy JiBX tăng thêm giá trị cho các
lược đồ bạn đã tạo ra như thế nào khi sử dụng những công sức đầu tư của bạn vào
Javadocs để làm tài liệu về định nghĩa lược đồ một cách tự động. Sau khi đọc
hướng dẫn này và thực hiện các ví dụ được cung cấp, bạn sẽ có khả năng sử dụng
JiBX để tạo ra các định nghĩa lược đồ XML có chất lượng từ các lớp cấu trúc dữ
liệu Java riêng của bạn.
Các điều kiện cần có trước
Để hiểu được hướng dẫn này, bạn ít nhất nên có các kiến thức cơ bản về cả mã
Java và XML. Bạn không cần phải hiểu biết chi tiết về các định nghĩa lược đồ
XML nhưng sự quen thuộc với các lược đồ sẽ giúp bạn hiểu các ví dụ tốt hơn.
Các yêu cầu hệ thống
Để chạy các ví dụ này, bạn cần phải cài đặt:
Cả hai:
o Sun's JDK 1.5.0_09 (hoặc mới hơn).
o Bộ dụng cụ của nhà phát triển của IBM cho công nghệ Java 1.5.0
SR3
Một phiên bản mới đây của công cụ xây dựng Apache Ant.
Các hướng dẫn tải về và cài đặt JiBX có trong hướng dẫn này.
Bắt đầu
Trong phần này, bạn sẽ có được cái nhìn tổng quan về JiBX và bạn sẽ cài đặt JiBX
và mã lệnh mẫu của hướng dẫn này.
Giới thiệu JiBX
JiBX là một trong nhiều công cụ dùng để chuyển đổi giữa các cấu trúc dữ liệu
Java và các tài liệu XML (Tài nguyên). Cái làm nên sự khác biệt của JiBX so với
những công cụ khác là các đặc tính linh hoạt và hiệu năng. Hiệu năng của JiBX
luôn được đánh giá ở vị trí cao nhất trong lĩnh vực này, vượt quá hai lần hoặc hơn
nữa so với hiệu năng của các công cụ phổ biến khác (như JAXB 2.0 chẳng hạn).
JiBX cũng linh hoạt hơn hầu hết tất cả các công cụ Java-XML khác, khi sử dụng
các định nghĩa liên kết để tách các cấu trúc Java khỏi biểu diễn XML sao cho từng
cái có thể được thay đổi độc lập với cái kia.
Với bản phát hành 1.2, JiBX bổ sung thêm các đặc tính hỗ trợ các định nghĩa lược
đồ XML. Bạn có thể sử dụng các công cụ kèm theo trong bản phát hành JiBX để
tạo ra một định nghĩa lược đồ khớp với mã Java của bạn hoặc để tạo mã Java khớp
với định nghĩa lược đồ của bạn. Dù bằng cách nào, bạn cũng nhận được một định
nghĩa liên kết để cho phép bạn sử dụng JiBX để chuyển đổi giữa các mã Java và
các tài liệu XML khớp với định nghĩa lược đồ. Trong hướng dẫn này, bạn sẽ thấy
cách làm thế nào để áp dụng kiểu tạo mã đầu tiên: từ mã Java sinh ra định nghĩa
lược đồ.
Cài đặt JiBX
Bạn cần phải cài đặt JiBX trước khi tiếp tục thực hiện hướng dẫn này. Hãy tải về
bản ZIP phân phối mới nhất 1.2.x và giải nén nó vào một chỗ thuận tiện trên hệ
thống của bạn. Xong việc, bạn sẽ nhận được một thư mục có tên là jibx, trong đó
có chứa tất cả các tệp JiBX JAR, tài liệu hướng dẫn, các ví dụ và thậm chí cả mã
nguồn.
Cài đặt mã nguồn các ví dụ của hướng dẫn này
Bây giờ hãy tải về các mã mẫu, của hướng dẫn này, cũng được cung cấp dưới
dạng một tệp tin ZIP. Cách dễ nhất để cài đặt nó trên hệ thống của bạn là giải nén
tệp tin ZIP vào thư mục gốc của bản phân phối JiBX của bạn (hoặc trên
Windows®, sao chép thư mục dwcode1 từ bên trong tệp tin ZIP này vào thư mục
gốc bản phân phối JiBX của bạn). Điều này sẽ tạo ra một thư mục con dwcode1
trong thư mục jibx, với các tệp tin ví dụ (bao gồm cả các tệp tin build.xml,
custom1.xml và các tệp tin khác) bên trong thư mục con dwcode1 đó.
Mã mẫu bao gồm một tệp tin xây dựng Ant Apache để tự động hoá cho chạy các
công cụ JiBX và xử lý các bước khác có trong các ví dụ. Nếu bạn cài đặt các mã
mẫu trực tiếp vào thư mục cài đặt của JiBX, công cụ xây dựng (build) có thể truy
cập các tệp JiBX JAR mà không cần thêm bất kỳ cấu hình nào. Nếu bạn cài đặt
các mã mẫu ở nơi khác, bạn vẫn có thể sử dụng công cụ xây dựng Ant. Trong
trường hợp này, bạn chỉ cần thiết lập một biến môi trường JIBX_HOME chỉ rõ
đường dẫn đến bản cài đặt JiBX của bạn. Ngoài ra, một cách khác là bạn có thể
chỉnh sửa các tệp tin build.xml-bên trong thư mục mã mẫu và bỏ dấu chú thích ở
đầu các dòng phía trên cùng của tệp tin, nơi trực tiếp thiết lập các thuộc tính jibx-
home.
Tạo ra liên kết mặc định và lược đồ từ mã Java
Cách sử dụng cho trường hợp không phải Java 5
Mã ví dụ của hướng dẫn này sử dụng các đặc tính về bảng kê (enum) và sưu tập có
định kiểu của Java 5, nhưng bản thân JiBX hoàn toàn tương thích với các phiên
bản Java cũ hơn. Môi trường chạy JiBX tiêu chuẩn làm việc được với các JVM
phiên bản 1.3 và mới hơn và cũng có thể được xây dựng để tương thích với J2ME.
Hầu hết các thành phần khác của JiBX bao gồm cả BindGen, có thể chạy được
trên các bản JVM phiên bản 1.4.1 và mới hơn. Tài liệu BindGen trong bản tải về
JiBX có một ví dụ chỉ rõ cách tùy chỉnh như thế nào để có thể cung cấp cho
BindGen các thay thế tương đương của các sưu tập có định kiểu nếu bạn sử dụng
mã Java cũ hơn phiên bản Java 5.
Thật dễ dàng để tạo ra một định nghĩa liên kết JiBX và định nghĩa lược đồ XML
tương ứng từ mã Java. Bạn sẽ tìm hiểu cách làm thế nào trong phần này.
Giới thiệu về mã ví dụ Java
Như một ví dụ, tôi sẽ bắt đầu với mã Java cho một tập các lớp theo phong cách
bean (các trường dữ liệu là riêng-private và các phương thức set và các phương
thức get là chung-public) dùng để mô tả một đơn hàng từ một cửa hàng trực tuyến.
Listing 1 hiển thị một phiên bản mã rút gọn, bỏ qua hầu hết các phương thức
get/set. Toàn bộ mã mẫu hoàn chỉnh nằm trong thư mục src các mã mẫu.
Listing 1. Mã Java cơ sở
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
}
Tạo liên kết và lược đồ mặc định
Để tạo ra một liên kết JiBX và lược đồ XML từ một số lớp Java, đầu tiên bạn cần
phải biên dịch các lớp, sau đó chạy công cụ org.jibx.binding.generator.BindGen có
trong jibx-tools.jar từ bản phân phối JiBX. Bạn có thể chạy trực tiếp công cụ từ
dòng lệnh hoặc gián tiếp thông qua một công cụ xây dựng như Ant.
Trong tệp tải về của hướng dẫn có chứa một kịch bản lệnh Ant build.xml với đích
compile để biên dịch mã ví dụ và đích bindgen để chạy chương trình BindGen trên
mã đã biên dịch.
Để thử làm việc này, mở một cửa sổ lệnh trong thư mục dwcode1 nơi cài đặt ví dụ
đã tải về và gõ ant compile bindgen. Nếu Ant đã được cài đặt trên hệ thống và bạn
đã cài đặt mã đã tải xuống theo đúng các chỉ dẫn, bạn sẽ thấy kết quả tương tự như
được hiển thị trong Hình 1:
Hình 1. Sử dụng công cụ xây dựng Ant
Bạn cũng có thể chạy BindGen trực tiếp từ cửa số lệnh. Để làm được điều này, bạn
cần đưa thêm vào biến môi trường Java classpath của bạn tên tệp tin jibx-tools.jar
cùng với đường dẫn đến các tệp tin lớp đã biên dịch sẽ được sử dụng làm đầu vào
cho BindGen. Nếu bạn muốn tạo bản sao đúp kết quả của đích Ant bindgen, đã
cung cấp, bạn cũng cần phải thêm vào dòng lệnh cả tên thư mục gốc của các tệp
mã nguồn của các lớp đó. Cuối cùng, bạn cần liệt kê (các) lớp gốc mà bạn muốn
sử dụng cho việc sinh mã. Trên các hệ thống UNIX® và Linux®, dòng lệnh Java
(chỉ là một dòng, ngay cả khi hiển thị màn hình có xuống dòng vì quá dài) để sao
đúp đích Ant bindgen từ cửa sổ lệnh trong thư mục dwcode1 (giả thiết bạn đã làm
theo đúng các chỉ dẫn cài đặt được khuyến cáo) là:
java
-cp /lib/jibx-tools.jar:bin org.jibx.binding.generator.BindGen
-s src org.jibx.starter.Order
Trên Windows, dòng lệnh (chỉ là một dòng, bất kể hiển thị ở đây như thế nào) là:
java
-cp \lib\jibx-tools.jar;bin org.jibx.binding.generator.BindGen
-s src org.jibx.starter.Order
Có thể chuyển thêm nhiều tham số tùy chọn khác đến dòng lệnh cho chạy
BindGen. Bạn sẽ xem xét các tùy chọn đó sau trong hướng dẫn này. Bây giờ, hãy
nhìn vào lược đồ đã tạo ra.
Các tạo phẩm được tạo ra
Listing 2 cho thấy lược đồ kết quả đã tạo ra từ BindGen (tên là starter.xsd), được
định dạng lại một chút cho phù hợp với độ rộng trang và bỏ bớt một số chi tiết.
Thẻ bắt đầu của định nghĩa lược đồ khớp với mỗi lớp Java được hiển thị bằng chữ
in đậm để nhấn mạnh cấu trúc.
Listing 2. Lược đồ được tạo ra
<xs:schema xmlns:xs="
xmlns:tns=" elementFormDefault="qualified"
targetNamespace="
<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>
Theo mặc định, BindGen tạo ra một lược đồ với các định nghĩa complexType và
simpleType ghép lồng nhau nếu các kiểu chỉ được sử dụng một lần và tách riêng
các định nghĩa nếu các kiểu được sử dụng nhiều lần. Trong trường hợp này, dùng
định nghĩa kiểu lồng nhau dẫn đến một lược đồ chỉ có ba định nghĩa toàn cục: các
kiểu phức hợp: địa chỉ (address) và đơn hàng và phần tử đơn hàng order. Lớp
Address được sử dụng ở hai chỗ trong lớp Order (cho các địa chỉ thanh toán và
vận chuyển), đó là lý do tại sao mà lớp đó được miêu tả bằng một định nghĩa toàn
cầu riêng biệt trong lược đồ. (Lược đồ cho phép bạn sử dụng lại các định nghĩa chỉ
khi chúng là toàn cầu). Các lớp khác trong cấu trúc dữ liệu Java (Khách hàng
(Customer), Mục hàng (Item) và Vận chuyển (Shipping)) mỗi lớp được tham chiếu
chỉ tại một điểm trong lớp Order, do đó các định nghĩa kiểu tương ứng được
nhúng trực tiếp trong định nghĩa kiểu lược đồ order.
Một trong những đặc tính tốt đẹp hơn của BindGen là nó có thể tạo ra các tài liệu
lược đồ từ Javadocs trong các lớp đầu vào. Bạn có thể xem tài liệu lược đồ trong
Listing 2 cho từng trường với một Javadoc trong Listing 1 và cho mỗi kiểu toàn
cầu tương ứng với một lớp với một Javadoc. Không phải tất cả các định dạng của
các Javadoc đều có thể khớp với các thành phần của lược đồ theo xử lý mặc định
của BindGen — và một số Javadoc, ví dụ như những javadocs về các phương thức
truy cập “get”, có thể trông có vẻ kỳ cục khi được biến đổi thành tài liệu lược đồ
— và một số Javadoc, ví dụ như những javadocs về các phương thức truy cập
“get”, có thể trông có vẻ kỳ cục khi được biến đổi thành tài liệu lược đồ - nhưng
tài liệu lược đồ kết quả có thể vô cùng hữu ích để làm rõ việc sử dụng đúng đắn
các biểu diễn XML. Bạn thậm chí có thể định nghĩa một lớp định dạng (formatter)
của riêng bạn dành cho các Javadoc được sử dụng như là tài liệu lược đồ, nếu bạn
muốn thực hiện một số thay đổi lời văn trong quá trình biến đổi (chẳng hạn như
việc loại bỏ đoạn mào đầu câu "Get " trong Javadocs của phương thức "get").
Đặc tính chuyển đổi Javadoc này chỉ hoạt động được nếu bạn có sẵn mã nguồn
cho các lớp và cung cấp một đối số cho BindGen để báo cho nó biết một đường
dẫn của thư mục gốc (hoặc các đường dẫn). Trong các mẫu dòng lệnh tôi đã cung
cấp trước đó (xem Tạo liên kết và lược đồ mặc định-Generating the default
binding and schema), đường dẫn nguồn được cung cấp là -s src.
Liên kết JiBX được tạo ra
Ngoài các định nghĩa lược đồ, BindGen cũng tạo ra một định nghĩa liên kết JiBX
(là tệp tin binding.xml, trong trường hợp này). Định nghĩa liên kết cho các trình
biên dịch liên kết của JiBX biết cách chuyển đổi giữa các lớp Java và XML như
thế nào. Định nghĩa liên kết đó thực sự là kết quả chính của BindGen, với lược đồ
được tạo ra từ việc liên kết. Các định nghĩa liên kết có đầy đủ các các chi tiết về
các phép chuyển đổi được JiBX thực hiện, vì thế chúng nhất định là phải phức tạp.
May mắn thay, bạn không cần phải hiểu định nghĩa liên kết để làm việc với JiBX
khi sử dụng tạo lược đồ và liên kết của BindGen, vì vậy hướng dẫn này không
trình bày các chi tiết.
Làm việc với các tài liệu XML
Trong phần này, bạn sẽ tìm hiểu về việc chạy trình biên dịch liên kết JiBX và sử
dụng JiBX lúc đang chạy để làm việc với các tài liệu XML.
Chạy trình biên dịch liên kết JiBX
Để sử dụng định nghĩa liên kết được tạo ra trong khi làm việc với các tài liệu
XML, trước hết bạn cần phải chạy công cụ trình biên dịch liên kết JiBX. Trình
biên dịch liên kết thêm mã byte (bytecode) vào các tệp tin lớp đã biên dịch của bạn
để thực sự triển khai thực hiện các phép biến đổi thành XML và từ XML, như định
nghĩa liên kết đã chỉ rõ. Bạn phải chạy trình biên dịch liên kết mỗi khi bạn biên
dịch lại lớp Java của bạn hoặc sửa đổi định nghĩa liên kết, vì vậy tốt nhất là thêm
bước biên dịch liên kết như là một phần của quá trình xây dựng tiêu chuẩn của các
dự án của bạn.
Trình biên dịch liên kết được bao gồm trong bản phân phối JiBX như là một phần
của tệp tin jibx-bind.jar. Tài liệu JiBX cung cấp đầy đủ các chi tiết về các cách
khác nhau để chạy trình biên dịch liên kết, bao gồm cả cách làm thế nào để bạn có
thể chạy nó ở môi trường đang chạy chứ không phải là một phần của quá trình xây
dựng. JiBX cũng cung cấp các trình cắm thêm cho Eclipse và IntelliJ IDEA để tự
động chạy các trình biên dịch liên kết khi bạn đang làm việc trong các IDE này.
Với mục đích của hướng dẫn này, bạn nên làm đơn giản mọi việc và chỉ cần chạy
trình biên dịch liên kết thông qua Ant, sử dụng đích bind (liên kết) trong tệp tin
build.xml. Hình 2 cho thấy kết quả đầu ra mà bạn sẽ thấy khi bạn chạy đích này,
giả định bạn đã chạy các đích compile và bindgen. (Bạn cũng có thể chạy lần lượt
tất cả ba đích này bằng cách liệt kê chúng theo thứ tự trên dòng lệnh: ant compile
bindgen bind.)
Hình 2. Tác vụ bind của công cụ xây dựng Ant
Sử dụng JiBX trong môi trường đang chạy chương trình
Listing 3 cho thấy một tài liệu thử nghiệm đơn giản khớp với lược đồ đã tạo ra, có
trong mã đã tải về của hướng dẫn này, có tên là data.xml:
Listing 3. Tài liệu kiểm tra liên kết mặc định
<order orderNumber="12345678" orderDate="2008-10-18" shipDate="2008-10-
22"
xmlns="
<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>
Gói tải về cũng bao gồm một chương trình kiểm tra đơn giản, được hiển thị ở đây
như Listing 4, để trình bày việc sử dụng JiBX cho cả hai tài liệu không tuần tự hóa
(unmarshalling) và tuần tự hóa (marshalling). (Marshalling là quá trình sinh ra
một biểu diễn XML của một đối tượng trong bộ nhớ, có thể bao gồm cả các đối
tượng được liên kết với đối tượng ban đầu. Unmarshalling là quá trình ngược với
tuần tự hóa, tức là xây dựng một đối tượng (và có thể là một đồ thị của các đối
tượng liên kết với nhau) trong bộ nhớ từ một biểu diễn XML). Đích run của Ant
thi hành chương trình thử nghiệm này bằng cách sử dụng tài liệu trong Listing 3
làm đầu vào và viết ra một bản sao kết quả tuần tự hóa đối tượng thành một tệp tin
có tên là out.xml.
Listing 4. Chương trình thử nghiệm
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);
}
}
}
Hình 3 hiển thị kết quả mà bạn sẽ thấy khi chạy đích run:
Hình 3. Tác vụ run của công cụ xây dựng Ant
Bạn có thể rà soát tệp tin out.xml đã tạo ra để xem nó khớp với các đầu vào gốc
được hiển thị trong Listing 3 như thế nào. Trừ ra khai báo không gian tên, thứ tự
các thuộc tính và thuộc tính tổng giá trị (total) đã được thêm vào kết quả đầu ra
(do chương trình thử nghiệm tính toán và thiết lập), hai tài liệu phải giống hệt
nhau. Không phải lúc nào cũng được như vậy! JiBX, giống như hầu hết các dạng
liên kết dữ liệu, chỉ làm việc với dữ liệu "quan trọng" trong tài liệu, có nghĩa là các
giá trị được ứng dụng của bạn sử dụng. Các phần không quan trọng của tài liệu
(như là khoảng trống bên trong thẻ bắt đầu và thẻ kết thúc, văn bản giữa các phần
tử, và các lời ghi chú) bị mất khi bạn không sắp xếp theo thứ tự (unmarshal) một
tài liệu. Một số lý do là các tài liệu đầu vào và đầu ra trong trường hợp này giống
như mã của Listing 4 thiết lập định dạng đầu ra để sử dụng khoảng lùi đầu dòng là
hai khoảng trống cho mỗi mức lồng nhau của phần tử XML, phù hợp với tài liệu
đầu vào.
Người quan sát tinh mắt sẽ nhận thấy một sự khác biệt giữa đầu vào và đầu ra có
vẻ quan trọng ở phần danh sách các mục hàng trong tài liệu kết quả đầu ra được
hiển thị trong Listing 5:
Listing 5. Danh sách các mục hàng trong tài liệu kết quả
<item quantity="1" price="5.99">
<id>AC4983498512</id>
<description>Left-handed widget</description>