【问题标题】:JAXB: Generate Object from attributes and another from elementsJAXB:从属性生成对象,从元素生成另一个对象
【发布时间】:2018-01-15 21:18:22
【问题描述】:

我需要知道是否可以解组 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;
}

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

【问题讨论】:

    标签: java xml jaxb unmarshalling


    【解决方案1】:

    试试这个:尽管您缺少 nWheels 和 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;
    }
    

    【讨论】:

      【解决方案2】:

      是的,如果您使用委托 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]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-23
        • 2014-03-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-16
        • 1970-01-01
        相关资源
        最近更新 更多