如何从Java中的xml实体字符串值创建不同的pojo

时间:2018-07-23 06:05:54

标签: java xml jaxb unmarshalling

我的用例非常有限,并且有很多限制。

首先,我仅具有以下定义的示例结构的XML。我没有架构定义。我对方法的要求和实施受到很大限制。

<?xml version="1.0" encoding="UTF-8" ?>
<items>
    <item>
        <content_id>56789012</content_id>
        <unique_record_id>B-123456</unique_record_id>
        <title>ABC</title>
        <type>board</type>
        <dfield>098765</dfield>
        <abn>11 222 333 444</abn>
        <cfield>Yes</cfield>
        <bfield>Goodness me</bfield>
        <afield>ABCD</afield>
    </item>
    <item>
        <content_id>1234</content_id>
        <unique_record_id>D-789</unique_record_id>
        <title>Member</title>
        <type>role</type>
        <contact>90000</contact>
        <role_belongs_to>56789012</role_belongs_to>
        <updated>23/07/2018 - 3:30pm</updated>
        <importance>90</importance>
    </item>
    <item>
        <content_id>90000</content_id>
        <unique_record_id>D-654321</unique_record_id>
        <title>Someone Else</title>
        <type>person</type>
        <salutation>Ms.</salutation>
        <first_name>Someone</first_name>
        <last_name>Else</last_name>
    </item>
    .
    .
    .
    .
    .
</items>

上面的模型是我将得到的xml的简单表示(不直接与人打交道,公司数据模型:))。请注意,有许多项目类型。 type 字段实际上是我要创建的POJO。项目之间也有关系。请注意,这种关系通常是一对多的。

  • 一个人可以扮演许多角色
  • 一个人可以为许多委员会工作
  • 一个人可以为许多组织工作

也存在1对1的关系,即:

  • 一个角色只能属于1个组织
  • 还有一些.....

我的目标:

  • 我想知道提取所有关系的最简洁方法
  • 使用正确的所有项目创建关联的pojo列表 pojo类型
  • 将xml反规范化为下面定义的新xml结构示例。

我知道我可以编写大量代码来剥离xml,并在xml解组和迭代后使用反射创建POJO。

我正在寻找最干净的方法,可以使用JAXB,SAX或其他任何可以简化当前任务的库。

非正规化的输出示例:

<?xml version="1.0" encoding="UTF-8" ?>
<items>
    <Person>
        <content_id>90000</content_id>
        <unique_record_id>D-654321</unique_record_id>
        <title>Someone Else</title>
        <salutation>Ms.</salutation>
        <first_name>Someone</first_name>
        <last_name>Else</last_name>
        <role>
            <content_id>1234</content_id>
            <unique_record_id>D-789</unique_record_id>
            <title>Member</title>
            <role_belongs_to>
                <board>
                    <content_id>56789012</content_id>
                    <unique_record_id>B-123456</unique_record_id>
                    <title>ABC</title>
                    <dfield>098765</dfield>
                    <abn>11 222 333 444</abn>
                    <cfield>Yes</cfield>
                    <bfield>Goodness me</bfield>
                    <afield>ABCD</afield>
                </board>
            </role_belongs_to>
            <updated>23/07/2018 - 3:30pm</updated>
            <importance>90</importance>
        </role>

    </Person>
    .
    .
</items>

1 个答案:

答案 0 :(得分:0)

有趣的需求组合。我知道它可以与SimpleXml一起使用。如果您觉得足够干净,完全取决于您。首先介绍一些POJO:

public class Items {
    @XmlName("item")
    @XmlAbstractClass(tag="type", types={
        @TypeMap(name="board", type=Board.class),
        @TypeMap(name="role", type=Role.class),
        @TypeMap(name="person", type=Person.class)
    })
    public List<Item> items;
}

abstract class Item {
    @XmlName("content_id")
    public Integer contentId;
}
public class Board extends Item {
    String abn;
}
public class Role extends Item {
    @XmlNoExport
    @XmlName("role_belongs_to")
    Integer boardId;
    @XmlNoImport
    @XmlWrapperTag("role_belongs_to")
    Board board;
}
public class Person extends Item {
    @XmlNoExport
    @XmlName("has_role")
    public Integer hasRole;
    @XmlNoImport
    public Role role;
}

@XmlName("items")
public class PersonList {
    @XmlName("Person")
    public List<Person> persons;
}

接下来,我们将xml序列化为项目列表:

final SimpleXml simple = new SimpleXml();
final Items items = simple.fromXml(xml, Items.class);

然后我们需要在内存中移动一些

final Map<Integer, Board> boards = new HashMap<>();
items.items.forEach(item -> { if (item instanceof Board) boards.put(item.contentId, (Board)item); });
final Map<Integer, Role> roles = new HashMap<>();
items.items.forEach(item -> { if (item instanceof Role) roles.put(item.contentId, (Role)item); });
final List<Person> persons = new ArrayList<>();
items.items.forEach(item -> { if (item instanceof Person) persons.add((Person)item); });

roles.values().forEach(role -> role.board = boards.get(role.boardId));
persons.forEach(person -> person.role = roles.get(person.hasRole));

最后序列化结果并打印:

final PersonList pl = new PersonList();
pl.persons = persons;
System.out.println(simple.toXml(pl));

应准确打印出您想要的内容。我不太清楚您是如何将角色分配给“人”的,所以我组成了一个has_role字段并使用了它。当然,您可以做任何事情。

SimpleXml位于Maven中央:

<dependency>
    <groupId>com.github.codemonstur</groupId>
    <artifactId>simplexml</artifactId>
    <version>1.5.5</version>
</dependency>