作者的ky什么意思:JAXB(Java Architecture for XML Binding)新手學習筆記

来源:百度文库 编辑:偶看新闻 时间:2024/05/03 05:01:48
各位先進好, 小弟最近剛學 JAXB, 整理了一些內容,
希望能藉此減低往後入門者的痛感,
新手拙文, 請多指教,

總共會有八篇

初探 JAXB -- 生成物件及將物件轉 xml
由 XML 字串生成物件 -- 如字面所述
用 NamespacePrefixMapper 修正 prefix -- 增加生出來的 xml 的可讀性
JAXB xsd 中使用其它文件的內容 -- import / include / namespace
使用 Name space 解決名稱衝突 -- 撞名問題
為同名型態生成不同 class - Customizing JAXB Bindings -- 處理完撞名繼續看它
分門別類 - customize package bindings -- 管理 package
以 Ant 使用 JAXB xjc -- 用 Ant 做 xjc 動作

會陸續整理上來

第一篇 -- 初探 JAXB

1. 撰寫 XML Schema 的 xsd 檔


首先要準備一份 xsd 檔, 以便利用它來生成物件,

並使用 JAXB 的 API 進行物件與 xml 之間的轉換,

例如以下的 schema 代表一家製糖公司生產的 白糖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
"1.0" encoding="UTF-8"?>"http://www.w3.org/2001/XMLSchema"  xmlns:ws="http://www.WhiteSugerCompany.com/ws"  targetNamespace="http://www.WhiteSugerCompany.com/ws">     "suger">          "color" type="xsd:string"/>      "sweetness" type="xsd:byte"/>           "Sugers" type="ws:suger"/>



2. 使用 xjc 由 xsd 檔生成物件


接下來將 xsd 檔複製到 jdk\bin 資料夾中 執行以下命令

1
C:\Program Files\Java\jdk1.6.0_21\bin>xjc -p org.iii.test.jaxb.whitesuger xmlSchema\WhiteSuger\WhiteSuger.xsd


就可以利用 jdk 所附的 xjc 程式, 由我們寫的 xsd 檔生成對應物件,

其中 \-p 是用來指定物件的 package,

xmlSchema\WhiteSuger\WhiteSuger.xsd 則是我們 xsd 檔的相對路徑,

這時可看到像以下的畫面及檔案






3. 利用 JAXB 由物件生成 XML


現在有了 xsd 檔及生出的物件, 接下來便可以使用 JAXB 提供的 API,

由物件直接生成 xml

首先將剛生成的 package 放到 src 中如下 (請先忽略紅框之外的部份)



然後要下載 JAXB RI 及將 lib 加入專案, 如下

下載 JAXB RI

下載頁

http://jaxb.java.net/2.2.3/

點 Download the binary, 副檔名要改 .jar

安裝

在下載後的 jar 檔點兩下, 第一頁版權宣告頁拉到最下方,

點 Accept, 會生出一個資料夾, 將它搬到適當地方即可,

然後將該資料夾下 lib 內的 jar 檔加入專案內

下載並加入 jar 後

接下來撰寫如下程式, 生成物件, 設置適當的值並生成 xml

這裡要注意的是, StringWriter 會以附加的方式持續加入內容,

