XML解析之JAXB (实现Java对象与XML的相互转换)



JAXBJava API for XML Binding),提供了一个快速便捷的方式将Java对象与XML进行转换。在JAX-WSJavaWebService规范之一)中,JDK1.6自带的版本JAX-WS2.1,其底层支持就是JAXB 

JAXB可以实现Java对象与XML的相互转换,在JAXB中,将一个Java对象转换为XML的过程称之为Marshal,将XML转换为Java对象的过程称之为UnMarshal。我们可以通过在 Java 类中标注注解的方式将一个Java对象绑定到一段XML,也就是说,在Java类中标注一些注解,这些注解定义了如何将这个类转换为XML,怎么转换,以及一段XML如何被解析成这个类所定义的对象;也可以使用JAXBXJC工具,通过定义schema的方式实现Java对象与XML的绑定。 


项目整体结构如下:


1.建立三个实体


People.java

package com.hys.demo.entity;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "people",namespace="abc")//设置根节点
@XmlAccessorType(XmlAccessType.FIELD)
public class People {    
 
 public String id;    
 public String name;       
 public int age;
 
 public People() {
  
 }

 public People(String id, String name, int age) {
  this.id = id;
  this.name = name;
  this.age = 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 int getAge() {
  return age;
 }

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

TestObj.java

package com.hys.demo.entity;
import java.util.Date;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;

@XmlAccessorType(XmlAccessType.FIELD)
public class TestObj {

 private long id;
 private String name; 
 private Date birthday;
 
 public TestObj() {
 
 }

 public TestObj(long id, String name, Date birthday) {
  this.id = id;
  this.name = name;
  this.birthday = birthday;
 }

 public long getId() {
  return id;
 }
 
 public void setId(long id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

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

 public Date getBirthday() {
  return birthday;
 }

 public void setBirthday(Date birthday) {
  this.birthday = birthday;
 }

}

ObjList.java

package com.hys.demo.entity;
import java.util.ArrayList;
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 com.hys.demo.entity.TestObj;

@XmlRootElement(name = "peoples")
@XmlAccessorType(XmlAccessType.FIELD)
public class ObjList {

    @XmlAttribute(name = "size")
    private int size;
    
    @XmlElement(name = "people")
    private ArrayList<TestObj> objList; 

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

 public ArrayList<TestObj> getObjList() {
  return objList;
 }

 public void setObjList(ArrayList<TestObj> objList) {
  this.objList = objList;
 }

}

2Xml文件

test.xml

<?xml version="1.0" encoding="UTF-8"?>
<peoples size="7095">
    <people>
        <id>16817</id>
        <name>张三01</name>
        <birthday>2011-12-28</birthday>
    </people>
    <people>
        <id>16817</id>
        <name>张三02</name>
        <birthday>2011-12-28</birthday>
    </people>
    <people>
        <id>16817</id>
        <name>张三03</name>
        <birthday>2011-12-28</birthday>
    </people>
</peoples>

people.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:people xmlns:ns2="abc">
    <id>001</id>
    <name>灰太狼</name>
    <age>22</age>
</ns2:people>

Java To XMLMarshal 


JaxbWriteXml.java

package com.hys.demo.marshal;
import java.util.ArrayList;
import java.util.Date;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import org.junit.Test;
import com.hys.demo.entity.ObjList;
import com.hys.demo.entity.People;
import com.hys.demo.entity.TestObj;

public class JaxbWriteXml {

	public static <T> Marshaller getMarshaller(Class<T> c) throws JAXBException{
		
		JAXBContext context = JAXBContext.newInstance(c);
		Marshaller marshaller = context.createMarshaller(); 
		//编码格式 
		marshaller.setProperty(Marshaller.JAXB_ENCODING,"UTF-8");
		//是否格式化生成的xml串    
		marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
		//是否省略xml头信息(<?xml version="1.0" encoding="gb2312" standalone="yes"?>)
		marshaller.setProperty(Marshaller.JAXB_FRAGMENT, false);
		
		return marshaller;
	}
	
	@Test
	public void test_xml() throws JAXBException{
		Marshaller marshaller = getMarshaller(People.class);
        People people = new People("001","灰太狼",22);  
        marshaller.marshal(people, System.out);   
	}
	
	@Test
	public void test_xml2() throws JAXBException{
		Marshaller marshaller = getMarshaller(ObjList.class);
        
		ArrayList<TestObj> list = new ArrayList<TestObj>(); 
        TestObj testObj1 = new TestObj(111, "灰太狼", new Date());
        TestObj testObj2 = new TestObj(222, "灰太狼", new Date());
        list.add(testObj1);
        list.add(testObj2);
        
        ObjList objlist = new ObjList();
        objlist.setObjList(list);
        marshaller.marshal(objlist, System.out);
	}
}

测试结果1

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:people xmlns:ns2="abc">
    <id>001</id>
    <name>灰太狼</name>
    <age>22</age>
</ns2:people>

测试结果2

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<peoples size="0">
    <people>
        <id>111</id>
        <name>灰太狼</name>
        <birthday>2017-01-11T17:10:01.181+08:00</birthday>
    </people>
    <people>
        <id>222</id>
        <name>灰太狼</name>
        <birthday>2017-01-11T17:10:01.182+08:00</birthday>
    </people>
</peoples>

XML To JavaUnMarshal

JaxbReadXml.java

package com.hys.demo.unMarshal;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import org.junit.Test;
import com.hys.demo.entity.ObjList;
import com.hys.demo.entity.People;
import com.hys.demo.entity.TestObj;

public class JaxbReadXml {

    @SuppressWarnings("unchecked")
    public static <T> T readString(Class<T> clazz, String context) throws JAXBException, IOException {
        try {
        	InputStream inputStream = ClassLoader.getSystemResource(context).openStream();
            JAXBContext jc = JAXBContext.newInstance(clazz);
            Unmarshaller u = jc.createUnmarshaller();
            return (T) u.unmarshal(inputStream);
        } catch (JAXBException e) {
            throw e;
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T readConfig(Class<T> clazz, String config, Object... arguments) throws IOException,
            JAXBException {
        InputStream is = null;
        try {
            if (arguments.length > 0) {
                config = MessageFormat.format(config, arguments);
            }
            // logger.trace("read configFileName=" + config);
            JAXBContext jc = JAXBContext.newInstance(clazz);
            Unmarshaller u = jc.createUnmarshaller();
            is = new FileInputStream(config);
            return (T) u.unmarshal(is);
        } catch (IOException e) {
            // logger.trace(config, e);
            throw e;
        } catch (JAXBException e) {
            // logger.trace(config, e);
            throw e;
        } finally {
            if (is != null) {
                is.close();
            }
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T readConfigFromStream(Class<T> clazz, InputStream dataStream) throws JAXBException {
        try {
            JAXBContext jc = JAXBContext.newInstance(clazz);
            Unmarshaller u = jc.createUnmarshaller();
            return (T) u.unmarshal(dataStream);
        } catch (JAXBException e) {
            // logger.trace(e);
            throw e;
        }
    }

    @Test
    public void test_xml() throws JAXBException, IOException{
    	
    	ObjList arrayObj = JaxbReadXml.readString(ObjList.class, "test.xml");
        System.out.println(arrayObj.getSize());
        
        for (TestObj testObj : arrayObj.getObjList()) {
			System.out.println("姓名:"+testObj.getName()+"  出生日期:"+testObj.getBirthday());
		}
    }
    
    @Test
    public void test_xml1() throws JAXBException, IOException{
    	
    	People People = JaxbReadXml.readString(People.class, "people.xml");
    	System.out.println("姓名:"+People.getName()+"  年龄:"+People.getAge());
    }
}

测试结果1

7095

姓名:张三01  出生日期:Wed Dec 28 00:00:00 CST 2011
姓名:张三02  出生日期:Wed Dec 28 00:00:00 CST 2011
姓名:张三03  出生日期:Wed Dec 28 00:00:00 CST 2011

测试结果2

姓名:灰太狼  年龄:22

其实Marshal UnMarshal的过程并不复杂,只需要从JAXBContext中获得MarshallerUnmarshaller对象,就可以让JAXB帮我们来进行转换了。

我们需要操作的主要内容是定义一个规则,告诉JAXB如何将一个类、按照什么样的格式转换为XML,下面是JAXB中主要的一些注解。

@XmlRootElement  将一个Java类映射为一段XML的根节点

参数:name定义这个根节点的名称;namespace  定义这个根节点命名空间

@XmlAccessorType 定义这个类中的何种类型需要映射到XML。可接收四个参数,分别是:

     XmlAccessType.FIELD:映射这个类中的所有字段到XML

     XmlAccessType.PROPERTY:映射这个类中的属性(get/set方法)到XML

     XmlAccessType.PUBLIC_MEMBER:将这个类中的所有publicfieldproperty同时映射到XML(默认)

     XmlAccessType.NONE:不映射 

@XmlElement 指定一个字段或get/set方法映射到XML的节点。如,当一个类的XmlAccessorType被标注为PROPERTY时,在某一个没有get/set方法的字段上标注此注解,即可将该字段映射到XML

参数:defaultValue 指定节点默认值 

        name            指定节点名称 

        namespace   指定节点命名空间

        required        是否必须(默认为false 

        nillable          该字段是否包含nillable="true"属性(默认为false 

        type              定义该字段或属性的关联类型   

@XmlAttribute 指定一个字段或get/set方法映射到XML的属性。 

参数:name            指定属性名称 

        namespace   指定属性命名空间

        required        是否必须(默认为false 

@XmlTransient 定义某一字段或属性不需要被映射为XML。如,当一个类的XmlAccessorType被标注为PROPERTY时,在某一get/set方法的字段上标注此注解,那么该属性则不会被映射。  

@XmlType 定义映射的一些相关规则 

参数:propOrder       指定映射XML时的节点顺序 

        factoryClass    指定UnMarshal时生成映射类实例所需的工厂类,默认为这个类本身

        factoryMethod 指定工厂类的工厂方法

        name              定义XML Schematype的名称 

        namespace     指定Schema中的命名空间 

@XmlElementWrapper 为数组元素或集合元素定义一个父节点。如,类中有一元素为List items,若不加此注解,该元素将被映射为 

   <items>...</items> 

   <items>...</items> 


这种形式,此注解可将这个元素进行包装,如: 

@XmlElementWrapper(name="items")    @XmlElement(name="item")    public List items; 

将会生成这样的XML样式: 


   <items>

       <item>...</item> 

       <item>...</item>

   </items>


@XmlJavaTypeAdapter 自定义某一字段或属性映射到XML的适配器。如,类中包含一个接口,我们可以定义一个适配器(继承自 javax.xml.bind.annotation.adapters.XmlAdapter类),指定这个接口如何映射到XML   

@XmlSchema配置整个包的namespace,这个注解需放在package-info.java文件中。 jaxb编码:

          JAXBContext jaxbContext = JAXBContext.newInstance(clazz);

           Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

           InputStreamReader reader=newInputStreamReader(inputStream,"GBK");  //在此修改编码

           return unmarshaller.unmarshal(reader);


其他:

对于要序列化(marshal)为XMLJava类,绝不能把成员变量声明为public,否则运行将抛出异常com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException

对于JAXB相关的重要Annotation的声明,如@Xml.....,可以放在成员变量的setter()getter()方法上,两者中任选其一即可,但决不能放在成员变量上,否则运行将抛出异常com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException

缺省的数据类型绑定

下面的表格列出了JAXBXML数据类型和Java数据类型的映射。

XML Schema类型

Java数据类型

xsd:string

java.lang.String

xsd:positiveInteger

java.math.BigInteger

xsd:int

int

xsd:long

long

xsd:short

short

xsd:decimal

java.math.BigDecimal

xsd:float

float

xsd:double

double

xsd:boolean

boolean

xsd:byte

byte

xsd:QName

javax.xml.namespace.QName

xsd:dateTime

javax.xml.datatype.XMLGregorianCalendar

xsd:base64Binary

byte[]

xsd:hexBinary

byte[]

xsd:unsignedInt

long

xsd:unsignedShort

int

xsd:unsignedByte

short

xsd:time

javax.xml.datatype.XMLGregorianCalendar

xsd:date

javax.xml.datatype.XMLGregorianCalendar

xsd:g

javax.xml.datatype.XMLGregorianCalendar

xsd:anySimpleType

java.lang.Object

xsd:anySimpleType

java.lang.String

xsd:duration

javax.xml.datatype.Duration

xsd:NOTATION

javax.xml.namespace.QName


  • 3
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值