当前位置: 首页 > 知识库问答 >
问题:

JAXB XML动态解组

龙智
2023-03-14

所以我有几个XML,我正在尝试解封。

一个XML可以如下所示:

<TABLE>
    <RECORDS>
        <RECORD>
            <DOC_ID>some value</DOC_ID>
            <ENTITY_ID>some value</ENTITY_ID>
            ...more entries
        </RECORD>
        <RECORD>
            <DOC_ID>some value</DOC_ID>
            <ENTITY_ID>some value</ENTITY_ID>
            ...more entries
        </RECORD>
    </RECORDS>
</TABLE>
<TABLE>
    <RECORDS>
        <RECORD>
            <SUB_ID>some value</SUB_ID>
            <CASE_DOC_ID>some value</CASE_DOC_ID>
            ...more entries
        </RECORD>
        <RECORD>
            <SUB_ID>some value</SUB_ID>
            <CASE_DOC_ID>some value</CASE_DOC_ID>
            ...more entries
        </RECORD>
    </RECORDS>
</TABLE>

在我的Table类中

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "TABLE")
public class Table {

    @XmlJavaTypeAdapter(MapAdapter.class)
    private Map<String, String> RECORDS;

    public Map<String, String> getMap() {
        return RECORDS;
    }

    public void setMap(Map<String, String> record) {
        this.RECORDS = record;
    }

}

我从这个链接获取了MapAdapter:JAXB封送和反封送映射到/从 value

我的问题是:我希望能够在传入XML时将记录中的每个标记名(Doc_id/sub_id或XML中的任何内容)及其每个值作为字符串获取,但我不确定如何实现。

如果能给我指明正确的方向,我将不胜感激。

编辑:

2个新问题!我意识到我可能需要一份所有记录的地图清单。

  • 我使用上面的Table类获得了最后一条记录的键和值。如何将其转换为映射列表,以便获得每条记录而不是最后一条记录?
  • 另一个问题是Table类只有在XML中没有RECORDS标记时才起作用。如何修复?

共有1个答案

巢安澜
2023-03-14

您需要能够使用提供的链接中的MapAdapter来注释Map,因此需要创建一个子类。

@XmlJavaTypeAdapter(MapAdapter.class)
public class Record extends HashMap<String, String> {
}

那么您的表类就足够简单了,不过您需要使用@XmlElementWrapper进行注释以获得额外的XML级别。

@XmlRootElement(name = "TABLE")
public class Table {
    private List<Record> records = new ArrayList<>();

    @XmlElementWrapper(name = "RECORDS")
    @XmlElement(name = "RECORD")
    public List<Record> getRecords() {
        return this.records;
    }
    public void setRecords(List<Record> records) {
        this.records = records;
    }
}

当使用JAXB并且解析没有加载所有信息时,我发现首先编写生成XML的代码会有帮助,因为您可以在生成的XML中看到JAXB映射与您预期/预期的不同。

如果您向上面的类添加几个帮助器方法,创建示例数据就会更容易,所以让我们先这样做:

@XmlJavaTypeAdapter(MapAdapter.class)
public class Record extends HashMap<String, String> {
    private static final long serialVersionUID = 1L;

    public Record addElement(String name, String value) {
        put(name, value);
        return this;
    }

    @Override
    public String toString() {
        return "Record" + super.toString();
    }
}
@XmlRootElement(name = "TABLE")
public class Table {
    private List<Record> records;

    public Table() {
        this.records = new ArrayList<>();
    }
    public Table(Record... records) {
        this.records = Arrays.asList(records);
    }

    @XmlElementWrapper(name = "RECORDS")
    @XmlElement(name = "RECORD")
    public List<Record> getRecords() {
        return this.records;
    }
    public void setRecords(List<Record> records) {
        this.records = records;
    }

    @Override
    public String toString() {
        return "Table" + this.records.toString();
    }
}

然后我们就可以很容易地编写测试代码,以确保它都正常工作。

生成要生成为XML的数据

