Spring Boot中XML转多Item对象报错:根元素后标记格式不正确
问题分析与解决方案
这个报错的核心原因是你的JAXB配置和XML结构完全不匹配:
- 你的XML根元素是
<string>(还带了命名空间xmlns="test.example.com"),但你直接用标注了@XmlRootElement(name = "Item")的Model类去解析,JAXB找不到对应的根节点,自然抛出格式错误。 - 更关键的是,XML里包含多个
<Item>节点,你却试图把它们解析成单个Model对象,这完全不匹配——单个Item时能运行,应该是因为当时的XML根就是<Item>,而非现在的<string>包裹多个Item的结构。
下面是具体的修复步骤:
步骤1:创建对应根节点的包装类
你需要一个类来映射XML的根元素<string>,里面定义一个List来容纳所有的<Item>节点:
package example.models; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import java.util.List; // 命名空间必须和XML里的xmlns完全一致 @XmlRootElement(name = "string", namespace = "test.example.com") public class ItemListWrapper { // 这里的name要匹配XML里的Item节点名,同时指定命名空间 @XmlElement(name = "Item", namespace = "test.example.com") private List<Model> items; // JAXB强制要求无参构造器 public ItemListWrapper() {} // getter和setter方法 public List<Model> getItems() { return items; } public void setItems(List<Model> items) { this.items = items; } }
步骤2:调整Model类的注解
因为XML带有命名空间,你的Model类也需要指定对应的命名空间,否则JAXB无法正确识别节点:
package example.models; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; // 加上匹配的命名空间,这里的@XmlRootElement其实不是解析整个XML的根,但保留也不影响 @XmlRootElement(name = "Item", namespace = "test.example.com") public class Model { // 每个字段的@XmlElement都要加上命名空间,确保节点匹配 @XmlElement(name = "CodeNo", namespace = "test.example.com") private String CodeNo; @XmlElement(name = "ItemKey", namespace = "test.example.com") private String ItemKey; @XmlElement(name = "Start", namespace = "test.example.com") private String Start; @XmlElement(name = "End", namespace = "test.example.com") private String End; @XmlElement(name = "Account", namespace = "test.example.com") private String Account; @XmlElement(name = "Name", namespace = "test.example.com") private String Name; @XmlElement(name = "Note", namespace = "test.example.com") private String Note; // JAXB强制要求无参构造器,必须加上 public Model() {} // 你的getter和setter方法 // ... }
步骤3:修改main代码,用包装类解析
现在需要用ItemListWrapper作为解析的目标类,而不是直接用Model:
// 先修正原代码的顺序问题:先获取response再创建reader String response = restTemplate.getForObject(url, String.class); StringReader reader = new StringReader(response); JAXBContext jaxbContext = JAXBContext.newInstance(ItemListWrapper.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); ItemListWrapper wrapper = (ItemListWrapper) unmarshaller.unmarshal(reader); // 现在就能获取所有Item的列表了 List<Model> records = wrapper.getItems();
额外注意事项
- JAXB要求所有被映射的类必须有无参构造器,如果你的
Model类之前没有,一定要补上,否则会解析失败。 - 命名空间必须完全匹配XML里的
xmlns="test.example.com",包括大小写和拼写,否则JAXB会忽略这些节点。 - 原代码里的变量名
recordes是拼写错误,记得修正为records。
内容的提问来源于stack exchange,提问作者Mr K
相关产品推荐
相关产品推荐

