使用注解标注需要被转化的Java类

@XmlRootElement(name = "Car")
public class Car {

    private String carName;

    private String carType;

    private Driver driver;

    private List<Driver> driverList;

    @XmlElement(name = "drivers")
    public List<Driver> getDriverList() {
        return driverList;
    }

    public void setDriverList(List<Driver> driverList) {
        this.driverList = driverList;
    }

    public Driver getDriver() {
        return driver;
    }

    public void setDriver(Driver driver) {
        this.driver = driver;
    }

    public String getCarName() {
        return carName;
    }

    public void setCarName(String carName) {
        this.carName = carName;
    }

    public String getCarType() {
        return carType;
    }

    public void setCarType(String carType) {
        this.carType = carType;
    }
}

@XmlRootElement
public class Driver {

    private String driverName;

    private String driverAge;

    public String getDriverName() {
        return driverName;
    }

    public void setDriverName(String driverName) {
        this.driverName = driverName;
    }

    public String getDriverAge() {
        return driverAge;
    }

    public void setDriverAge(String driverAge) {
        this.driverAge = driverAge;
    }
}

实例中仅用了最简单的注解使用方法,即先用@XmlRootElement标注在类名上,默认会使用类名作为xml根节点,可以使用name属性指定标签名称。@XmlElement则标注在属性上用来定义子标签。更多详细的注解请参考https://zhuanlan.zhihu.com/p/343893930

bean转xml方法

public static void main(String[] args) throws JAXBException {

        Car car = new Car();
        car.setCarName("123");
        car.setCarType("456");

        Driver driver = new Driver();
        driver.setDriverName("abc");
        driver.setDriverAge("def");

        Driver driver2 = new Driver();
        driver2.setDriverName("abcd");
        driver2.setDriverAge("defg");

        car.setDriver(driver);
        car.setDriverList(Arrays.asList(driver,driver2));

        JAXBContext context = JAXBContext.newInstance(Car.class);
        Marshaller marshaller = context.createMarshaller();
        //格式化输出
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        //去掉xml头
        marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
        marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
        StringWriter writer = new StringWriter();
        marshaller.marshal(car,writer);
        System.out.println(writer.toString());
    }

转换后结果:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Car>
    <carName>123</carName>
    <carType>456</carType>
    <driver>
        <driverAge>def</driverAge>
        <driverName>abc</driverName>
    </driver>
    <drivers>
        <driverAge>def</driverAge>
        <driverName>abc</driverName>
    </drivers>
    <drivers>
        <driverAge>defg</driverAge>
        <driverName>abcd</driverName>
    </drivers>
</Car>

xml转bean

public static Object xmlStrToOject(Class<?> clazz, String xmlStr) throws Exception {
        Object xmlObject = null;
        Reader reader = null;
        JAXBContext context = JAXBContext.newInstance(clazz);
        
        // XML 转为对象的接口
        Unmarshaller unmarshaller = context.createUnmarshaller();
        
        reader = new StringReader(xmlStr);
        xmlObject = unmarshaller.unmarshal(reader);
        
        if (null != reader) {
            reader.close();
        }
        
        return xmlObject;
    }

入参分别为要转换为的bean的class与xml串,如果xml标签中不包含任何命名空间则可以使用上面的方法,若xml中存在标签(例如标签<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
)则需要参考下面的方法:

public static Object xmlStrToOject(Class<?> clazz, String xmlStr) throws Exception {
        Object xmlObject = null;
        Reader reader = null;
        JAXBContext context = JAXBContext.newInstance(Car.class);

        // XML 转为对象的接口
        Unmarshaller unmarshaller = context.createUnmarshaller();

//        reader = new StringReader(xml1);
        reader = new StringReader(xml2);

        //忽视标签上的命名空间
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        saxParserFactory.setNamespaceAware(false);
        XMLReader xmlReader = saxParserFactory.newSAXParser().getXMLReader();
        SAXSource saxSource = new SAXSource(xmlReader, new InputSource(reader));

        //无命名空间的xml可直接转换,否则报错
//        xmlObject = unmarshaller.unmarshal(reader);
        xmlObject = unmarshaller.unmarshal(saxSource);

        if (null != reader) {
            reader.close();
        }
        
        
        return xmlObject;
    }

若命名空间格式不正确例如xml报文是截取出来的,这个方法同样会报错,此时可以借助dom4j Element的remove(Attribute attr)方法去掉不规范的命名空间(不匹配的命名空间会被识别为属性)。

截取xml可以用dom4j Element的asXml()方法截取。

如果xml中某个多次出现的标签被映射到bean的一个非数组属性中时,会使用最后出现的标签赋值。

注意点

在使用jaxb时尽量不配合lombook使用,lombook在生成get方法时的方法名称会引起冲突导致重复内容的标签出现。


guomz
16 声望1 粉丝

不求做完人,只求做凡人。