JAXB

(史帝芬, idealist@gcn.net.tw, J2SDK 1.4.2, JWSDP 1.4, 2004/10/05)

早期Java要讀寫XML都是透過DOM或SAX,即使後來有JDOM的出現,但是讀寫XML對許多技術人員來說, 仍是一件痛苦的事,現在又有一組更簡單的API出現了,這就是本篇要介紹的主題 --- JAXB。這裡使用JWSDP、 WSAD (Websphere Studio Application Developer)來展示JAXB的用法。

下載並安裝J2SDK

以瀏覽器連線至http://java.sun.com/j2se/1.4.2/download.html下載J2SDK, 並安裝至C:\J2SDK,然後設定環境變數JAVA_HOME=C:\J2SDK。

下載並安裝JWSDP

以瀏覽器連線至http://java.sun.com/webservices/downloads/webservicespack.html 下載JWSDP,並安裝至c:\jwsdp-1.4。

建立Java專案

開啟WSAD,建立一個Java專案,命名為testJAXB (圖1)。

(圖1)

加入類別路徑

在喜好設定中,選擇"類別路徑變數",加入C:\jwsdp-1.4\jaxb\lib、C:\jwsdp-1.4\jaxp\lib、C:\jwsdp-1.4\jaxp\lib\endorsed底下的所有檔案,及 C:\jwsdp-1.4\jwsdp-shared\lib底下的jax-qname.jar、namespace.jar、relaxngDatatype.jar (圖2)

(圖2)

然後在專案名稱上按滑鼠右鍵後選內容,找到"Java建置路徑"後按"新增變數",將上述的類別檔加入。

(圖3)

新增XML檔

在專案中新增一個data.xml,內容如下…
<?xml version="1.0" encoding="UTF-8"?>
<book>
<title>象棋開局精華</title>
<author>史帝芬</author>
<content>
<chapter>
<topic>當頭炮過河車攻屏風馬左馬盤河</topic>
<page>33</page>
</chapter>
<chapter>
<topic>當頭炮過河車攻屏風馬平包兌車</topic>
<page>35</page>
</chapter>
<chapter>
<topic>當頭炮進三兵攻屏風馬</topic>
<page>19</page>
</chapter>
</content>
</book>

產生XML Schema

正常情況下應該先有XML Schema再產生XML,這裡先產生XML,再利用工具產生XML Schema也是行的通, 不過,這樣子必須用來產生XML Schema的XML很完整才行,這裡只是一個示範。在data.xml上按滑鼠右鍵, 選擇"產生"後再選擇產生"XML綱目" (圖4),就可產生XML Schema,在圖5位置輸入檔名data.xsd。

(圖4)

(圖5)

在data.xsd中找到如圖6的字串,原本WSAD幫我們產生的型別是string,將它改成integer,因為page頁數是數字。

(圖6)

產生XML Schema

打開命令視窗,將data.xsd烤具到一個暫時目錄,執行xjc (圖7),如此,xjc將依XML Schema產生所有相關程式碼。

(圖7)

將所有xjc產生的檔案匯入WSAD (圖8)。

(圖8)

接下來我們就可以利用xjc產生的程式來讀寫XML

範例程式

在testJAXB專案底下,新增一個Sample1.java類別檔,並且寫如下的程式碼…
import java.io.*;
import java.math.BigInteger;
import java.util.*;
import javax.xml.bind.*;
import generated.*;

public class Sample1 {
public Sample1() {
try {
//取得JAXBContext物件,並設定Java套件名稱
JAXBContext jc = JAXBContext.newInstance("generated");

//unmarshall
Unmarshaller um = jc.createUnmarshaller(); //取得提供Unmarshal功能的物件
BookType bt = (BookType) um.unmarshal(new FileInputStream("data.xml"));
System.out.println("Title => " + bt.getTitle());
System.out.println("Author => " + bt.getAuthor());
ContentType ct = bt.getContent();
List list = ct.getChapter();
for(Iterator iter = list.iterator(); iter.hasNext(); ) {
Chapter ch = (Chapter) iter.next();
System.out.println(" -- [Topic, Page] => [" + ch.getTopic() + ", " + ch.getPage().intValue() + "]");
}

//新增一個章節
ObjectFactory of = new ObjectFactory();
Chapter ch = of.createChapter();
ch.setTopic("當頭炮橫車攻順手包直車");
ch.setPage(new BigInteger("17"));
ct.getChapter().add(3, ch);

//marshall
Marshaller m = jc.createMarshaller(); //取得提供Marshal功能的物件
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(bt, new FileWriter("newData.xml"));
} catch (JAXBException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

public static void main(String[] args) {
new Sample1();
}
}

執行後"主控台"將會出現如下輸出,顯示程式已正確讀入data.xml。
Title => 象棋開局精華
Author => 史帝芬
-- [Topic, Page] => [當頭炮過河車攻屏風馬左馬盤河, 33]
-- [Topic, Page] => [當頭炮過河車攻屏風馬平包兌車, 35]
-- [Topic, Page] => [當頭炮進三兵攻屏風馬, 19]


然後在專案目錄下找到newData.xml,檢視其內容,如下,可以發現新增了一個章節。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<book>
<title>象棋開局精華</title>
<author>史帝芬</author>
<content>
<chapter>
<topic>當頭炮過河車攻屏風馬左馬盤河</topic>
<page>33</page>
</chapter>
<chapter>
<topic>當頭炮過河車攻屏風馬平包兌車</topic>
<page>35</page>
</chapter>
<chapter>
<topic>當頭炮進三兵攻屏風馬</topic>
<page>19</page>
</chapter>
<chapter>
<topic>當頭炮橫車攻順手包直車</topic>
<page>17</page>
</chapter>
</content>
</book>