Java获取并解析XML(JavaBean和XML的转化)

最近遇到一个问题,需要从一个url获取xml文档并解析,google了很多方法,大多数都
是获取到XML然后循环遍历拿到数据,但是感觉很麻烦,并且感觉当数据量比较大的时候效率也不怎么
高,后面研究了下,发现JAXB这个好东西,可以实现JavaBean和XML节点元素的互相转换,故此总结一
下:

1、相关链接

2、准备工作

需要安装JAXB和dom4j,如果用的Maven,可以访问上面的url,并搜索JAXB和dom4j,选择需要的版本
,复制下面的代码配置到自己的项目中:

3、获取并解析

先看一下返回的XML格式

<HotelGeos>
    <HotelGeoList>
        <HotelGeo CityCode="0101" CityName="北京市" Country="中国" ProvinceId="0100" ProvinceNam
                  e="北京市">
            <CommericalLocations>
                <Location Id="010103" Name="天安门/王府井商业区"/>
                <Location Id="010119" Name="前门/大栅栏"/>
            </CommericalLocations>
            <Districts>
                <Location Id="0001" Name="浦东新区"/>
                <Location Id="0028" Name="闵行区"/>
            </Districts>
            <LandmarkLocations>
                <Location Id="60000283" Name="上海虹桥站"/>
                <Location Id="60000282" Name="上海站"/>
            </LandmarkLocations>
        </HotelGeo>
    </HotelGeoList>
</HotelGeos>
解析
public static void main(String[] args) {
       //获取XML
       SAXReader reader = new SAXReader();
       org.dom4j.Document document = reader.read(new URL("http://api.************************                */v2.0/hotel/geo_cn.xml")));
       String documentStr = document.asXML();
       //将xml字符串转换为java对象
       JaxbUtil resultBinder = new JaxbUtil(HotelGeos.class, JaxbUtil.CollectionWrapper.class);
       HotelGeos hotelObj = resultBinder.fromXml(documentStr);
       //将java对象转换为XML字符串
       HotelGeos hotelGeos=new HotelGeos();
       List<HotelGeo> hotelGeoList=new ArrayList<>();
       HotelGeo hotelGeo =new HotelGeo();
       hotelGeo.setCityCode("0101");
       hotelGeo.setCityName("北京市");
       hotelGeo.setCountry("中国");
       hotelGeo.setProvinceId("0100");
       hotelGeo.setProvinceName("北京市");
       //其他层级的这里就不一一赋值了
       hotelGeoList.add(hotelGeo);
       hotelGeos.setHotelGeoList(hotelGeoList);
       JaxbUtil requestBinder = new JaxbUtil(HotelGeos.class, CollectionWrapper.class);
       String retXml = requestBinder.toXml(hotelGeos, "utf-8");
       System.out.println("xml:"+retXml);
   }
相关类之HotelGeos
package com .*****.geoData.items;
   import lombok.Data;
   import javax.xml.bind.annotation .*;
   import java.util.List;

   /**
    * Created by IntelliJ IDEA.
    * User: Steven
    * Date: 2019/12/05
    * Time: 13:36
    */
   @Data
   @XmlRootElement(name = "HotelGeos")
   public class HotelGeos {
       @XmlElementWrapper(name = "HotelGeoList")
       @XmlElement(name = "HotelGeo")
       private List<HotelGeo> HotelGeoList;
   }
