浅谈XML 解析技术(六)Jaxb 解析对象之手工编写xml映射类

时间:2021-04-27 14:43:44

   JaxbContext  是jdk自带的 xml 和 java 对象之间转换的API, 使用JaxbContext 进行java对象转换时,java实体类需要用相对应的注解修饰类和属性, 常用的属性有以下几个:

    @XmlAccessorType(XmlAccessType.FIELD): 修饰类

   @XmlType(name = "", propOrder = { "name", "age" }):修饰类, 指定该对象生成xml元素的顺序,只写相关xml元素,不写相关xml属性, propOrder 的值为java属性名,而不是xml属性名,这点需要注意。

   @XmlRootElement(name = "PETS"):修饰类,根元素,也就是xml元素名称

 @XmlAttribute(name = "ID"):修饰java 属性, 映射xml元素的属性,name为属性名称,区分 大小写。

    @XmlElement(name = "NAME", required = true):修饰java属性,映射xml元素,name为元素名称,区分大小写


   下面来测试一个最简单的例子:

【1. xml 片段】

<?xml version="1.0" encoding="UTF-8"?>
<STUDENT>
	<NUMBER>10001</NUMBER>
	<NAME>张三</NAME>
	<PETS>
		<PET ID="101">
			<NAME>大黄</NAME>
			<AGE>3</AGE>
		</PET>
		<PET ID="102">
			<NAME>小白</NAME>
			<AGE>2</AGE>
		</PET>
	</PETS>
</STUDENT>

【2. 映射java 实体类】

    【2.1 StudentEle.java】

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "number", "name", "pets" })
@XmlRootElement(name = "STUDENT")
public class StudentEle {

	@XmlElement(name = "NUMBER", required = true)
	protected String number;

	@XmlElement(name = "NAME", required = true)
	protected String name;

	@XmlElement(name = "PETS", required = true)
	protected PetsEle pets;

	public String getNumber() {
		return number;
	}

	public void setNumber(String number) {
		this.number = number;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public PetsEle getPets() {
		return pets;
	}

	public void setPets(PetsEle pets) {
		this.pets = pets;
	}

	@Override
	public String toString() {
		return "StudentEle [number=" + number + ", name=" + name + ", pets="
				+ pets + "]";
	}

}


    【2.2 PetsEle.java】

import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "pets"})
@XmlRootElement(name = "PETS")
public class PetsEle {

	@XmlElement(name = "PETS")
	protected List<PetEle> pets;

	public List<PetEle> getPets() {
		return pets;
	}

	public void setPets(List<PetEle> pets) {
		this.pets = pets;
	}

	@Override
	public String toString() {
		return "PetsEle [pets=" + pets + "]";
	}
	
}


    【2.3 PetEle.java】

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = { "name", "age" })
@XmlRootElement(name = "PETS")
public class PetEle {

	@XmlAttribute(name = "ID")
	protected String id;

	@XmlElement(name = "NAME", required = true)
	protected String name;

	@XmlElement(name = "AGE", required = true)
	protected String age;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getAge() {
		return age;
	}

	public void setAge(String age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "PetEle [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

}


 【3. jaxb 工具类】

import java.io.ByteArrayInputStream;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class JaxbUtil {

	private static final String DEFAULT_ENCODING = "UTF-8";

	/**
	 * @Description java对象转xml
	 * @param obj java 对象
	 * @return String
	 * @author zonggf
	 * @date 2016年6月17日  下午2:34:50
	 */
	public static String marshall(Object obj) {
		try {
			JAXBContext jaxbContext = JAXBContext.newInstance(obj.getClass());
			Marshaller marshaller = jaxbContext.createMarshaller();
			marshaller.setProperty(Marshaller.JAXB_ENCODING, DEFAULT_ENCODING);
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
					Boolean.TRUE);
			marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);

			StringWriter stringWriter = new StringWriter();
			marshaller.marshal(obj, stringWriter);
			return stringWriter.toString();

		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}

	}

	/**
	 * @Description xml 片段转换为java对象
	 * @param xml 
	 * @param clz 要转换的java类型
	 * @return T
	 * @author zonggf
	 * @date 2016年6月17日  下午2:35:35
	 */
	@SuppressWarnings("unchecked")
	public static <T> T unmarshall(String xml, Class<T> clz) {
		try {
			JAXBContext jaxbContext = JAXBContext.newInstance(clz);

			Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

			Object obj =  unmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes(DEFAULT_ENCODING)));
			
			return (T)obj;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

}


 【4. 测试】

import java.util.ArrayList;
import java.util.List;

public class TestJaxb {
	
	/** 测试java 对象转换成xml  */
	public static void test2xml(){
		StudentEle studentEle = new StudentEle();
		studentEle.setName("张三");
		studentEle.setNumber("123456");
		
		
		List<PetEle> petList = new ArrayList<PetEle>();
		PetEle petEle = new PetEle();
		petEle.setAge("2");
		petEle.setId("101");
		petEle.setName("小白");
		
		PetEle petEle2 = new PetEle();
		petEle2.setAge("5");
		petEle2.setId("100");
		petEle2.setName("大黄");
		
		petList.add(petEle);
		petList.add(petEle2);
		
		
		PetsEle pets = new PetsEle();
		pets.setPets(petList);
		
		studentEle.setPets(pets );
		
		System.out.println(JaxbUtil.marshall(studentEle));
	}
	
	/** 测试xml 转换为java 对象 */
	public static void test2Object(){
		String xml = ""
				+ "<STUDENT>"
				+ "<NUMBER>123456</NUMBER>"
				+ "<NAME>张三</NAME>"
				+ "<PETS>"
				+ "<PETS ID=\"101\">"
				+ "<NAME>小白</NAME>"
				+ "<AGE>2</AGE>"
				+ "</PETS>"
				+ "<PETS ID=\"100\">"
				+ " <NAME>大黄</NAME>"
				+ "<AGE>5</AGE>"
				+ "</PETS>"
				+ "</PETS>"
				+ "</STUDENT>";

		StudentEle studentEle = JaxbUtil.unmarshall(xml, StudentEle.class);
		System.out.println(studentEle);
		
	}

	public static void main(String[] args) {
	
		test2xml();
		System.out.println("\n\n");
		test2Object();
		
	}
	
}

【5. 测试结果】

<STUDENT>
    <NUMBER>123456</NUMBER>
    <NAME>张三</NAME>
    <PETS>
        <PETS ID="101">
            <NAME>小白</NAME>
            <AGE>2</AGE>
        </PETS>
        <PETS ID="100">
            <NAME>大黄</NAME>
            <AGE>5</AGE>
        </PETS>
    </PETS>
</STUDENT>



StudentEle [number=123456, name=张三, pets=PetsEle [pets=[PetEle [id=101, name=小白, age=2], PetEle [id=100, name=大黄, age=5]]]]

【6. 注意】

    1. 生成的xml 不包含<?xml version="1.0" encoding="UTF-8"?>

    2. jaxb相关的注解不止这几个,而且还有一些属性,具体怎样使用,可百度

    3. 根据xml 编写java 实体类是一个比较繁琐的过程,而且还容易出错。 jdk提供了根据xsd文件自动生成java实体对象的工具,可参见笔者的另一篇博客

      《webservice 中根据xml片段,反转xsd文件,生成java对象》