天天看點

使用XStream處理Xml文檔和實體類之間的轉換的幾種方式

首先說一下背景(覺得沒用可以直接跳過看代碼),最近在和其他系統做對接的時候用到了xml作為傳輸格式的内容,涉及到了xml和實體類的互相轉換,然後也上網查了一下,一開始嘗試了dom4j不過發現有些繁瑣,後來繼續查資料,找到了XStream,發現這個還是很好用的,作為總結也把使用方法寫一下,供大家參考吧,不足之處望指出!

1.項目結構(PersonList.java沒卵用的,忽略之)

使用XStream處理Xml文檔和實體類之間的轉換的幾種方式

2.pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>Test</groupId>
	<artifactId>com.Generic.test</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>xstream</groupId>
			<artifactId>xstream</artifactId>
			<version>1.2.2</version>
		</dependency>
	</dependencies>
</project>
           

3.實體類

這裡用了一個比較簡單的例子——教室和人的關系,也就是一個1:n的關系(我就是覺得這兩個實體類比較省事...寫Demo嘛...)

3.1 ClassRoom類

package com.entity;

import java.util.List;

public class ClassRoom {
	private String className;
	private int studentNum;
	private List<Person> persons;
        /*set和get方法不再列出*/
}
           

3.2 Person類

package com.entity;

import java.io.Serializable;

public class Person implements Serializable{
	private static final long serialVersionUID = 1L;
	
	private String uid;
	private String name;
	private int age;
        /*set 和 get 方法不再給出*/
}
           

4.工具類

這裡為了使代碼能夠複用,使用了Class類,回頭可以試試用泛型的寫法,正好自己最近也在看這塊,還需要實踐啊

package com.utils;

import com.entity.ClassRoom;
import com.entity.Person;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

public class XmlHelper {
	
	public Object convertXmlStrToObjectList(Class mainClazz, Class detailClazz,String xmlStr, String strIgnore){
		Object object = null;
		try{
		XStream xStream = new XStream(new DomDriver());
		xStream.alias("body", mainClazz);  //這裡指定從body節點開始解析mainClass實體類
		//xStream.addImplicitCollection(mainClazz, strIgnore);
		xStream.alias("record", detailClazz);
		object = xStream.fromXML(xmlStr);
		}catch(Exception e){
			System.out.println(e.getMessage());
		}
		return object;
	}
	
	public String converObjectToXmlStr(Class mainClazz, Class detailClazz, Object object, String strIgnore){
		String xmlStr = "";
		try {
			XStream xStream = new XStream(new DomDriver());
			xStream.alias("body", mainClazz);
			xStream.alias("record", detailClazz);
			//xStream.addImplicitCollection(mainClazz, strIgnore);  這裡下面再說
			xmlStr = xStream.toXML(object);
		} catch (Exception e) {
			System.out.println(e.getMessage());
		}
		return xmlStr;
	}
}
           

5.測試類

package com.Generic.test;

import java.util.ArrayList;
import java.util.List;
import com.entity.ClassRoom;
import com.entity.Person;
import com.utils.XmlHelper;

public class MainClass {
	public static void main(String[] args) {
		String xmlStr = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>"
				+ "<body>"
				+ "<className>Class1</className>"
				+ "<studentNum>2</studentNum>"
				+ "<persons>"
				+ "<record>"
				+ "<uid>1</uid>"
				+ "<name>ZhangSan</name>"
				+ "<age>18</age>"
				+ "</record>"
				+ "<record>"
				+ "<uid>2</uid>"
				+ "<name>LiSi</name>"
				+ "<age>20</age>"
				+ "</record>"
				+ "</persons>"
				+ "</body>";
		XmlHelper xmlHelper = new XmlHelper();
		ClassRoom classRoom = (ClassRoom)xmlHelper.convertXmlStrToObjectList(ClassRoom.class, Person.class, xmlStr, "persons");
		System.out.println(classRoom);
		
		Person person1 = new Person();
		person1.setUid("1");
		person1.setName("ZhangSan");
		person1.setAge(21);
		
		Person person2 = new Person();
		person2.setUid("2");
		person2.setName("LiSi");
		person2.setAge(22);
		
		List<Person> persons = new ArrayList<Person>();
		persons.add(person1);
		persons.add(person2);
		
		ClassRoom classRoom2 = new ClassRoom();
		classRoom2.setClassName("三年二班");
		classRoom2.setStudentNum(2);
		classRoom2.setPersons(persons);
		
		
		xmlStr = xmlHelper.converObjectToXmlStr(ClassRoom.class, Person.class, classRoom2, "persons");
		
		System.out.println(xmlStr);
	}
}
           

6.運作結果

使用XStream處理Xml文檔和實體類之間的轉換的幾種方式

至此,基本功能完成,不過這樣的話,還是會有一些問題的,比如這個<persons>節點,因為我的ClassRoom類裡是List<Person> persons,是以XML中展現出來的是persons(廢話),那如果我希望指定其他的字段來取代persons,隻需要在程式中加上這一句

xStream.aliasField("records", mainClazz, "persons");  //為persons設定别名  具體效果請自行試驗
           

理論上,做到這一步,也就能滿足大部分需要了,然而...然而我們的小夥伴說,我們傳過去的封包不支援嵌套兩層 =_=! 啊?什麼是嵌套兩層?就是像這樣

<records>
    <record>
        ...
    </record>
    <record>
        ...
    </record>
</records>
           

這時我是不開心的...可是小夥伴都說了嵌套兩層對于他們來說比較困難,我也就隻好尋找解決方法了,還記得代碼裡屏蔽的那兩行嗎?就是這個:

xStream.addImplicitCollection(mainClazz, strIgnore); 
           

加上之後,運作,檢視結果:

使用XStream處理Xml文檔和實體類之間的轉換的幾種方式

Good!

P.S 關于XStream更多,大家可以移步下面的網站,我沒看完啊,不過看上去挺全的...關于上述程式中出現的錯誤,歡迎指出,也希望大家能有一起探讨相關技術~