zoukankan      html  css  js  c++  java
  • Jaxb2 转换XML文档

    ——完成Java对象和XML相互转换

    前面有介绍过json-lib这个框架,在线博文:http://www.cnblogs.com/hoojo/archive/2011/04/21/2023805.html

    以及Jackson这个框架,在线博文:http://www.cnblogs.com/hoojo/archive/2011/04/22/2024628.html

    它们都可以完成Java对象到XML的转换,但是还不是那么的完善。

    还有XStream对JSON及XML的支持,它可以对JSON或XML的完美转换。在线博文:

    http://www.cnblogs.com/hoojo/archive/2011/04/22/2025197.html

    以及介绍Castor来完成Java对象到xml的相互转换。在线博文:http://www.cnblogs.com/hoojo/archive/2011/04/25/2026819.html

    这次介绍Jaxb2完成xml的转换,Jaxb2使用了JDK的新特性。如:Annotation、GenericType等,Jaxb2需要在即将转换的JavaBean中添加annotation注解。下面我们就来看看Jaxb2是怎么样完成Java对象到XML之间的相互转换吧。

    一、 准备工作

    1、 资源准备

    a) 官方文档:http://www.oracle.com/technetwork/articles/javase/index-140168.html

    b) Jar包下载:http://jaxb.java.net/2.2.3/JAXB2_20101209.jar

    如果你有添加jdk的jar到工程中,在rt.jar中就带有jaxb2。一般情况下不用自己添加jaxb2的jar。

    2、 程序前代码准备

    package com.hoo.test;
     
    import java.io.IOException;
    import java.io.StringReader;
    import java.io.StringWriter;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import com.hoo.entity.Account;
    import com.hoo.entity.AccountBean;
    import com.hoo.entity.Birthday;
    import com.hoo.entity.ListBean;
    import com.hoo.entity.MapBean;
     
    /**
     * function:Jaxb2 完成Java和XML的编组、解组
     * @author hoojo
     * @createDate 2011-4-25 上午11:54:06
     * @file Jaxb2Test.java
     * @package com.hoo.test
     * @project WebHttpUtils
     * @blog http://blog.csdn.net/IBM_hoojo
     * @email hoojo_@126.com
     * @version 1.0
     */
    public class Jaxb2Test {
        private JAXBContext context = null;
        
        private StringWriter writer = null;
        private StringReader reader = null;
        
        private AccountBean bean = null;
        
        @Before
        public void init() {
            bean = new AccountBean();
            bean.setAddress("北京");
            bean.setEmail("email");
            bean.setId(1);
            bean.setName("jack");
            Birthday day = new Birthday();
            day.setBirthday("2010-11-22");
            bean.setBirthday(day);
            
            try {
                context = JAXBContext.newInstance(AccountBean.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        
        @After
        public void destory() {
            context = null;
            bean = null;
            try {
                if (writer != null) {
                    writer.flush();
                    writer.close();
                }
                if (reader != null) {
                    reader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            System.gc();
        }
        
        public void fail(Object o) {
            System.out.println(o);
        }
        
        public void failRed(Object o) {
            System.err.println(o);
        }
    }

    通过JAXBContext的newInstance方法,传递一个class就可以获得一个上下文。 newInstance方法也可以传递一个xml的文件的path。通过xml文件,对class的描述进行转换。然后,就可以通过这个上下文的来创建一个Marshaller,通过Marshaller对象的marshal方法就可以转换JavaBean对象到xml。同样JAXBContext也可以创建一个Unmarshall的unmarshal方法可以进行xml到Java对象的解组。

    二、 Java编组、XML解组

    1、 JavaBean和XML的相互转换

    代码如下:

    @Test
    public void testBean2XML() {
        try {
            //下面代码演示将对象转变为xml
            Marshaller mar = context.createMarshaller();
            writer = new StringWriter();
            mar.marshal(bean, writer);
            fail(writer);
            
            //下面代码演示将上面生成的xml转换为对象
            reader = new StringReader(writer.toString());
            Unmarshaller unmar = context.createUnmarshaller();
            bean = (AccountBean)unmar.unmarshal(reader);
            fail(bean);
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    上面的context是在init方法中创建的,它传递了一个AccountBean的class,这个AccountBean不是一般的普通的bean。除了它带有getter、setter方法外,还有Annotation注解。下面我们就看看这个bean的代码。

    package com.hoo.entity;
     
    import javax.xml.bind.annotation.XmlAttribute;
    import javax.xml.bind.annotation.XmlRootElement;
    import com.sun.xml.internal.txw2.annotation.XmlElement;
     
    @XmlRootElement(name = "account")
    public class AccountBean {
        private int id;
        private String name;
        private String email;
        private String address;
        private Birthday birthday;
        
        @XmlElement
        public Birthday getBirthday() {
            return birthday;
        }
        public void setBirthday(Birthday birthday) {
            this.birthday = birthday;
        }
        
        @XmlAttribute(name = "number")
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        
        @XmlElement
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        
        @XmlElement
        public String getEmail() {
            return email;
        }
        public void setEmail(String email) {
            this.email = email;
        }
        
        @XmlElement
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        
        @Override
        public String toString() {
            return this.name + "#" + this.id + "#" + this.address + "#" + this.birthday + "#" + this.email;
        }
    }

    上面的XmlRootElement是设置当前对象转换成xml后的根节点,name的值是设置根节点的名称。在getter方法上设置XmlElement表示这个方法对应的属性是一个xml元素,如果这个注解还设置了name,那么这个name就是转换后xml的名称。在一个属性上设置XmlAttribute,表示这个方法对应的属性在转换xml后是父元素的一个属性。XmlAttribute的name就是转换后xml的属性的name。

    运行后,结果如下:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><account number="1"><address>北京</address>
    <birthday><birthday>2010-11-22</birthday></birthday><email>email</email><name>jack</name></account>
    jack#1#北京#2010-11-22#email

    把转换后的xml和上面的AccountBean对应看看

    2、 对List类型对象,进行编组、解组

    @Test
    public void testList2XML() {
        ListBean listBean = new ListBean();
        listBean.setName("list to xml");
        List<Object> list = new ArrayList<Object>();
        list.add(bean);
        bean = new AccountBean();
        bean.setAddress("china");
        bean.setEmail("tom@125.com");
        bean.setId(2);
        bean.setName("tom");
        Birthday day = new Birthday("2010-11-22");
        bean.setBirthday(day);
        
        Account acc = new Account();
        acc.setAddress("china");
        acc.setEmail("tom@125.com");
        acc.setId(2);
        acc.setName("tom");
        day = new Birthday("2010-11-22");
        acc.setBirthday(day);
        list.add(bean);
        list.add(acc);
        listBean.setList(list);
        
        try {
            context = JAXBContext.newInstance(ListBean.class);
            //下面代码演示将对象转变为xml
            Marshaller mar = context.createMarshaller();
            writer = new StringWriter();
            mar.marshal(listBean, writer);
            fail(writer);
            
            //下面代码演示将上面生成的xml转换为对象
            reader = new StringReader(writer.toString());
            Unmarshaller unmar = context.createUnmarshaller();
            listBean = (ListBean)unmar.unmarshal(reader);
            fail(listBean.getList().get(0));
            fail(listBean.getList().get(1));
            fail(listBean.getList().get(2));
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    你不能直接new 一个List,然后将对象放到List中。进行编组、解组,这样会出现异常情况的。你需要构建一个JavaBean,在bean中创建一个List的属性。然后在这个属性的getter方法上进行Annotation注解。下面我们看看ListBean的代码:

    package com.hoo.entity;
     
    import java.util.List;
    import javax.xml.bind.annotation.XmlAttribute;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlElements;
    import javax.xml.bind.annotation.XmlRootElement;
     
    @SuppressWarnings("unchecked")
    @XmlRootElement(name = "list-bean")
    public class ListBean {
        private String name;
        private List list;
        
        @XmlElements({
            @XmlElement(name = "account", type = Account.class),
            @XmlElement(name = "bean", type = AccountBean.class)
        })
        public List getList() {
            return list;
        }
     
        public void setList(List list) {
            this.list = list;
        }
        
        @XmlAttribute
        public String getName() {
            return name;
        }
     
        public void setName(String name) {
            this.name = name;
        }
    }

    XmlElements表示是一个集合类型,然后注解在集合中存放上面类型的对象。

    XmlElement表示在集合中存放的一个对象类型和元素名称。

    转换后结果如下:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <list-bean name="list to xml">
    <bean number="1"><address>北京</address><birthday><birthday>2010-11-22</birthday></birthday>
    <email>email</email><name>jack</name></bean>
    <bean number="2"><address>china</address><birthday><birthday>2010-11-22</birthday></birthday>
    <email>tom@125.com</email><name>tom</name></bean>
    <account><address>china</address><birthday><birthday>2010-11-22</birthday></birthday>
    <email>tom@125.com</email><id>2</id><name>tom</name></account>
    </list-bean>
    jack#1#北京#2010-11-22#email
    tom#2#china#2010-11-22#tom@125.com
    2#tom#tom@125.com#china#2010-11-22

    转换后的XML和Bean的注解的描述是一样的吧。

    2、 对Map集合进行解组、编组

    /**
     * <b>function:</b>Map需要自己实现,可以构造一个简单的Map对象实现
     * http://metro.1045641.n5.nabble.com/Does-JAXB-2-0-support-Map-td1058084.html
     * @author hoojo
     * @createDate 2010-12-1 上午10:23:26
     */
    @Test
    public void testMap2XML() {
        MapBean mapBean = new MapBean();
        HashMap<String, AccountBean> map = new HashMap<String, AccountBean>();
        map.put("NO1", bean);
        bean = new AccountBean();
        bean.setAddress("china");
        bean.setEmail("tom@125.com");
        bean.setId(2);
        bean.setName("tom");
        Birthday day = new Birthday("2010-11-22");
        bean.setBirthday(day);
        map.put("NO2", bean);
        mapBean.setMap(map);
        
        try {
            context = JAXBContext.newInstance(MapBean.class);
            //下面代码演示将对象转变为xml
            Marshaller mar = context.createMarshaller();
            writer = new StringWriter();
            mar.marshal(mapBean, writer);
            fail(writer);
            
            //下面代码演示将上面生成的xml转换为对象
            reader = new StringReader(writer.toString());
            Unmarshaller unmar = context.createUnmarshaller();
            mapBean = (MapBean)unmar.unmarshal(reader);
            fail(mapBean.getMap());
        } catch (JAXBException e) {
            e.printStackTrace();
        }
    }

    下面看看MapBean的代码

    package com.hoo.entity;
     
    import java.util.HashMap;
    import javax.xml.bind.annotation.XmlRootElement;
    import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
    import com.hoo.util.MapAdapter;
     
    @XmlRootElement
    public class MapBean {
        private HashMap<String, AccountBean> map;
        
        @XmlJavaTypeAdapter(MapAdapter.class)
        public HashMap<String, AccountBean> getMap() {
            return map;
        }
        public void setMap(HashMap<String, AccountBean> map) {
            this.map = map;
        }
    }

    上面的map集合的getter方法有一个XmlJavaTypeAdapter,需要传递一个Adapter的类型。

    下面看看MyAdapter的代码

    package com.hoo.util;
     
    import java.util.HashMap;
    import java.util.Map;
    import javax.xml.bind.annotation.adapters.XmlAdapter;
    import com.hoo.entity.AccountBean;
     
    /**
     * <b>function:</b>AccountBean 编组、解组的XmlAdapter
     * @author hoojo
     * @createDate 2011-4-25 下午05:03:18
     * @file MyAdetper.java
     * @package com.hoo.util
     * @project WebHttpUtils
     * @blog http://blog.csdn.net/IBM_hoojo
     * @email hoojo_@126.com
     * @version 1.0
     */
    public class MapAdapter extends XmlAdapter<MapElements[], Map<String, AccountBean>> {
        public MapElements[] marshal(Map<String, AccountBean> arg0) throws Exception {
            MapElements[] mapElements = new MapElements[arg0.size()];
     
            int i = 0;
            for (Map.Entry<String, AccountBean> entry : arg0.entrySet())
                mapElements[i++] = new MapElements(entry.getKey(), entry.getValue());
     
            return mapElements;
        }
     
        public Map<String, AccountBean> unmarshal(MapElements[] arg0) throws Exception {
            Map<String, AccountBean> r = new HashMap<String, AccountBean>();
            for (MapElements mapelement : arg0)
                r.put(mapelement.key, mapelement.value);
            return r;
        }
    }

    MapElements

    package com.hoo.util;
     
    import javax.xml.bind.annotation.XmlElement;
    import com.hoo.entity.AccountBean;
     
    /**
     * <b>function:</b> MapElements
     * @author hoojo
     * @createDate 2011-4-25 下午05:04:04
     * @file MyElements.java
     * @package com.hoo.util
     * @project WebHttpUtils
     * @blog http://blog.csdn.net/IBM_hoojo
     * @email hoojo_@126.com
     * @version 1.0
     */
    public class MapElements {
        @XmlElement
        public String key;
        
        @XmlElement
        public AccountBean value;
     
        @SuppressWarnings("unused")
        private MapElements() {
        } // Required by JAXB
     
        public MapElements(String key, AccountBean value) {
            this.key = key;
            this.value = value;
        }
    }

    运行结果如下:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?><mapBean><map><item><key>NO2</key><value number="2"><address>china</address>
    <birthday><birthday>2010-11-22</birthday></birthday><email>tom@125.com</email><name>tom</name></value></item>
    <item><key>NO1</key><value number="1"><address>北京</address><birthday><birthday>2010-11-22</birthday></birthday>
    <email>email</email><name>jack</name></value></item></map></mapBean>
    {NO2=tom#2#china#2010-11-22#tom@125.com, NO1=jack#1#北京#2010-11-22#email}
  • 作者:hoojo
    出处:
    blog:http://blog.csdn.net/IBM_hoojo
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权所有,转载请注明出处 本文出自:
分享道版权所有,欢迎转载,转载请注明出处,谢谢
收藏
关注
评论
查看全文
  • 相关阅读:
    查询是哪个进程占用了特定端口
    (面向c#开发人员) 编写javascript的好习惯一 false 值
    onerror 事件 如何使用 onerror 事件捕获网页中的错误。(chrome、opera、safari 浏览器不支持)
    查找url里面的flag元素判断操作
    jquery 弹出窗
    向上滚动
    kissy helpcenter
    kissyAPI
    IE6 动态创建 iframe 无法显示的 bug 芒果
    图片轮换动画仿GIF
  • 原文地址:https://www.cnblogs.com/hoojo/p/2029011.html
  • Copyright © 2011-2022 走看看