【问题标题】:How to create a different pojo from xml entity string value in java如何在java中从xml实体字符串值创建不同的pojo
【发布时间】:2018-07-23 06:05:53
【问题描述】:

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

首先,我只有一个如下定义的示例结构的 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。物品之间也有关系。请注意,关系通常是一对多。

即

  • 一个人可以有很多角色
  • 一个人可以为多个董事会工作
  • 一个人可以为许多组织工作

也有一对一的关系,即:

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

我的目标:

  • 我想知道提取所有关系的最干净的方法
  • 使用正确的所有项目创建关联的 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>

【问题讨论】:

    标签: java xml jaxb unmarshalling


    【解决方案1】:

    有趣的需求组合。我让它与 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));
    

    应该准确地打印出您想要的内容。我不太明白你是如何为 Persons 分配角色的,所以我创建了一个 has_role 字段并使用了它。当然你可以做任何事情。

    SimpleXml 位于 Maven 中心:

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

    【讨论】:

    • 这是一个很好的答案,我最终做了类似的事情,除了我最终只是使用了一个 stax 解析器。我想我会将代码更改为与上述类似的更改。它更强大。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 2014-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多