JAXB解析含CDATA标签的XML时csNum值为null的解决方法
解决JAXB读取含CDATA的XML时csNum字段为null的问题
问题原因
当前JAXB默认会把XMLString节点下的CDATA内容视为纯文本,而非可解析的XML结构,因此无法将其映射到LocationsOuter类的locations属性,最终导致csNum字段值为null。
解决方案
方案一:自定义XmlAdapter自动解析CDATA内容
通过实现XmlAdapter,让JAXB自动将CDATA中的XML字符串转换成目标Java对象。
- 创建CDATA解析适配器
import javax.xml.bind.annotation.adapters.XmlAdapter; import javax.xml.bind.JAXBContext; import javax.xml.bind.Unmarshaller; import java.io.StringReader; public class CDATAXmlAdapter extends XmlAdapter<String, LocationsOuter> { @Override public LocationsOuter unmarshal(String cdataContent) throws Exception { // 解析CDATA内的XML字符串为LocationsOuter对象 JAXBContext context = JAXBContext.newInstance(LocationsOuter.class); Unmarshaller unmarshaller = context.createUnmarshaller(); return (LocationsOuter) unmarshaller.unmarshal(new StringReader(cdataContent)); } @Override public String marshal(LocationsOuter value) throws Exception { // 若需生成XML时输出CDATA,可在此补充逻辑,当前返回null即可 return null; } }
- 修改
GetLocations类的字段注解
在xmlString字段上添加@XmlJavaTypeAdapter,指定使用上述适配器:
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "getLocations") public class GetLocations implements Serializable { private final static long serialVersionUID = 1L; @XmlElement(name = "XMLString", required = true, nillable = true) @XmlJavaTypeAdapter(CDATAXmlAdapter.class) // 绑定适配器 protected LocationsOuter xmlString; public LocationsOuter getXMLString() { return xmlString; } // 其他原有代码... }
方案二:手动解析CDATA内容
将XMLString的字段类型改为String,在获取内容后手动解析成目标对象。
- 修改
GetLocations类的字段类型
@XmlAccessorType(XmlAccessType.FIELD) @XmlRootElement(name = "getLocations") public class GetLocations implements Serializable { private final static long serialVersionUID = 1L; @XmlElement(name = "XMLString", required = true, nillable = true) protected String xmlString; // 改为String类型接收CDATA内容 public String getXMLString() { return xmlString; } // 新增方法手动解析为LocationsOuter public LocationsOuter parseXMLString() throws Exception { if (xmlString == null) return null; JAXBContext context = JAXBContext.newInstance(LocationsOuter.class); Unmarshaller unmarshaller = context.createUnmarshaller(); return (LocationsOuter) unmarshaller.unmarshal(new StringReader(xmlString)); } // 其他原有代码... }
- 使用时手动解析
// 假设已完成JAXB反序列化得到GetLocations对象 GetLocations request = ...; LocationsOuter locationsOuter = request.parseXMLString(); if (locationsOuter != null && locationsOuter.getLocations() != null) { String csNum = locationsOuter.getLocations().getCsNum(); // 处理csNum }
注意事项
- 确保CDATA内的XML结构与
LocationsOuter、Locations类的JAXB注解完全匹配,否则会解析失败。 - 解析过程中需捕获
JAXBException等异常,避免程序崩溃。 - 若需要生成XML时输出CDATA,可在适配器的
marshal方法中补充逻辑(比如用<![CDATA[...]]>包裹序列化后的XML字符串)。
内容的提问来源于stack exchange,提问作者jianmin tu
相关产品推荐
相关产品推荐

