摘要:將XML文檔與JAVA對象互轉是很常見的需求,如果XML定義很規整這很好實現。然而在現實中“不規矩”的XML可能更常見,
Marshaller
便無能為力了嗎?
下面是一個小技巧,
調整一下思維便能重用
Marshaller
了,征服它們使工作更簡單
。
關鍵詞:
Marshaller, JAVA, XML
將一個類生成一個Json字符串、將一個Json字符串翻譯成一個類(JAVA、C#代碼),這一過程已經在“”博客中描述了;在實際項目應用中,如何將一個類生成一個XML文檔或XML字符串,如何將一個XML文檔翻譯成一個類,這又是經常遇到的問題。比如,跟其它系統的交互中,其它系統定義的接口參數以XML格式定義,那么你寫的系統就要解析並理解它傳入的數據,或者把自己內部的數據轉成按它規定的XML格式文檔傳出。在JAVA里,這一過程還蠻簡單,使用
Marshaller
便可以很輕松的解決。
然而,有一些“不守規矩”的XML格式可能被其它系統定義了,它們定義的XML格式恰恰不是
Marshaller天生
有能力生成與解析的,我們對這種“不規矩"的XML就無計可施了嗎?其實
Marshaller
還是很好用的,后來你
會發現
Marshaller
的極限便不復存在。下面,我以一個簡單的例子來證明我的這一觀點,對於“不規矩”的XML我也是有辦法將其制服的。
一、XML幫助類
首先,你得有一個XML幫助類,它提供的是最基礎的,使用
Marshaller
使XML和JAVA對象互轉,這對於規矩的XML文檔們,便能以一擋百了。
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
/**
* XML的幫助類
*
* @author wanganqi
* @version v1.0
* @since 2014年8月13日下午2:38:52
*/
public class XmlHelper
{
/**
* 將自定義數據對象轉化為XML字符串
*
* @param clazz 自定義數據類型
* @param object 自定義數據對象
* @return XML字符串
* @throws JAXBException 異常
*/
public static String objectToXML(Class clazz, Object object)
throws JAXBException
{
String xml = null;
JAXBContext context = JAXBContext.newInstance(clazz);
Marshaller m = context.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
Writer w = new StringWriter();
m.marshal(object, w);
xml = w.toString();
return xml;
}
/**
* 將XML字符串轉化為自定義數據對象
*
* @param clazz 自定義數據類型
* @param xml XML字符串
* @return 自定義數據對象
* @throws JAXBException 異常
*/
public static Object xmlToObject(Class clazz, String xml)
throws JAXBException
{
JAXBContext context = JAXBContext.newInstance(clazz);
Unmarshaller um = context.createUnmarshaller();
return um.unmarshal(new StringReader(xml));
}
} |
這對於這樣規矩的:XML,就要定義這樣的:JAVA類,一一對應,什么事情都能解決。
XML(規矩的)文件格式樣例 | JAVA生成方法 |
<?xml version="1.0" encoding="UTF-8"?>
<ANQIFILE>
<HEAD>
<
ANQI
NUM>2</
ANQI
NUM>
<DATETIME>YYYY-MM-DD HH:MM:SS</DATETIME>
<APPROVALNUM>王安琪No1</APPROVALNUM>
</HEAD>
<BODY>
<ANQI>00001</
ANQI
>
<
ANQI
>00002</
ANQI
>
<
ANQI
>00003</
ANQI
>
</BODY>
</ANQIFILE>
|
ANQIHead head = new ANQIHead(1, "YYYY-MM-DD HH:MM:SS",
"
王安琪
No1"
);
ANQIBody body = new ANQIBody("00001", "00002", "00003");
ANQIFile anqiFile = new ANQIFile(head, body);
String xml = XmlHelper.objectToXML(ANQIFile.class, anqiFile);補充說明: 下面的構造函數都隱去了,使用 String... anqis類似的參數,使用時請不要疑惑。 |
@XmlRootElement(name = "ANQIFILE")
@XmlType(propOrder =
{
"head"
,
"body"
})
public class ANQIFile
{
private ANQIHead head;
private ANQIBody body;
@XmlElement(name = "HEAD")
public ANQIHead getHead()
{
return head;
}
public void setHead(
ANQIHead
head)
{
this.head = head;
}
@XmlElement(name = "BODY")
public
ANQIBody
getBody()
{
return body;
}
public void setBody(
ANQIBody
body)
{
this.body = body;
}
}
-------------------------------------------------------------------------------------
public class ANQIBody
{
private List<String> anqi;
@XmlElement(name = "ANQI")
public List<String> getAnqi()
{
return anqi;
}
public void setAnqi(List<String> anqi)
{
this.
anqi
= anqi
;
}
} |
@XmlType(propOrder =
{
"anqiNum"
,
"dateTime"
,
"appovalNum"
})
public class ANQIHead
{
private int anqiNum;
private String dateTime;
private String appovalNum;
@XmlElement(name = "ANQINUM")
public int getAnqiNum()
{
return clueNum;
}
public void setAnqiNum(int clueNum)
{
this.clueNum = clueNum;
}
@XmlElement(name = "DATETIME")
public String getDateTime()
{
return dateTime;
}
public void setDateTime(String dateTime)
{
this.dateTime = dateTime;
}
@XmlElement(name = "APPROVALNUM")
public String getAppovalNum()
{
return appovalNum;
}
public void setAppovalNum(String appovalNum)
{
this.appovalNum = appovalNum;
}
}補充說明: 這里的構造函數都隱去了,使用 String... anqis類似的參數,使用時請不要疑惑。 |
二、將 自定義數據對象 與 XML(不規矩的)字符串 互轉
現在我們有一個需求,
把我們系統的JAVA對象轉成按其它系統規定的XML格式文檔傳出
,其它系統給了我們一份XML格式文檔,希望我們能正確構造它;
我寫的系統要解析並理解其它系統傳入的XML數據,同樣的其它系統給了我們一份XML格式文檔,希望我們能順利解釋它。
看看我們是怎么做的吧。
XML格式:
XML(不規矩的)文件格式樣例 | JAVA使用方法 及 JAVA類 |
<?xml version="1.0" encoding="UTF-8"?>
<ANGELFILE>
<ANGEL>
<WANG ID="00001" COUNT="2">
<ANQI>
<ITEM1>VALUE</ITEM1>
<ITEM2>VALUE</ITEM2>
<ITEMN>VALUE</ITEMN>
</ANQI>
<ANQI>
<ITEM1>VALUE</ITEM1>
<ITEM2>VALUE</ITEM2>
<ITEMN>VALUE</ITEMN>
</ANQI>
</WANG>
</ANGEL>
</ANGELFILE> |
可以使用與上面規矩的XML類似的JAVA定義、使用方法。
現在看看它有多不規矩(其實也不是很不規矩啦,只是在ANQI這個節點下面的子節點名字每個都不一樣,但都是以ITEM開頭的)。
要生成這樣的XML,可以先用ObjectToXML()生成都是以 ITEM 命名的節點,再通過DOM讀取並更新ITEM名稱,后面加上1、2...
要解析這樣的XML,可以先把此XML過濾一遍,把ITEM*樣的節點名稱更新為 ITEM,再用XMLToObject()生成對象。
|
三、遇到的問題及改進方法
1、在使用
Marshaller
的
過程中,出現了一點問題:生成XML時,並不按照配置的
@XmlType(propOrder =
{
"1"
,
"2"
})
的順序,而是恰好相反的,這個問題目前還沒有解決,唯一在網上查到的相關信息是說JAVA版本為6以下的會有這個BUG,但是我的JAVA版本為1.7,也出現了這個問題,望有知道解決方法的同學告知一下,
請不吝賜教
。

2、對於不規矩的XML格式,更好的辦法是使用Marshaller所支持的自定義解析器,上面的不規矩XML完全可以映射到Map對象上面去。這種方法更能支持更不規則的XML定義。網上不知有無已經實現的代碼,知道的同學,請不吝賜教。
最近項目工作量很大,每天都能學習到很多東西,項目管理的、JAVA使用的、界面規范的......不勝枚舉,畢竟是第一次自己負責的項目,經驗和教訓肯定的巨大的。
作為一個項目經理,對作品、對自己的團隊都覺得立馬有了深深的責任感,也有了很大的壓力,感謝組織的信任與支持,感謝團隊的鼎力協作,感謝相關部門的大力配合,感謝姚老師的無私幫助,也感謝老婆默默的支持。
ありがとうございます
如何集中資源做成一個優秀的項目,如何擔當得起自己的責任,如何與各類角色溝通,真是任重而道遠。