Java對象和XML的相互轉換化


https://blog.csdn.net/u010331823/article/details/78258311

寫在前面:Jaxb是JavaEE的規范.全稱Java Architecture for XML Binding.  可以根據XML Schema產生Java類的技術.JAXB也提供了將XML實例文檔反向生成Java對象樹的方法,並能將Java對象樹的內容重新寫到XML實例文檔.  JAXB 2.0是JDK 1.6的組成部分。JAXB 2.2.3是JDK 1.7的組成部分,在實際使用不需要引入新的jar.

1. 常用注解說明
常用的annotation有:
@XmlType
@XmlElement
@XmlRootElement
@XmlAttribute
@XmlAccessorType
@XmlAccessorOrder
@XmlTransient
@XmlJavaTypeAdapter
@Temporal(TemporalType.XXXX) -->JPA中的時間處理注解,非JAXB
@XmlElementWrapper

1.@XmlType
  @XmlType用在class類的注解,常與@XmlRootElement,@XmlAccessorType一起使用。它有三個屬性:name、propOrder、namespace,經常使用的只有前兩個屬性。如:
同時使用了@XmlType(propOrder={})和@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)的時候,生成的xml只按照propOrder定義的順序生成元素
@XmlType(name = "basicStruct", propOrder = {
    "intValue",
    "stringArray",
    "stringValue"
)
在使用@XmlType的propOrder 屬性時,必須列出JavaBean對象中的所有屬性,否則會報錯。

2.@XmlRootElement
  @XmlRootElement用於類級別的注解,對應xml的跟元素,常與 @XmlType 和 @XmlAccessorType一起使用。如:
  @XmlType
  @XmlAccessorType(XmlAccessType.FIELD)
  @XmlRootElement
  public class Address {}

3.@XmlElement
  @XmlElement將java對象的屬性映射為xml的節點,在使用@XmlElement時,可通過name屬性改變java對象屬性在xml中顯示的名稱。如:
  @XmlElement(name="Address")  
  private String yourAddress;

4.@XmlAttribute
  @XmlAttribute用於把java對象的屬性映射為xml的屬性,並可通過name屬性為生成的xml屬性指定別名。如:
  @XmlAttribute(name="Country")
  private String state;
 
5.@XmlAccessorType
  @XmlAccessorType用於指定由java對象生成xml文件時對java對象屬性的訪問方式。常與@XmlRootElement、@XmlType一起使用。它的屬性值是XmlAccessType的4個枚舉值,分別為:

XmlAccessType.FIELD:java對象中的所有成員變量
XmlAccessType.PROPERTY:java對象中所有通過getter/setter方式訪問的成員變量
XmlAccessType.PUBLIC_MEMBER:java對象中所有的public訪問權限的成員變量和通過getter/setter方式訪問的成員變量
XmlAccessType.NONE:java對象的所有屬性都不映射為xml的元素
注意:@XmlAccessorType的默認訪問級別是XmlAccessType.PUBLIC_MEMBER,因此,如果java對象中的private成員變量設置了public權限的getter/setter方法,就不要在private變量上使用@XmlElement和@XmlAttribute注解,否則在由java對象生成xml時會報同一個屬性在java類里存在兩次的錯誤。同理,如果@XmlAccessorType的訪問權限為XmlAccessType.NONE,如果在java的成員變量上使用了@XmlElement或@XmlAttribute注解,這些成員變量依然可以映射到xml文件。

注意:雖然@XmlAccessorType為XmlAccessType.NONE,但是在java類的私有屬性上加了@XmlAttribute和@XmlElement注解后,這些私有成員會映射生成xml的元素

6.@XmlAccessorOrder
  @XmlAccessorOrder用於對java對象生成的xml元素進行排序。它有兩個屬性值:
  AccessorOrder.ALPHABETICAL:對生成的xml元素按字母書序排序
  XmlAccessOrder.UNDEFINED:不排序

7.@XmlTransient
  @XmlTransient用於標示在由java對象映射xml時,忽略此屬性。即,在生成的xml文件中不出現此元素。

8.@XmlJavaTypeAdapter
  @XmlJavaTypeAdapter常用在轉換比較復雜的對象時,如map類型或者格式化日期等。使用此注解時,需要自己寫一個adapter類繼承XmlAdapter抽象類,並實現里面的方法。
  @XmlJavaTypeAdapter(value=xxx.class),value為自己定義的adapter類
  XmlAdapter 抽象接口如下:

public abstract class XmlAdapter<ValueType,BoundType> {    // Do-nothing constructor for the derived classes.
    protected XmlAdapter() {}
    // Convert a value type to a bound type.
    public abstract BoundType unmarshal(ValueType v);
    // Convert a bound type to a value type.
    public abstract ValueType marshal(BoundType v);
 }

 

 

 

下面舉一個簡單的例子:

1.School類 一些基本的屬性,包含Student集合

package com.gs.mountain.test.xml;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.ArrayList;
import java.util.List;
@XmlRootElement(name="list")
public class School {
private String name;
private String address;
private String level;
private long popular;
private List<Student> students=new ArrayList<Student>();
@XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement(name = "address")
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
@XmlElement(name = "level")
public String getLevel() {
return level;
}
public void setLevel(String level) {
this.level = level;
}
@XmlElement(name = "popular")
public long getPopular() {
return popular;
}
public void setPopular(long popular) {
this.popular = popular;
}
@XmlElement(name = "Student")
public List<Student> getStudents() {
return students;
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
2.Student類,包含愛好集合和一些基本的屬性

package com.gs.mountain.test.xml;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import java.util.List;

public class Student {
String name; //姓名
String sex; //性別
int number; //學號
String className; //班級
List<String> hobby; //愛好

public Student(){
}
public Student(String name,String sex,int number,
String className,List<String> hobby) {
this.name = name;
this.sex = sex;
this.number = number;
this.className = className;
this.hobby = hobby;
}
@XmlAttribute(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

@XmlAttribute(name="sex")
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}

@XmlAttribute(name="number")
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}

@XmlElement(name="className")
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}

@XmlElementWrapper(name="hobbys")
@XmlElement(name = "hobby")
public List<String> getHobby() {
return hobby;
}
public void setHobby(List<String> hobby) {
this.hobby = hobby;
}

}
3.工具類,提供xml到javaBean的相互轉換 由 valvin大神提供,很好用(自己看其中的方法,說不定有你需要的)

/**
* Copyright (c) 2005-2012 springside.org.cn
*/
package com.gs.mountain.common.mapper;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.namespace.QName;

import com.gs.mountain.common.utils.StringUtils;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.util.Assert;

import com.gs.mountain.common.utils.Exceptions;
import com.gs.mountain.common.utils.Reflections;

/**
* 使用Jaxb2.0實現XML<->Java Object的Mapper.
*
* 在創建時需要設定所有需要序列化的Root對象的Class.
* 特別支持Root對象是Collection的情形.
*
* @author calvin
* @version 2013-01-15
*/
@SuppressWarnings("rawtypes")
public class JaxbMapper {

private static ConcurrentMap<Class, JAXBContext> jaxbContexts = new ConcurrentHashMap<Class, JAXBContext>();

/**
* Java Object->Xml without encoding.
*/
public static String toXml(Object root) {
Class clazz = Reflections.getUserClass(root);
return toXml(root, clazz, null);
}

/**
* Java Object->Xml with encoding.
*/
public static String toXml(Object root, String encoding) {
Class clazz = Reflections.getUserClass(root);
return toXml(root, clazz, encoding);
}

/**
* Java Object->Xml with encoding.
*/
public static String toXml(Object root, Class clazz, String encoding) {
try {
StringWriter writer = new StringWriter();
createMarshaller(clazz, encoding).marshal(root, writer);
return writer.toString();
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
}

/**
* Java Collection->Xml without encoding, 特別支持Root Element是Collection的情形.
*/
public static String toXml(Collection<?> root, String rootName, Class clazz) {
return toXml(root, rootName, clazz, null);
}

/**
* Java Collection->Xml with encoding, 特別支持Root Element是Collection的情形.
*/
public static String toXml(Collection<?> root, String rootName, Class clazz, String encoding) {
try {
CollectionWrapper wrapper = new CollectionWrapper();
wrapper.collection = root;

JAXBElement<CollectionWrapper> wrapperElement = new JAXBElement<CollectionWrapper>(new QName(rootName),
CollectionWrapper.class, wrapper);

StringWriter writer = new StringWriter();
createMarshaller(clazz, encoding).marshal(wrapperElement, writer);

return writer.toString();
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
}

/**
* Xml->Java Object.
*/
@SuppressWarnings("unchecked")
public static <T> T fromXml(String xml, Class<T> clazz) {
try {
StringReader reader = new StringReader(xml);
return (T) createUnmarshaller(clazz).unmarshal(reader);
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
}

/**
* 創建Marshaller並設定encoding(可為null).
* 線程不安全,需要每次創建或pooling。
*/
public static Marshaller createMarshaller(Class clazz, String encoding) {
try {
JAXBContext jaxbContext = getJaxbContext(clazz);

Marshaller marshaller = jaxbContext.createMarshaller();

marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

if (StringUtils.isNotBlank(encoding)) {
marshaller.setProperty(Marshaller.JAXB_ENCODING, encoding);
}

return marshaller;
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
}

/**
* 創建UnMarshaller.
* 線程不安全,需要每次創建或pooling。
*/
public static Unmarshaller createUnmarshaller(Class clazz) {
try {
JAXBContext jaxbContext = getJaxbContext(clazz);
return jaxbContext.createUnmarshaller();
} catch (JAXBException e) {
throw Exceptions.unchecked(e);
}
}

protected static JAXBContext getJaxbContext(Class clazz) {
Assert.notNull(clazz, "'clazz' must not be null");
JAXBContext jaxbContext = jaxbContexts.get(clazz);
if (jaxbContext == null) {
try {
jaxbContext = JAXBContext.newInstance(clazz, CollectionWrapper.class);
jaxbContexts.putIfAbsent(clazz, jaxbContext);
} catch (JAXBException ex) {
throw new HttpMessageConversionException("Could not instantiate JAXBContext for class [" + clazz
+ "]: " + ex.getMessage(), ex);
}
}
return jaxbContext;
}

/**
* 封裝Root Element 是 Collection的情況.
*/
public static class CollectionWrapper {

@XmlAnyElement
protected Collection<?> collection;
}

}

4.下面是測試的代碼,結果很棒,so easy!


package com.gs.mountain.test.xml;

import com.gs.mountain.common.mapper.JaxbMapper;

import javax.xml.bind.JAXBException;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class BeanToXml {

public static void main(String[] args) throws JAXBException, IOException {
List<String> hobby = new ArrayList();
hobby.add("籃球");
hobby.add("音樂");
hobby.add("乒乓球");

List<Student> studentList = new ArrayList();

Student st = new Student("張三","男",10001,"尖子班",hobby);
studentList.add(st);
Student st1 = new Student("李四","男",10002,"普通班",hobby);
studentList.add(st1);
Student st2 = new Student("莉莉","女",10003,"普通班",hobby);
studentList.add(st2);

School school = new School();
School school1 ;
School school2 ;
school.setAddress("成都市武侯區天府五街");
school.setLevel("高級中學");
school.setName("華陽中學");
school.setPopular(5000L);
school.setStudents(studentList);
school1=school;
school2=school;
List<School> listSchool=new ArrayList<School>();
listSchool.add(school);
listSchool.add(school1);
listSchool.add(school2);
String str = JaxbMapper.toXml(listSchool,"schoolList",School.class);

//寫入到xml文件中
String xmlPath = "D:/testConfig.xml";
BufferedWriter bfw = new BufferedWriter(new FileWriter(new File(xmlPath)));
bfw.write(str);
bfw.close();
}
}


下面是由listSchool轉化成的xml文件,內容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<schoolList>
<list>
<address>成都市武侯區天府五街</address>
<level>高級中學</level>
<name>華陽中學</name>
<popular>5000</popular>
<Student name="張三" number="10001" sex="男">
<className>尖子班</className>
<hobbys>
<hobby>籃球</hobby>
<hobby>音樂</hobby>
<hobby>乒乓球</hobby>
</hobbys>
</Student>
<Student name="李四" number="10002" sex="男">
<className>普通班</className>
<hobbys>
<hobby>籃球</hobby>
<hobby>音樂</hobby>
<hobby>乒乓球</hobby>
</hobbys>
</Student>
<Student name="莉莉" number="10003" sex="女">
<className>普通班</className>
<hobbys>
<hobby>籃球</hobby>
<hobby>音樂</hobby>
<hobby>乒乓球</hobby>
</hobbys>
</Student>
</list>
<list>
<address>成都市武侯區天府五街</address>
<level>高級中學</level>
<name>華陽中學</name>
<popular>5000</popular>
<Student name="張三" number="10001" sex="男">
<className>尖子班</className>
<hobbys>
<hobby>籃球</hobby>
<hobby>音樂</hobby>
<hobby>乒乓球</hobby>
</hobbys>
</Student>
<Student name="李四" number="10002" sex="男">
<className>普通班</className>
<hobbys>
<hobby>籃球</hobby>
<hobby>音樂</hobby>
<hobby>乒乓球</hobby>
</hobbys>
</Student>
<Student name="莉莉" number="10003" sex="女">
<className>普通班</className>
<hobbys>
<hobby>籃球</hobby>
<hobby>音樂</hobby>
<hobby>乒乓球</hobby>
</hobbys>
</Student>
</list>
<list>
<address>成都市武侯區天府五街</address>
<level>高級中學</level>
<name>華陽中學</name>
<popular>5000</popular>
<Student name="張三" number="10001" sex="男">
<className>尖子班</className>
<hobbys>
<hobby>籃球</hobby>
<hobby>音樂</hobby>
<hobby>乒乓球</hobby>
</hobbys>
</Student>
<Student name="李四" number="10002" sex="男">
<className>普通班</className>
<hobbys>
<hobby>籃球</hobby>
<hobby>音樂</hobby>
<hobby>乒乓球</hobby>
</hobbys>
</Student>
<Student name="莉莉" number="10003" sex="女">
<className>普通班</className>
<hobbys>
<hobby>籃球</hobby>
<hobby>音樂</hobby>
<hobby>乒乓球</hobby>
</hobbys>
</Student>
</list>
</schoolList>


————————————————
版權聲明:本文為CSDN博主「mountainGS」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/u010331823/java/article/details/78258311


免責聲明!

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



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