JAXB:从属性生成对象,从元素

时间:2018-01-15 21:18:23

标签: java xml jaxb unmarshalling

我需要知道是否可以解组xml并生成子对象。

例如:

<car>
    <nWheels>4</nWheels>
    <nDoors>5</nDoors>
    <motor id="1" type="cc" model="kly">
        <na>A</na>
        <nb>B</nb>
        <nc>C</nc>
        <nd>D</nd>
    </motor>
    <motor id="2" type="cc2" model="kly2">
        <na>E</na>
        <nb>F</nb>
        <nc>G</nc>
        <nd>H</nd>
    </motor>
</car>

使用这个xml我想生成3个对象。 一个包含电机列表和每个电机对象的类,其中包含一个带有元素的类。

另一堂课:

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Motor {

    @XmlAttribute(name = "id")
    private Long id;

    @XmlAttribute(name = "type")
    private int type;

    @XmlAttribute(name = "model")
    private String model;

    //if possible generate another class from motor
    // ??????
    private MotorProperties properties;

}

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class MotorProperties {

        @XmlElement(name = "na")
        private String na;

        @XmlElement(name = "nb")
        private String nb;

        @XmlElement(name = "nc")
        private String nc;

        @XmlElement(name = "nd")
        private String nd;
}

可以这样做吗?我找不到一个好的例子。

2 个答案:

答案 0 :(得分:0)

试试这个:虽然你缺少nWheels&amp;的元素。 NDOORS。但我想你可以从这里弄明白。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Motor {

    @XmlAttribute(name = "id")
    private Long id;

    @XmlAttribute(name = "type")
    private int type;

    @XmlAttribute(name = "model")
    private String model;

    @XMLElement(name="motor")
    private MotorProperties properties;

}

@XMLRootElement(name = "motor")
@XmlAccessorType(XmlAccessType.FIELD)
public class MotorProperties {

    @XmlElement(name = "na")
    private String na;

    @XmlElement(name = "nb")
    private String nb;

    @XmlElement(name = "nc")
    private String nc;

    @XmlElement(name = "nd")
    private String nd;
}

答案 1 :(得分:0)

是的,如果您使用委托的getter和setter,则可以将nanbncnd值存储在嵌套对象中。

我总是发现更容易确保类和@Xml...注释是好的,首先从Java编组XML,然后通过解组并打印结果来验证解析。

在下面的代码中,我对线条进行了一些压缩,以便您可以一次看到更多。您可能不会在真实的代码中这样做。

我还依赖于默认命名,所以我没有给出注释的任何值。

这是完全正常的代码,可以生成您展示的XML,并将其解析回来。

class MotorProperties {
    private String na;
    private String nb;
    private String nc;
    private String nd;
    public MotorProperties() {
    }
    public MotorProperties(String na, String nb, String nc, String nd) {
        this.na = na;
        this.nb = nb;
        this.nc = nc;
        this.nd = nd;
    }
    public void setNa(String na) { this.na = na; }
    public void setNb(String nb) { this.nb = nb; }
    public void setNc(String nc) { this.nc = nc; }
    public void setNd(String nd) { this.nd = nd; }
    public String getNa() { return this.na; }
    public String getNb() { return this.nb; }
    public String getNc() { return this.nc; }
    public String getNd() { return this.nd; }
    @Override
    public String toString() {
        return "MotorProperties[na=" + this.na +
                             ", nb=" + this.nb +
                             ", nc=" + this.nc +
                             ", nd=" + this.nd + "]";
    }
}

请注意,上面的MotorProperties类没有任何@Xml...注释,因为JAXB不会直接使用它。

@XmlAccessorType(XmlAccessType.NONE)
class Motor {
    @XmlAttribute private long   id;
    @XmlAttribute private String type;
    @XmlAttribute private String model;
    private MotorProperties props;
    public Motor() {
        this.props = new MotorProperties();
    }
    public Motor(long id, String type, String model, String na, String nb, String nc, String nd) {
        this.id = id;
        this.type = type;
        this.model = model;
        this.props = new MotorProperties(na, nb, nc, nd);
    }
    public void setNa(String na) { this.props.setNa(na); }
    public void setNb(String nb) { this.props.setNb(nb); }
    public void setNc(String nc) { this.props.setNc(nc); }
    public void setNd(String nd) { this.props.setNd(nd); }
    @XmlElement public String getNa() { return this.props.getNa(); }
    @XmlElement public String getNb() { return this.props.getNb(); }
    @XmlElement public String getNc() { return this.props.getNc(); }
    @XmlElement public String getNd() { return this.props.getNd(); }
    @Override
    public String toString() {
        return "Motor[id="    + this.id +
                   ", type="  + this.type +
                   ", model=" + this.model +
                   ", props=" + this.props + "]";
    }
}

上面有XmlAccessType.NONE,只会处理@Xml...个带注释的字段/方法。这样可以更好地控制。 MotorProperties类的所有值都使用委托作为直接属性提供。

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
class Car {
    @XmlElement private int nWheels;
    @XmlElement private int nDoors;
    @XmlElement private List<Motor> motor;
    public Car() {
    }
    public Car(int nWheels, int nDoors, Motor... motor) {
        this.nWheels = nWheels;
        this.nDoors = nDoors;
        this.motor = Arrays.asList(motor);
    }
    public List<Motor> getMotor() {
        return this.motor;
    }
    @Override
    public String toString() {
        return "Car[nWheels=" + this.nWheels +
                 ", nDoors="  + this.nDoors + "]";
    }
}

<强>测试

Car car = new Car(4, 5,
                  new Motor(1, "cc", "kly", "A", "B", "C", "D"),
                  new Motor(2, "cc2", "kly2", "E", "F", "G", "H"));

JAXBContext jaxbContext = JAXBContext.newInstance(Car.class);

Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
StringWriter xmlWriter = new StringWriter();
marshaller.marshal(car, xmlWriter);
String xml = xmlWriter.toString();

System.out.println(xml);

Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Car car2 = (Car) unmarshaller.unmarshal(new StringReader(xml));

System.out.println(car2);
car2.getMotor().forEach(m -> System.out.println("  " + m));

<强>输出

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<car>
    <nWheels>4</nWheels>
    <nDoors>5</nDoors>
    <motor id="1" type="cc" model="kly">
        <na>A</na>
        <nb>B</nb>
        <nc>C</nc>
        <nd>D</nd>
    </motor>
    <motor id="2" type="cc2" model="kly2">
        <na>E</na>
        <nb>F</nb>
        <nc>G</nc>
        <nd>H</nd>
    </motor>
</car>

Car[nWheels=4, nDoors=5]
  Motor[id=1, type=cc, model=kly, props=MotorProperties[na=A, nb=B, nc=C, nd=D]]
  Motor[id=2, type=cc2, model=kly2, props=MotorProperties[na=E, nb=F, nc=G, nd=H]]