不規矩的xml與JAVA對象互相轉換的小技巧-使用Marshaller


摘要:將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使用的、界面規范的......不勝枚舉,畢竟是第一次自己負責的項目,經驗和教訓肯定的巨大的。

作為一個項目經理,對作品、對自己的團隊都覺得立馬有了深深的責任感,也有了很大的壓力,感謝組織的信任與支持,感謝團隊的鼎力協作,感謝相關部門的大力配合,感謝姚老師的無私幫助,也感謝老婆默默的支持。

ありがとうございます 

 

如何集中資源做成一個優秀的項目,如何擔當得起自己的責任,如何與各類角色溝通,真是任重而道遠。






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM