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;
 
    }
 
}

推荐阅读更多精彩内容