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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:21:01