因此在加入新內容前要清空它的 buffer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package org.iii.test.jaxb; import java.io.StringWriter;import javax.xml.bind.JAXBContext;import javax.xml.bind.JAXBElement;import javax.xml.bind.Marshaller;import org.iii.test.jaxb.whitesuger.Suger;import org.iii.test.jaxb.whitesuger.ObjectFactory; public class Test {   public static void main(String args[]){     try{      //-- get context instance      JAXBContext ctx = JAXBContext.newInstance("org.iii.test.jaxb.whitesuger");      ObjectFactory of = new ObjectFactory();       //-- create Suger object      Suger ws = of.createSuger();       //-- set values      ws.setColor("Cream color");      ws.setSweetness((byte)20);       //-- convert ws to JAXBElement      JAXBElement je = of.createSugers(ws);      //-- get Marshaller      Marshaller m = ctx.createMarshaller();       //-- marshal JAXBElement into StringWriter      StringWriter xml = new StringWriter();      m.marshal(je, xml);      System.err.println(xml.toString());       //-- separator      System.err.println("\n********\n********\n");       //-- clear old content in StringWriter      StringBuffer sb = xml.getBuffer();      sb.setLength(0);       //-- marshal JAXBElement into StringWriter with format      m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);      m.marshal(je, xml);      System.err.println(xml.toString());    }    catch (Exception e){      e.printStackTrace();    }  }} 


輸出結果如下圖



其中兩行星號上方的是 未格式化 的輸出結果,

下方的則是經過格式化的輸出結果


4. References


W3C 文件

http://www.w3.org/TR/xmlschema-0/#DefnDeclars

史蒂芬 很詳盡的教學

http://home.so-net.net.tw/idealist/WebService/
第二篇 -- 由 XML 字串生成物件


1. 使用 Unmarshaller


在 第一篇 之中, 我們將物件利用 JAXB 的 API 轉成 XML 字串,

通常之後我們會將轉出的字串傳到其它地方, 而其它地方收到後,

便要由 XML 字串 轉回相對應的物件,

假設已經知道所要轉成的物件類型, 則轉換的程式如下

1
2
3
4
5
6
7
8
9
10
//-- get context instanceJAXBContext context = JAXBContext.newInstance(Suger.class);//-- get unmarshallerUnmarshaller um = context.createUnmarshaller();//-- unmarshal xml string to JAXB elementJAXBElement root = um.unmarshal(new StreamSource(new StringReader(  xmlString)), Suger.class); //-- get object from JAXB elementSuger ws2 = root.getValue();


這裡要注意的是, xmlString 要是未經 format 過的,


2. 完整程式及執行結果


以下為完整的程式及執行結果截圖, 其中包含 第一篇 的部份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package org.iii.test.jaxb.test; import java.io.StringReader;import java.io.StringWriter;import javax.xml.bind.JAXBContext;import javax.xml.bind.JAXBElement;import javax.xml.bind.Marshaller;import javax.xml.bind.Unmarshaller;import javax.xml.transform.stream.StreamSource; import org.iii.test.jaxb.whitesuger.Suger;import org.iii.test.jaxb.whitesuger.ObjectFactory; public class Test {   public static void main(String args[]){     try{      //-- get context instance      JAXBContext ctx = JAXBContext.newInstance("org.iii.test.jaxb.whitesuger");      ObjectFactory of = new ObjectFactory();       //-- create Suger object      Suger ws = of.createSuger();       //-- set values      ws.setColor("Cream color");      ws.setSweetness((byte)20);       //-- convert ws to JAXBElement      JAXBElement je = of.createSugers(ws);      //-- get Marshaller      Marshaller m = ctx.createMarshaller();       //-- marshal JAXBElement into StringWriter      StringWriter xml = new StringWriter();      m.marshal(je, xml);       //-- get xml string      String xmlString = xml.toString();      System.err.println(xmlString);       //-- separator      System.err.println("\n********\n********\n");       //-- clear old content in StringWriter      StringBuffer sb = xml.getBuffer();      sb.setLength(0);       //-- marshal JAXBElement into StringWriter with format      m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);      m.marshal(je, xml);      System.err.println(xml.toString());       //-- get context instance      JAXBContext context = JAXBContext.newInstance(Suger.class);      //-- get unmarshaller      Unmarshaller um = context.createUnmarshaller();      //-- unmarshal xml string to JAXB element      JAXBElement root = um.unmarshal(new StreamSource(new StringReader(          xmlString)), Suger.class);       //-- get object from JAXB element      Suger ws2 = root.getValue();       //-- separator      System.err.println("\n********\n********\n");       //-- output object value      System.err.println(" ws2 color = " + ws2.getColor());      System.err.println(" ws2 sweetness = " + ws2.getSweetness());    }    catch (Exception e){      e.printStackTrace();    }  }}





3. References


實用教學

http://jaxb.java.net/guide/_XmlRootElement_and_unmarshalling.html

第三篇 -- 用 NamespacePrefixMapper 修正 prefix



1. 前言



在 第一篇 之中, 格式化的輸出如下

1
2
3
4
5
6
"1.0" encoding="UTF-8" standalone="yes"?>"http://www.WhiteSugerCompany.com/ws">    Cream color    20 


我們可以發現, [http://www.WhiteSugerCompany.com/ws] 在這裡的 prefix,

變成了 ns2, 而不是 xsd 中的 ws,

我們可以實作 com.sun.xml.bind.marshaller.NamespacePrefixMapper,

來進行 Namespace 與 Prefix 之間對應的處理,



2. 實作並使用 NamespacePrefixMapper



實作 NamespacePrefixMapper

首先我們要實作 NamespacePrefixMapper, 實作程式如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package org.iii.test.jaxb.test; import com.sun.xml.bind.marshaller.NamespacePrefixMapper; public class NamespacePrefixMapperImpl extends NamespacePrefixMapper {   public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {    //-- if namespace is "http://www.WhiteSugerCompany.com/ws"    //-- map it to "ws"    if( "http://www.WhiteSugerCompany.com/ws".equals(namespaceUri) )      return "ws";     // otherwise just use the default suggestion.    return suggestion;  }} 


使用 NamespacePrefixMapper

接下來是在 Marshaller 中 設定要使用的 NamespacePrefixMapperImpl 如下

1
m.setProperty("com.sun.xml.bind.namespacePrefixMapper",new NamespacePrefixMapperImpl());


只要加了這一行, 並且有實作 NamespacePrefixMapper,

便可得到如下圖的輸出, 可以看到原本的 ns2 都變成 ws 了,



完整程式如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package org.iii.test.jaxb.test; import java.io.StringWriter;import javax.xml.bind.JAXBContext;import javax.xml.bind.JAXBElement;import javax.xml.bind.Marshaller; import org.iii.test.jaxb.whitesuger.Suger;import org.iii.test.jaxb.whitesuger.ObjectFactory; public class Test {   public static void main(String args[]){     try{      //-- get context instance      JAXBContext ctx = JAXBContext.newInstance("org.iii.test.jaxb.whitesuger");      ObjectFactory of = new ObjectFactory();       //-- create Suger object      Suger ws = of.createSuger();       //-- set values      ws.setColor("Cream color");      ws.setSweetness((byte)20);       //-- convert ws to JAXBElement      JAXBElement je = of.createSugers(ws);      //-- get Marshaller      Marshaller m = ctx.createMarshaller();       StringWriter xml = new StringWriter();      //-- marshal JAXBElement into StringWriter with format and mapped prefix      m.setProperty("com.sun.xml.bind.namespacePrefixMapper",new NamespacePrefixMapperImpl());      m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);      m.marshal(je, xml);      System.err.println(xml.toString());     }    catch (Exception e){      e.printStackTrace();    }  }}




3. References



官方文件

http://download.oracle.com/docs/cd/E17802_01/webservices/webservices/docs/2.0/jaxb/vendorProperties.html



第八篇 -- 以 Ant 使用 JAXB xjc



1. 以 Ant 轉換 schema 為 java 檔



Ant 也可以用來將 xjc 的功能自動化,

讓我們不必再重覆 搬移 schema 檔案 下指令 搬回物件檔案 這些動作,

環境說明

這裡以 第七篇 -- 分門別類 - customize package bindings 的情況為例,

我們要撰寫一個 build.xml, 準備好 xsd 檔及 binding file,

執行它後就會把 java 檔 產生出來放到正確的位置

build.xml 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
"1.0" encoding="BIG5"?> "genXsdClasses" default="genClass" basedir=".">       "jaxb.home" value="C:/java/jaxb-ri-20101209" />     "classpath">    "src" />    "classes" />    "schemas" />    "lib" includes="*.jar" />        "${jaxb.home}" includes="lib/*.jar" />       "xjc" classname="com.sun.tools.xjc.XJCTask">    "classpath" />       "genClass">    "src">      "xmlSchema/drink" includes="MixedSugerWater.xsd" />      "xmlSchema" includes="customBinding.xml" />        


以下為執行前及執行後的截圖

首先是執行前 src 下的情形



執行後將 src 重新整理後的情形 以及執行的訊息



寫得更完整, 加入清除舊檔的部份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
"1.0" encoding="BIG5"?> "genXsdClasses" default="genClass" basedir=".">       "jaxb.home" value="C:/java/jaxb-ri-20101209" />       "classpath">    "src" />    "classes" />    "schemas" />    "lib" includes="*.jar" />        "${jaxb.home}" includes="lib/*.jar" />       "xjc" classname="com.sun.tools.xjc.XJCTask">    "classpath" />       "clean">    "src/org/iii/test/jaxb/drink" />    "src/org/iii/test/jaxb/suger" />       "genClass" depends="clean">    "src">      "xmlSchema/drink" includes="MixedSugerWater.xsd" />      "xmlSchema" includes="customBinding.xml" />        


執行結果如下





2. References



官網

http://jaxb.java.net/jaxb20-ea/docs/xjcTask.html

注意, Parameter Attributes 表格中的 target 應改為 destdir 才能動