【问题标题】:JAXB: How to marshal objects in lists?JAXB:如何编组列表中的对象?
【发布时间】:2011-04-10 15:52:38
【问题描述】:

也许是个愚蠢的问题:我有一个 <Data> 类型的 List,我想将其编组为 XML 文件。这是我的课程Database,其中包含一个ArrayList...

@XmlRootElement
public class Database
{
    List<Data> records = new ArrayList<Data>();

    public List<Data> getRecords()                   { return records; }
    public void       setRecords(List<Data> records) { this.records = records; }
}

...这是数据类:

// @XmlRootElement
public class Data 
{
    String name;
    String address;

    public String getName()            { return name;      }
    public void   setName(String name) { this.name = name; }

    public String getAddress()               { return address;         }
    public void   setAddress(String address) { this.address = address; }
}

使用下面的测试类...

public class Test
{
    public static void main(String args[]) throws Exception
    {
        Data data1 = new Data();
             data1.setName("Peter");
             data1.setAddress("Cologne");

        Data data2 = new Data();
             data2.setName("Mary");
             data2.setAddress("Hamburg");

        Database database = new Database();
                 database.getRecords().add(data1);
                 database.getRecords().add(data2);

        JAXBContext context = JAXBContext.newInstance(Database.class);
        Marshaller marshaller = context.createMarshaller();
                   marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
                   marshaller.marshal(database, new FileWriter("test.xml"));       
    }
}

...我得到了结果:

<database>
    <records>
        <address>Cologne</address>
        <name>Peter</name>
    </records>
    <records>
        <address>Hamburg</address>
        <name>Mary</name>
    </records>
</database>

但这不是我所期望的,即&lt;Data&gt; 对象的所有标签都丢失了。我正在寻找一种以以下结构导出数据的方法,但我不知道如何实现:

<database>
    <records>
        <data>
            <address>Cologne</address>
            <name>Peter</name>
        </data>
        <data>
            <address>Hamburg</address>
            <name>Mary</name>
        </data>
    </records>
</database>

另外一个问题:如果我想使用@XmlElementWrapper@XmlElement注解来处理这个问题,我可以引入一个中间类

public class Records
{
    List<Data> data = new ArrayList<Data>();

    public List<Data> getData()                { return data; }
    public void       setData(List<Data> data) { this.data = data; }
}

被修改后的基类使用

@XmlRootElement
public class Database
{
    Records records = new Records();

    public Records getRecords()                { return records; }
    public void    setRecords(Records records) { this.records = records; }
}

在稍作修改的Test 类中:

...
Database database = new Database();
database.getRecords().getData().add(data1);
database.getRecords().getData().add(data2);
...

结果也是:

<database>
    <records>
        <data>
            <address>Cologne</address>
            <name>Peter</name>
        </data>
        <data>
            <address>Hamburg</address>
            <name>Mary</name>
        </data>
    </records>
</database>

这就是推荐按照上面的XML文件结构创建Java类结构的方式吗?

【问题讨论】:

标签: xml jaxb arraylist unmarshalling


【解决方案1】:

在记录属性上添加:

@XmlElementWrapper(name="records")
@XmlElement(name="data")

有关 JAXB 和集合属性的更多信息,请参阅:

【讨论】:

【解决方案2】:

这是对你第二个问题的回答:

两种方法都将生成相同的 XML。我的建议是使用最适合您的应用程序的模型。对我来说,这通常使用@XmlElementWrapper/@XmlElement。由于“记录”只是用来组织“数据”元素,因此它并不真正值得拥有自己的类。

我领导 MOXy JAXB 的实现,我们提供了一个基于 XPath 的映射扩展,以超越 @XmlElementWrapper 的能力:

【讨论】:

  • 这个领域正在发生的事情真的令人印象深刻。我想我需要一些时间来接触这种新的映射技术。能否给我第一个提示,如何将导出的 XML 数据再次读入类结构?如果我使用@XmlElementWrapper/@XmlElement 进行导出,导入程序会抱怨相应的类(显然:-) 不存在...
  • 导入(解组)应该可以正常工作,您遇到什么异常?
  • 我想我遇到了一个异常,即找不到类“记录”。但可以肯定的是,我明天会通过一个例子来验证它......
  • 是的,你是对的,解组按预期工作! --- JAXBContext 上下文 = JAXBContext.newInstance(Database.class);解组器 unmarshaller = context.createUnmarshaller();数据库数据库 = (Database) unmarshaller.unmarshal(new File("test.xml"));
  • 我会在你的博客上发布这个,但似乎只有团队成员可以在那里回复。感谢您的示例代码,但是在 2017 年,现在有没有更简洁的方法可以在没有样板类和严格类型的情况下执行此操作?
【解决方案3】:

回答你的第二个问题:

Is this the recommended way to create a Java class structure
according to the XML file structure above?

从技术上讲,引入一个额外的Records 类来解决您的 JAXB 问题是不必要且多余的工作,因为 JAXB 不需要它。这 @XmlElementWrapper@XmlElement name 属性旨在解决您的问题。

从您的 cmets 到 Blaise 的回答,我维护了一个 tutorial,其中包含操作示例,解释了在解组时如何处理 List 等泛型类。

【讨论】:

    猜你喜欢
    • 2014-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多