HotelGeo
package com.***.geoData.items;
   import lombok.Data;
   import org.codehaus.jackson.map.annotate.JsonSerialize;
   import javax.xml.bind.annotation.XmlAttribute;
   import javax.xml.bind.annotation.XmlElement;
   import javax.xml.bind.annotation.XmlElementWrapper;
   import java.io.Serializable;
   import java.util.List;
   /**
    * Created by IntelliJ IDEA.
    * User: Steven
    * Date: 2019/12/06
    * Time: 13:38
    */
   @Data
   @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
   public class HotelGeo implements Serializable {
       @XmlAttribute(name = "CityCode")
       private String CityCode;
       @XmlAttribute(name = "CityName")
       private String CityName;
       @XmlAttribute(name = "Country")
       private String Country;
       @XmlAttribute(name = "ProvinceId")
       private String ProvinceId;
       @XmlAttribute(name = "ProvinceName")
       private String ProvinceName;
       @XmlElementWrapper(name = "CommericalLocations")
       @XmlElement(name = "Location") //这里需要格外注意,层级很容易写错
       private List<Location> CommericalLocations;
       @XmlElementWrapper(name = "Districts")
       @XmlElement(name = "Location")
       private List<Location> Districts;
       @XmlElementWrapper(name = "LandmarkLocations")
       @XmlElement(name = "Location")
       private List<Location> LandmarkLocations;
   }
Location
    package com.*****.geoData.items;
    import lombok.Data;
    import org.codehaus.jackson.map.annotate.JsonSerialize;
    import javax.xml.bind.annotation.XmlAttribute;
    import java.io.Serializable;
    /**
     * Created by IntelliJ IDEA.
     * User: Steven
     * Date: 2019/12/06
     * Time: 13:53
     */
    @Data
    @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
    public class Location implements Serializable {
        @XmlAttribute(name = "Id")
        private String Id;
        @XmlAttribute(name = "Name")
        private String Name;
    }
JaxbUtil工具类

package com.*****.utils;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Collection;
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 org.apache.commons.lang.StringUtils;
/**
 * 使用Jaxb2.0实现XML<->Java Object的Binder.
 *
 * 特别支持Root对象是List的情形.
 *
 * @author
 */public class JaxbUtil {
    // 多线程安全的Context.
    private JAXBContext jaxbContext;
    /**
     * @param types
     * 所有需要序列化的Root对象的类型.
     */
    public JaxbUtil(Class<?>... types) {
        try {
            jaxbContext = JAXBContext.newInstance(types);
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * Java Object->Xml.
     */
    public String toXml(Object root, String encoding) {
        try {
            StringWriter writer = new StringWriter();
            createMarshaller(encoding).marshal(root, writer);
            return writer.toString();
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * Java Object->Xml, 特别支持对Root Element是Collection的情形.
     */
    @SuppressWarnings("unchecked")
    public String toXml(Collection root, String rootName, String encoding) {
        try {
            CollectionWrapper wrapper = new CollectionWrapper();
            wrapper.collection = root;
            JAXBElement<CollectionWrapper> wrapperElement = new JAXBElement<CollectionWrap
            per>(
                    new QName(rootName), CollectionWrapper.class, wrapper);
            StringWriter writer = new StringWriter();
            createMarshaller(encoding).marshal(wrapperElement, writer);
            return writer.toString();
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }/**
     * Xml->Java Object.
     */
    @SuppressWarnings("unchecked")
    public <T> T fromXml(String xml) {
        try {
            StringReader reader = new StringReader(xml);
            return (T) createUnmarshaller().unmarshal(reader);
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * Xml->Java Object, 支持大小写敏感或不敏感.
     */
    @SuppressWarnings("unchecked")
    public <T> T fromXml(String xml, boolean caseSensitive) {
        try {
            String fromXml = xml;
            if (!caseSensitive)
                fromXml = xml.toLowerCase();
            StringReader reader = new StringReader(fromXml);
            return (T) createUnmarshaller().unmarshal(reader);
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }
    /**
     * 创建Marshaller, 设定encoding(可为Null).
     */
    public Marshaller createMarshaller(String encoding) {
        try {
            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 new RuntimeException(e);
        }
    }
/**
 * 创建UnMarshaller
*/
 public Unmarshaller createUnmarshaller() {
        try {
            return jaxbContext.createUnmarshaller();
        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }
 
  /**
  * 封装Root Element 是 Collection的情况.
  */

    public static class CollectionWrapper {
 
        @SuppressWarnings("unchecked")
 
        @XmlAnyElement
 
        protected Collection collection;
 
    }
 
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容