You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用JAXB解组XML时Body.content未正确映射为目标对象问题

问题:JAXB解组XML时未将子节点映射为对应Java对象

现有Java类定义

Data与Body类

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Data", propOrder = {
    "body"
})
@XmlRootElement(name = "Data")
class Data {
    @XmlElement(name = "Body", required = true)
    protected Body body;
    // getter and setter
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Body", propOrder = {
    "content"
})
class Body {
    @XmlMixed
    @XmlAnyElement
    protected List<Object> content; 
    // getter
}

Node1与Node2类

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Node1", propOrder = {
    "data",
})
class Node1 {
   @XmlElement(name = "Data")
   private String data;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Node2", propOrder = {
    "int",
})
class Node2 {
   @XmlElement(name = "Int")
   private Integer int;
}

XML示例

<Data>
    <Body>
        <Node1>
           <Data>abc</Data>
        </Node1>
        <Node2>
           <Int>abc</Int>
        </Node2>
    </Body>
</Data>

解组代码

private Object xmlToObject(String xmlString) throws Exception {
        var context = JAXBContext.newInstance(Data.class, Node1.class, Node2.class);
        var unmarshaller = context.createUnmarshaller();
        return unmarshaller.unmarshal(new StringReader(xmlString));
    }

问题现象

预期:解组后得到包含Body对象的Data实例,Body的content集合中包含Node1和Node2类型对象。
实际:Body.content中的元素为ElementNSimpl类型对象及含换行的字符串,未映射为目标Java类实例。

解决方案

原因分析

@XmlAnyElement默认会将未匹配的XML元素解析为DOM节点(ElementNSimpl),@XmlMixed会把XML中的文本节点(包括换行、空格)也加入集合,两者叠加导致当前结果。要让JAXB自动映射Node1/Node2,需调整注解配置。

修正方案

方案1:仅保留子节点对象(移除文本内容)

如果不需要保留Body中的换行、空格等文本内容,直接修改Body类的注解:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "Body", propOrder = {
    "content"
})
class Body {
    @XmlAnyElement(lax = true) // 关键:添加lax=true属性
    protected List<Object> content; 
    // getter
}

lax=true会让JAXB尝试将XML元素映射到JAXBContext已注册的类(Node1、Node2),匹配成功则返回对应Java对象,否则返回DOM节点。同时移除@XmlMixed,避免文本节点混入集合。

方案2:保留混合内容(文本+子节点)

如果必须保留文本内容,需保留@XmlMixed并配合@XmlAnyElement(lax=true),但集合中仍会包含文本对象,后续需自行过滤。另外注意Node2类的字段名int是Java关键字,建议改为intValue等合法名称,避免编译报错。

验证

修改后重新运行解组代码,Body.content集合中将出现Node1和Node2的实例,而非ElementNSimpl对象。

内容的提问来源于stack exchange,提问作者bobrik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 17:05:34