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

JAXB Unmarshalling如何处理不同Field包装元素下的相同User节点

方案1:使用@XmlAnyElement接收动态Field节点(实现简单)

该方案无需修改XML结构,也无需提前知道Field节点的数量和命名规则,通过JAXB自带的任意元素注解接收所有未知外层节点,再统一提取内部的User元素。

步骤1:定义User实体类

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "User")
@XmlAccessorType(XmlAccessType.FIELD)
public class User {
    @XmlElement(name = "Name")
    private String name;
    @XmlElement(name = "Id")
    private Integer id;
    
    // 自行补充getter、setter方法
}

步骤2:定义Response根节点类

import org.w3c.dom.Element;
import javax.xml.bind.*;
import javax.xml.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;

@XmlRootElement(name = "Response")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response {
    // 接收所有未在类中显式定义的子节点
    @XmlAnyElement(lax = true)
    private List<Object> dynamicFieldNodes;

    // 直接返回所有提取到的User对象
    public List<User> getAllUsers() throws JAXBException {
        List<User> users = new ArrayList<>();
        Unmarshaller userUnmarshaller = JAXBContext.newInstance(User.class).createUnmarshaller();
        for (Object node : dynamicFieldNodes) {
            if (node instanceof Element) {
                var userNodes = ((Element) node).getElementsByTagName("User");
                for (int i = 0; i < userNodes.getLength(); i++) {
                    users.add((User) userUnmarshaller.unmarshal(userNodes.item(i)));
                }
            }
        }
        return users;
    }
}

步骤3:执行反序列化

JAXBContext context = JAXBContext.newInstance(Response.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Response response = (Response) unmarshaller.unmarshal(你的XML输入源);
List<User> userList = response.getAllUsers();

方案2:预处理XML事件流剥离Field层(性能更高,适合大体积XML)

该方案通过StAX事件流在反序列化前直接过滤掉所有Field节点的起止标签,相当于把所有User节点直接作为Response的子节点,无需二次反序列化User元素。

步骤1:简化Response实体类定义

import javax.xml.bind.annotation.*;
import java.util.List;

@XmlRootElement(name = "Response")
@XmlAccessorType(XmlAccessType.FIELD)
public class Response {
    @XmlElement(name = "User")
    private List<User> users;

    // 自行补充getter、setter方法
}

步骤2:使用过滤后的事件流执行反序列化

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.stream.events.XMLEvent;
import java.io.FileReader;

// 构造原始XML事件读取器
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
XMLEventReader originalReader = xmlInputFactory.createXMLEventReader(new FileReader("你的XML文件路径"));

// 自定义过滤读取器,跳过所有Field节点的起止标签
XMLEventReader filteredReader = new EventReaderDelegate(originalReader) {
    @Override
    public XMLEvent nextEvent() throws XMLStreamException {
        XMLEvent event = super.nextEvent();
        String nodeName = "";
        if (event.isStartElement()) {
            nodeName = event.asStartElement().getName().getLocalPart();
        } else if (event.isEndElement()) {
            nodeName = event.asEndElement().getName().getLocalPart();
        }
        // 只要是Field开头的节点就跳过
        if (nodeName.startsWith("Field")) {
            return nextEvent();
        }
        return event;
    }
};

// 直接用过滤后的事件流反序列化
JAXBContext context = JAXBContext.newInstance(Response.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Response response = (Response) unmarshaller.unmarshal(filteredReader);
List<User> userList = response.getUsers();

注意事项

如果使用Jakarta EE 9+版本的JAXB(Jakarta XML Binding),只需要把所有javax.xml.bind的包引用替换为jakarta.xml.bind即可,逻辑完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 01:00:01