如何通过JAXB生成无父元素的交替重复XML元素?
解决JAXB生成交替无父节点的XML元素问题
我之前对接第三方系统时也碰到过一模一样的需求,要生成这种交替排列、没有中间父元素包裹的XML结构,用JAXB其实可以通过组合注解轻松实现,下面是具体的落地方案:
1. 定义单个元素的实体类
首先给<code>和<percentage>分别创建简单的实体类,用@XmlRootElement指定对应XML元素名,@XmlValue绑定元素的文本内容:
Code类
@XmlRootElement(name = "code") public class Code { private String value; // JAXB强制要求无参构造器 public Code() {} public Code(String value) { this.value = value; } @XmlValue public String getValue() { return value; } public void setValue(String value) { this.value = value; } }
Percentage类
@XmlRootElement(name = "percentage") public class Percentage { private int value; public Percentage() {} public Percentage(int value) { this.value = value; } @XmlValue public int getValue() { return value; } public void setValue(int value) { this.value = value; } }
2. 定义Education父节点类
核心逻辑就在这个类的注解上,我们用@XmlMixed + @XmlAnyElement(lax = true)组合,让列表中的元素直接成为<education>的子节点,不需要额外的包裹元素:
@XmlRootElement(name = "education") public class Education { private List<Object> elements = new ArrayList<>(); @XmlMixed @XmlAnyElement(lax = true) public List<Object> getElements() { return elements; } public void setElements(List<Object> elements) { this.elements = elements; } // 封装工具方法,方便按顺序添加元素 public void addCode(String code) { elements.add(new Code(code)); } public void addPercentage(int percent) { elements.add(new Percentage(percent)); } }
这里的注解作用说明:
@XmlMixed:允许父节点下混合文本和子元素,这里我们用它来取消JAXB默认给列表添加的包裹元素@XmlAnyElement(lax = true):开启宽松模式后,JAXB会识别列表中带有@XmlRootElement的实体类,将它们序列化为对应的XML元素,而不是当作未知元素处理
3. 测试序列化效果
写个简单的测试代码验证生成的XML结构:
public class JaxbTest { public static void main(String[] args) throws JAXBException { Education education = new Education(); // 按需求的交替顺序添加元素 education.addCode("ENG24"); education.addPercentage(25); education.addCode("ENG25"); education.addPercentage(20); education.addCode("SPA50"); education.addPercentage(30); // 初始化JAXB上下文,必须包含所有相关实体类 JAXBContext context = JAXBContext.newInstance(Education.class, Code.class, Percentage.class); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // 输出格式化后的XML marshaller.marshal(education, System.out); } }
运行后生成的XML完全符合第三方要求:
<education> <code>ENG24</code> <percentage>25</percentage> <code>ENG25</code> <percentage>20</percentage> <code>SPA50</code> <percentage>30</percentage> </education>
额外注意点
- 创建JAXBContext时一定要传入所有用到的实体类,或者使用包路径扫描的方式,否则JAXB无法识别这些类对应的XML元素
- 如果需要反序列化这种结构,同样可以用这套方案,JAXB会自动把交替的元素映射回列表中的对应实体对象
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