Table table1 = new Table(
        new Record().addElement("DOC_ID", "some value")
                    .addElement("ENTITY_ID", "some value"),
        new Record().addElement("SUB_ID", "some value")
                    .addElement("CASE_DOC_ID", "some value")
);
System.out.println(table1);
Table[Record{DOC_ID=some value, ENTITY_ID=some value}, Record{SUB_ID=some value, CASE_DOC_ID=some value}]
String xml;
try (StringWriter out = new StringWriter()) {
    JAXBContext jaxbContext = JAXBContext.newInstance(Table.class);
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(table1, out);
    xml = out.toString();
}
System.out.println(xml);
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<TABLE>
    <RECORDS>
        <RECORD>
            <DOC_ID>some value</DOC_ID>
            <ENTITY_ID>some value</ENTITY_ID>
        </RECORD>
        <RECORD>
            <SUB_ID>some value</SUB_ID>
            <CASE_DOC_ID>some value</CASE_DOC_ID>
        </RECORD>
    </RECORDS>
</TABLE>
Table table2;
{
    JAXBContext jaxbContext = JAXBContext.newInstance(Table.class);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
    table2 = (Table) unmarshaller.unmarshal(new StringReader(xml));
}
System.out.println(table2);
Table[{DOC_ID=some value, ENTITY_ID=some value}, {SUB_ID=some value, CASE_DOC_ID=some value}]

正如您所看到的,解析后的数据具有所有的值,并且它与原始数据相匹配。

 类似资料:
  • 本文向大家介绍详解Mybatis动态sql,包括了详解Mybatis动态sql的使用技巧和注意事项,需要的朋友参考一下 1.什么是mybatis动态sql 看到动态,我们就应该想到,这是一个可以变化的sql语句 MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑 2.mybatis动态sql使用前准备 a.数据库表 b.创建类 3.使用mybatis动

  • 问题内容: 我正在尝试在Swift 4中解码以下JSON: 问题是,JSON中的最后2个元素(和)可能存在或可能不存在,或者这些元素可能被命名为完全不同但仍未知的名称,即 所以,我想要实现的解码是已知的东西,即,,和任何其他元素(,等),将它们放入一个字典。 我的结构如下所示: 如果有人可以提供一些指导,那么我能够解码已知结构的一部分,其中JSON也可以包含动态信息。 谢谢 问题答案: 受@mat

  • 问题内容: 我有一个yaml文件,当前写为: 但是,此yaml文件经常更改,因此每次可以使用不同的值添加新条目: 我从使用gopkg.in/yaml.v2包开始就知道,如果所有值都相同,我可以解析yaml文件,例如: 在上面的示例中,它仅适用于密钥/狗密钥,而不适用于其他密钥。 当新值经常添加到yaml文件中时,如何在Go中执行此操作? 谢谢 问题答案: 如果您现在不精确的结构,则应该使您的结构看

  • 问题内容: 我如何解析这个json对象: 我可以有N个端口,每个端口的值始终是key:value对。 到目前为止,我已经尝试过了: 有了这个我得到键(0,1),但值是空的。 我也尝试过这个: 但也不行。 这就是我解码json对象的方式: 问题答案: 使用此类型: 游乐场的例子 笔记: 字段名称非常匹配。我使用字段名称“ Ports”来匹配JSON文本中使用的名称。 Go类型在JSON中应具有相同级

  • 斐波那契数列 1. 爬楼梯 2. 强盗抢劫 3. 强盗在环形街区抢劫 4. 信件错排 5. 母牛生产 矩阵路径 1. 矩阵的最小路径和 2. 矩阵的总路径数 数组区间 1. 数组区间和 2. 数组中等差递增子区间的个数 分割整数 1. 分割整数的最大乘积 2. 按平方数来分割整数 3. 分割整数构成字母字符串 最长递增子序列 1. 最长递增子序列 2. 一组整数对能够构成的最长链 3. 最长摆动子

  • 我在寻找一个简单的解决方案。 我有一个xml文件: 我想做一个动态解析器。 我知道我可以用org.w3c.dom.*读取xml,org.w3c.dom.Node.getTextContent()我可以得到标签的值。 有什么建议吗? [编辑]通过反思: 变量“clazz”是java.lang.类,对吗?我怎么能转换文本内容值(在字符串)到任何包装类型? valueOf可能是我可以使用反射调用的通用方