打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
JAXB(Java Architecture for XML Binding)新手學習筆記
各位先進好, 小弟最近剛學 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
<?xml version="1.0" encoding="UTF-8"?><!-- xmlns:xsd="http://www.w3.org/2001/XMLSchema" ::   http://www.w3.org/2001/XMLSchema      可以想成使用到的其它份文件的 namespace     xsd 則是要關聯到該文件中的 type 時用作前綴的短名稱   targetNamespace="http://www.WhiteSugerCompany.com/ws" ::    表示這一份文件的 namespace 為 http://www.WhiteSugerCompany.com/ws    想像有多家製糖公司各自都有一個 suger 的 type,    namespace 可以用來區分它們   --><xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"  xmlns:ws="http://www.WhiteSugerCompany.com/ws"  targetNamespace="http://www.WhiteSugerCompany.com/ws">   <!-- 一個 suger 的 type, 包含了 顏色, 甜度 -->  <xsd:complexType name="suger">    <xsd:sequence>      <xsd:element name="color" type="xsd:string"/>      <xsd:element name="sweetness" type="xsd:byte"/>    </xsd:sequence>  </xsd:complexType>   <!-- 一個 type 為 suger 的 element -->  <xsd:element name="Sugers" type="ws:suger"/></xsd:schema>



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<Suger> 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<Suger> 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<Suger> 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<Suger> 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
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:Sugers xmlns:ns2="http://www.WhiteSugerCompany.com/ws">    <color>Cream color</color>    <sweetness>20</sweetness></ns2:Sugers> 


我們可以發現, [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<Suger> 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
<?xml version="1.0" encoding="BIG5"?> <project name="genXsdClasses" default="genClass" basedir=".">  <!-- 上面一行是 project 的進入點  -->   <!-- Define JAXB home, 請依個人檔案路徑修改 -->  <property name="jaxb.home" value="C:/java/jaxb-ri-20101209" />   <!-- Define class path, 同上 -->  <path id="classpath">    <pathelement path="src" />    <pathelement path="classes" />    <pathelement path="schemas" />    <fileset dir="lib" includes="*.jar" />    <!-- this example only need this one below, above 4 just for example -->    <fileset dir="${jaxb.home}" includes="lib/*.jar" />  </path>   <!-- This maps XJCTask to an Ant task named xjc.    Refer to any of the build.xml under jaxb.home/samples for detail. -->  <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">    <classpath refid="classpath" />  </taskdef>   <!-- Generate .java files by defined task xjc. -->  <target name="genClass">    <xjc destdir="src">      <schema dir="xmlSchema/drink" includes="MixedSugerWater.xsd" />      <binding dir="xmlSchema" includes="customBinding.xml" />    </xjc>   </target> </project>


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

首先是執行前 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
<?xml version="1.0" encoding="BIG5"?> <project name="genXsdClasses" default="genClass" basedir=".">  <!-- 上面一行是 project 的進入點  -->   <!-- Define JAXB home, 請依個人檔案路徑修改 -->  <property name="jaxb.home" value="C:/java/jaxb-ri-20101209" />  <!-- Define source and destnation, 同上 -->   <!-- Define class path -->  <path id="classpath">    <pathelement path="src" />    <pathelement path="classes" />    <pathelement path="schemas" />    <fileset dir="lib" includes="*.jar" />    <!-- this example only need this one below, above 4 just for example -->    <fileset dir="${jaxb.home}" includes="lib/*.jar" />  </path>   <!-- This maps XJCTask to an Ant task named xjc.    Refer to any of the build.xml under jaxb.home/samples for detail. -->  <taskdef name="xjc" classname="com.sun.tools.xjc.XJCTask">    <classpath refid="classpath" />  </taskdef>   <!-- clear old files -->  <target name="clean">    <delete dir="src/org/iii/test/jaxb/drink" />    <delete dir="src/org/iii/test/jaxb/suger" />  </target>   <!-- Generate .java files by defined task xjc. -->  <target name="genClass" depends="clean">    <xjc destdir="src">      <schema dir="xmlSchema/drink" includes="MixedSugerWater.xsd" />      <binding dir="xmlSchema" includes="customBinding.xml" />    </xjc>   </target> </project>


執行結果如下





2. References



官網

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

注意, Parameter Attributes 表格中的 target 應改為 destdir 才能動
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
JAXB2.0 使用文档
Spring-ws示例WebService开发
用户化JAXB绑定生成Java源代码的简单尝试
使用 JAXB 工具根据 Java 类生成 XML 模式
WebService CXF学习(进阶篇4):JAXB剖析
JSR224-JAX-WS2.0
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服