各位先進好, 小弟最近剛學 JAXB, 整理了一些內(nèi)容, 希望能藉此減低往後入門者的痛感, 新手拙文, 請多指教,
總共會有八篇
初探 JAXB -- 生成物件及將物件轉(zhuǎn) xml 由 XML 字串生成物件 -- 如字面所述 用 NamespacePrefixMapper 修正 prefix -- 增加生出來的 xml 的可讀性 JAXB xsd 中使用其它文件的內(nèi)容 -- import / include / namespace 使用 Name space 解決名稱衝突 -- 撞名問題 為同名型態(tài)生成不同 class - Customizing JAXB Bindings -- 處理完撞名繼續(xù)看它 分門別類 - customize package bindings -- 管理 package 以 Ant 使用 JAXB xjc -- 用 Ant 做 xjc 動作
會陸續(xù)整理上來
第一篇 -- 初探 JAXB
1. 撰寫 XML Schema 的 xsd 檔
首先要準備一份 xsd 檔, 以便利用它來生成物件,
並使用 JAXB 的 API 進行物件與 xml 之間的轉(zhuǎn)換,
例如以下的 schema 代表一家製糖公司生產(chǎn)的 白糖
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./2001/XMLSchema" ::
http:
可以想成使用到的其它份文件的 namespace
xsd 則是要關聯(lián)到該文件中的 type 時用作前綴的短名稱
targetNamespace="http://www.WhiteSugerCompany.com/ws" ::
表示這一份文件的 namespace 為 http:
想像有多家製糖公司各自都有一個 suger 的 type,
namespace 可以用來區(qū)分它們
-->
<xsd:schema xmlns:xsd="http://www./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 資料夾中 執(zhí)行以下命令
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
現(xiàn)在有了 xsd 檔及生出的物件, 接下來便可以使用 JAXB 提供的 API,
由物件直接生成 xml
首先將剛生成的 package 放到 src 中如下 (請先忽略紅框之外的部份)
然後要下載 JAXB RI 及將 lib 加入專案, 如下
下載 JAXB RI
下載頁
http://jaxb./2.2.3/
點 Download the binary, 副檔名要改 .jar
安裝
在下載後的 jar 檔點兩下, 第一頁版權宣告頁拉到最下方,
點 Accept, 會生出一個資料夾, 將它搬到適當?shù)胤郊纯?
然後將該資料夾下 lib 內(nèi)的 jar 檔加入專案內(nèi)
下載並加入 jar 後
接下來撰寫如下程式, 生成物件, 設置適當?shù)闹祦K生成 xml
這裡要注意的是, StringWriter 會以附加的方式持續(xù)加入內(nèi)容,
因此在加入新內(nèi)容前要清空它的 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{
JAXBContext ctx = JAXBContext.newInstance("org.iii.test.jaxb.whitesuger");
ObjectFactory of = new ObjectFactory();
Suger ws = of.createSuger();
ws.setColor("Cream color");
ws.setSweetness((byte)20);
JAXBElement<Suger> je = of.createSugers(ws);
Marshaller m = ctx.createMarshaller();
StringWriter xml = new StringWriter();
m.marshal(je, xml);
System.err.println(xml.toString());
System.err.println("\n********\n********\n");
StringBuffer sb = xml.getBuffer();
sb.setLength(0);
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(je, xml);
System.err.println(xml.toString());
}
catch (Exception e){
e.printStackTrace();
}
}
}
|
輸出結果如下圖
其中兩行星號上方的是 未格式化 的輸出結果,
下方的則是經(jīng)過格式化的輸出結果
4. References
W3C 文件
http://www./TR/xmlschema-0/#DefnDeclars
史蒂芬 很詳盡的教學
http://home./idealist/WebService/
|
第二篇 -- 由 XML 字串生成物件
1. 使用 Unmarshaller
在 第一篇 之中, 我們將物件利用 JAXB 的 API 轉(zhuǎn)成 XML 字串,
通常之後我們會將轉(zhuǎn)出的字串傳到其它地方, 而其它地方收到後,
便要由 XML 字串 轉(zhuǎn)回相對應的物件,
假設已經(jīng)知道所要轉(zhuǎn)成的物件類型, 則轉(zhuǎn)換的程式如下
1 2 3 4 5 6 7 8 9 10
|
JAXBContext context = JAXBContext.newInstance(Suger.class);
Unmarshaller um = context.createUnmarshaller();
JAXBElement<Suger> root = um.unmarshal(new StreamSource(new StringReader(
xmlString)), Suger.class);
Suger ws2 = root.getValue();
|
這裡要注意的是, xmlString 要是未經(jīng) format 過的,
2. 完整程式及執(zhí)行結果
以下為完整的程式及執(zhí)行結果截圖, 其中包含 第一篇 的部份
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{
JAXBContext ctx = JAXBContext.newInstance("org.iii.test.jaxb.whitesuger");
ObjectFactory of = new ObjectFactory();
Suger ws = of.createSuger();
ws.setColor("Cream color");
ws.setSweetness((byte)20);
JAXBElement<Suger> je = of.createSugers(ws);
Marshaller m = ctx.createMarshaller();
StringWriter xml = new StringWriter();
m.marshal(je, xml);
String xmlString = xml.toString();
System.err.println(xmlString);
System.err.println("\n********\n********\n");
StringBuffer sb = xml.getBuffer();
sb.setLength(0);
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
m.marshal(je, xml);
System.err.println(xml.toString());
JAXBContext context = JAXBContext.newInstance(Suger.class);
Unmarshaller um = context.createUnmarshaller();
JAXBElement<Suger> root = um.unmarshal(new StreamSource(new StringReader(
xmlString)), Suger.class);
Suger ws2 = root.getValue();
System.err.println("\n********\n********\n");
System.err.println(" ws2 color = " + ws2.getColor());
System.err.println(" ws2 sweetness = " + ws2.getSweetness());
}
catch (Exception e){
e.printStackTrace();
}
}
}
|
3. References
實用教學
http://jaxb./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>
|
我們可以發(fā)現(xiàn), [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( "http://www.WhiteSugerCompany.com/ws".equals(namespaceUri) )
return "ws";
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{
JAXBContext ctx = JAXBContext.newInstance("org.iii.test.jaxb.whitesuger");
ObjectFactory of = new ObjectFactory();
Suger ws = of.createSuger();
ws.setColor("Cream color");
ws.setSweetness((byte)20);
JAXBElement<Suger> je = of.createSugers(ws);
Marshaller m = ctx.createMarshaller();
StringWriter xml = new StringWriter();
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 轉(zhuǎn)換 schema 為 java 檔
Ant 也可以用來將 xjc 的功能自動化,
讓我們不必再重覆 搬移 schema 檔案 下指令 搬回物件檔案 這些動作,
環(huán)境說明
這裡以 第七篇 -- 分門別類 - customize package bindings 的情況為例,
我們要撰寫一個 build.xml, 準備好 xsd 檔及 binding file,
執(zhí)行它後就會把 java 檔 產(chǎn)生出來放到正確的位置
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>
|
以下為執(zhí)行前及執(zhí)行後的截圖
首先是執(zhí)行前 src 下的情形
執(zhí)行後將 src 重新整理後的情形 以及執(zhí)行的訊息
寫得更完整, 加入清除舊檔的部份
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>
|
執(zhí)行結果如下
2. References
官網(wǎng)
http://jaxb./jaxb20-ea/docs/xjcTask.html
注意, Parameter Attributes 表格中的 target 應改為 destdir 才能動
|
|