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

如何将带不同key的XML<supplement>映射到Java POJO字段或HashMap?

XML到Java POJO的映射方案

XML 文件内容

<foobar name="quux">
    <supplement key="head">this is a text row</supplement>
    <supplement key="body">this is some other text row</supplement>
</foobar>

目标Java POJO结构

希望将<supplement>标签按key属性分别映射到POJO的head和body字段:

@XmlRootElement(name = "foobar")
@XmlAccessorType(XmlAccessType.FIELD)
public class Foobar {
    @XmlAttribute
    private String name;

    private String head;  // 对应XML中key="head"的supplement标签内容

    private String body;  // 对应XML中key="body"的supplement标签内容
}

问题说明

能否实现上述直接映射?若可以该如何操作?

另外尝试将所有<supplement>标签存入HashMap<String, String>(以key属性值为键)但未成功,目前临时方案是映射为列表:

@XmlElement(name = "supplement")
private List<NewSupplement> supplements = new ArrayList<>();

但该方案依赖XML中标签的顺序,容易引发问题,因此更倾向于直接映射到单个字段或HashMap方案,求可行建议。


解决方案

方案一:直接映射到单个字段

可以通过EclipseLink MOXy(JAXB的扩展库,标准JAXB不支持@XmlPath)提供的@XmlPath注解实现按属性筛选的映射,步骤如下:

  1. 引入MOXy依赖(Maven为例):
<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>org.eclipse.persistence.moxy</artifactId>
    <version>4.0.2</version>
</dependency>
  1. 修改POJO,添加@XmlPath注解:
@XmlRootElement(name = "foobar")
@XmlAccessorType(XmlAccessType.FIELD)
public class Foobar {
    @XmlAttribute
    private String name;

    // 匹配key="head"的supplement标签文本内容
    @XmlPath("supplement[@key='head']/text()")
    private String head;

    // 匹配key="body"的supplement标签文本内容
    @XmlPath("supplement[@key='body']/text()")
    private String body;

    // 生成getter、setter方法
    // ...
}
  1. 配置JAXB使用MOXy:
    在POJO所在包下创建jaxb.properties文件,内容为:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

此方案可直接将指定key的<supplement>内容映射到对应字段,完全不受标签顺序影响。

方案二:映射到HashMap

基于标准JAXB实现,无需额外依赖,通过自定义XmlAdapter将<supplement>集合转换为HashMap:

  1. 定义单个<supplement>的辅助类:
public class Supplement {
    @XmlAttribute
    private String key;

    @XmlValue
    private String value;

    // 生成getter、setter方法
    // ...
}
  1. 编写自定义XmlAdapter:
public class SupplementMapAdapter extends XmlAdapter<List<Supplement>, Map<String, String>> {

    @Override
    public Map<String, String> unmarshal(List<Supplement> supplements) throws Exception {
        Map<String, String> map = new HashMap<>();
        for (Supplement s : supplements) {
            map.put(s.getKey(), s.getValue());
        }
        return map;
    }

    @Override
    public List<Supplement> marshal(Map<String, String> map) throws Exception {
        List<Supplement> supplements = new ArrayList<>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            Supplement s = new Supplement();
            s.setKey(entry.getKey());
            s.setValue(entry.getValue());
            supplements.add(s);
        }
        return supplements;
    }
}
  1. 修改Foobar类使用适配器:
@XmlRootElement(name = "foobar")
@XmlAccessorType(XmlAccessType.FIELD)
public class Foobar {
    @XmlAttribute
    private String name;

    @XmlElement(name = "supplement")
    @XmlJavaTypeAdapter(SupplementMapAdapter.class)
    private Map<String, String> supplementMap;

    // 生成getter、setter方法
    // 可添加便捷方法快速获取指定key的值
    public String getHead() {
        return supplementMap != null ? supplementMap.get("head") : null;
    }

    public String getBody() {
        return supplementMap != null ? supplementMap.get("body") : null;
    }
}

此方案将所有<supplement>按key存入HashMap,不受标签顺序影响,还可通过自定义方法快速获取目标字段值。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 21:33:16