使用JAXB在XML元素中使用marshall属性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用JAXB在XML元素中使用marshall属性相关的知识,希望对你有一定的参考价值。

我使用Spring JPA并拥有以下实体:

@Entity
@Table(name = Constants.ENTITY_TABLE_PREFIX + "ENTRY")
@XmlAccessorType(XmlAccessType.NONE)
@XmlRootElement(name = "monObj_info")
public class EntryXML implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "ID")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @XmlAttribute
    private long id;

    @Column(name = "ip_address", nullable = true)
    @XmlElement
    private String ip_address;

    @Column(name = "network_element_name", nullable = false)
    @XmlElement
    private String network_element_name;

    public EntryXML() {}

    public EntryXML(long id, String ip_address, String   network_element_name) {
        super();
        this.id = id;
        this.ip_address = ip_address;
        this.network_element_name = network_element_name;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getIp_address() {
        return ip_address;
    }

    public void setIp_address(String ip_address) {
        this.ip_address = ip_address;
    }

    public String getNetwork_element_name() {
        return network_element_name;
    }

    public void setNetwork_element_name(String network_element_name) {
        this.network_element_name = network_element_name;
    }

}

和端点:

@RestController
public class EntryXMLEndpoint {

    @Autowired
    private IEntryXMLService service;

    @RequestMapping(value = "/restxml", produces = { "application/xml" })
    public EntryXML findEntries() {
        EntryXML record = service.findById(1);
        return record;
    }

}

现在请求的响应是:

<monObj_info id="1">
 <atribute name="ip_address" value="xx.xxx.xxx.x"/>
 <atribute name="network_element_name" value="xxxxxx"/>
</monObj_info>

当然,我得到的是:

<monObj_info id="1">
  <ip_address>xx.xxx.xxx.x</ip_address>
  <network_element_name>xxxxxx</network_element_name>
</monObj_info>

我读了类似的帖子,但问题是我无法在我的实体类中创建一个包含所需元素的List,因为它不会映射到相应表中的任何列,有什么建议吗?

答案

你可以直接但有点hackish的方式实现你的目标。

由于您不希望ip_addressnetwork_element_name属性直接编组和解组,您需要删除它们的@XmlElement注释并添加@XmlTransient

相反,你想要一些<atribute name="..." value="..." />元素编组和解组。因此,您需要在EntryXML类中添加以下内容:

  • 包含属性列表的attributes属性。它用@XmlElement注释,因此它将成为XML编组和解组的一部分。它用@Transient注释,因此它不会成为数据库持久性的一部分。
  • 一个简单的帮助类Attribute用于保存名称和值。 namevalue@XmlAttribute注释,以便它们成为XML编组和解组的一部分。
  • Marshal Event Callback(beforeMarshal)用于从ip_addressnetwork_element_name转换到attributes列表。
  • 用于进行相反转换的Unmarshal Event Callback(afterUnmarshal)。

@XmlElement(name = "atribute")
@Transient  // from package javax.persistence
private List<Attribute> attributes;

// there is no need for getAttributes and setAttributes methods

private static class Attribute {

    @SuppressWarnings("unused")  // called by the unmarshaller
    Attribute() {
    }

    Attribute(String name, String value) {
        this.name = name;
        this.value = value;
    }

    @XmlAttribute
    private String name;

    @XmlAttribute
    private String value;
}

@SuppressWarnings("unused") // this method is called only by the marshaller
private boolean beforeMarshal(Marshaller marshaller) {
    attributes = new ArrayList<>();
    attributes.add(new Attribute("ip_address", ip_address));
    attributes.add(new Attribute("network_element_name", network_element_name));
    return true;
}

@SuppressWarnings("unused") // this method is called only by the unmarshaller
private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
    if (attributes != null) {
        for (Attribute attribute : attributes) {
            switch (attribute.name) {
            case "ip_address":
                ip_address = attribute.value;
                break;
            case "network_element_name":
                network_element_name = attribute.value;
                break;
            }
        }
    }
}

然后XML输出将如下所示:

<monObj_info id="1">
    <atribute name="ip_address" value="xx.xxx.xxx.x"/>
    <atribute name="network_element_name" value="xxxxxx"/>
</monObj_info>

以上是关于使用JAXB在XML元素中使用marshall属性的主要内容,如果未能解决你的问题,请参考以下文章

Jaxb2Marshaller在春天解组 - 意想不到的元素

JAXB XJC 代码生成 - Marshaller 生成的 xml 中缺少“schemaLocation”

JAXB使用方式

什么可以改变Java生成的XML文件中元素属性的顺序?

通过JAXB完成Java对象与XML之间的转换

JAXB - java xml解析