如何使用JAXB实例化一个空元素

13

我使用JAXB创建XML消息。我需要创建的XML是(为简单起见):

<request>
  <header/>
</request>

我的代码看起来像这样:

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "request")
public class Request {

    private String header;

    @XmlElement(required=true)
    public String getHeader() {
      return header;
    }

    public void setHeader(String header) {
      this.header=header;
    }
}
问题:元素header没有显示出来(header是null)。当header设置为空字符串时,将显示以下内容:

问题:元素header没有显示出来(header是null)。当header设置为空字符串时,将显示以下内容:

<request>
  <header></header>
</request>

当我使用类型为Object而不是String时,结果会更糟:

<request>
  <header xsi:type="xs:string" 
   xmlns:xs="http://www.w3.org/2001/XMLSchema" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"></header>
</request>

顺便提一下:我正在使用这个代码来创建XML字符串。

是否可能获得一个空标签?


那么将 header 设置为空有什么问题吗? - Tom Hawtin - tackline
我想要的是<header/>而不是<header></header>。 - doekman
@doekman 嗯,我知道现在有点晚了,但以防万一。要做到你想要的事情,你可以使用EclipseLink MOXy实现JAXB,它有一个非常好的扩展@XmlNullPolicy。在这里看一个例子(在“Option #2”部分)。 - informatik01
4个回答

12
在XML中,<header/><header></header>是等价的。如果你真的想要前一种形式,那么可以使用一个格式化工具。javax.xml.transform.TransformerFactory.newTransformer()可能会为你完成这个任务。

7
嗨@Tom,你能详细解释一下如何做吗? - Vladimir

5

一个String对象的空标签本质上就是空字符串。

如果你调用以下代码,你将得到你想要的结果:

request.setHeader("")

我应该指出,在XML中,以下两个标题声明是相同的。 这两个都没有子文本节点。 它们本质上是相同的,所有XML解析器将对其进行相同的处理:
<header></header>

<header/>

1
你好 Chris,如果要为包装对象(如 Boolean、BigInteger、BigDecimal等)创建空标签怎么办?显然,将 null 设置为这些对象将导致标记未生成。 - Min Naing Oo

2

正如 @Tom Hawtin - tackline 所说

<header/><header></header> 是相同的。解析器会返回空字符串。

你需要在头部注释中加上nillable

@XmlElement(nillable=true, required=true)
public String getHeader() {
  return header;
}

我希望这段代码能够针对 null 值生成以下 XML。
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;

@XmlRootElement
public class Request {

    public static void main(String[] args) throws JAXBException {
        final Request request = new Request();
        final JAXBContext context = JAXBContext.newInstance(Request.class);
        final Marshaller marshaller = context.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT,
                               Boolean.TRUE);
        marshaller.marshal(request, System.out);
        System.out.flush();
    }

    @XmlElement(nillable=true, required=true)
    private String header;
}

打印

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request>
    <header xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</request>

0

我想要的是在 XML 序列化过程中,实现 <header/> 而不是 <header></header>

由于 null 值 - 而不是空字符串 - 会产生正确的结果,因此我修改了我的 setter 方法,将值明确设置为 null:

public void setHeader(String header) {
    this.header = "".equals(header) ? null : header;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接