Java 使用 JAXB 解组嵌套的 xml 项目列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25704853/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:57:37  来源:igfitidea点击:

Unmarshalling nested list of xml items using JAXB

javaxmljaxb2

提问by Egor Lyashenko

I've got such xml construction which I need to convert into java objects using JAXB:

我有这样的 xml 结构,我需要使用 JAXB 将其转换为 java 对象:

<elements>
    <elemet>
        <type></type>
        <property1></property1>
        <property2></property2>
        <items>
            <item>
                <id></id>
                <name></name>
            </item>
            ...
            <item>
                <id></id>
                <name></name>
            </item>
        </items>
    </element>
</elements>

I should convert this construction not into element with nested list of items but into several elements one for every item. Here is example of Element class:

我不应该将这种结构转换为具有嵌套项目列表的元素,而是转换为每个项目一个的多个元素。这是 Element 类的示例:

class Element {
    Integer type;
    String property1;
    String property2;
    Integer itemId;
    String itemName; 
}

I want to get list of them after unmarshalling. Type, property1 and property2 values should be the same for all list elements. Is there any possibility to solve this problem using JAXB?

我想在解组后获得它们的列表。所有列表元素的类型、属性 1 和属性 2 值应该相同。有没有可能使用 JAXB 解决这个问题?

采纳答案by Ricardo Veguilla

You will need to define a custom XmlAdapter. The complicated part in your case is that you want to map one XML elementinto multiple Java Elementobjects. This means that, in Java., your XmlAdapterneeds to be configured for collection of Elementobjects. Assuming your example XML fragment is part of a document:

您将需要定义一个自定义XmlAdapter。在您的情况下,复杂的部分是您希望将一个 XML 映射element到多个 JavaElement对象中。这意味着,在 Java 中,您XmlAdapter需要针对Element对象集合进行配置。假设您的示例 XML 片段是文档的一部分:

<document>
   <elements> 
      <element>
          ....
      </element>
   <elements>
</document>    

Then you will need to configure the XmlAdapterfor the List<Element>field in the Java Documentclass:

然后你需要在 Java类中XmlAdapterList<Element>字段配置Document

class Document {
     @XmlJavaTypeAdapter(CustomAdapter.class)
     List<Element> elements;
}

Then you your CustomAdapterclass can receive a list of Element objects (corresponding to the actual XML structure with the nested items) and produce a list of Element with the structure you want.

然后,您的CustomAdapter类可以接收一个 Element 对象列表(对应于带有嵌套项的实际 XML 结构)并生成一个具有您想要的结构的 Element 列表。

For an example, check JAXB XmlAdapter – Customized Marshaling and Unmarshaling

例如,检查JAXB XmlAdapter – 自定义编组和解组

回答by Alkis Kalogeris

Main.java

主程序

import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;


public class Main {

    public static void main(String[] args) {

        List<Element> elementList = new ArrayList<Element>();
        List<Item> itemList = new ArrayList<Item>();
        Element element1 = new Element();
        Element element2 = new Element();
        Item item1 = new Item();
        Item item2 = new Item();
        Elements elements = new Elements();

        item1.setId(1);
        item1.setName("Test1");
        item2.setId(2);
        item2.setName("Test2");
        itemList.add(item1);
        itemList.add(item2);

        element1.setProperty1("prop1");
        element1.setProperty2("prop2");
        element1.setType(2);
        element1.setItems(itemList);

        element2.setProperty1("prop11");
        element2.setProperty2("prop22");
        element2.setType(22);
        element2.setItems(itemList);

        elementList.add(element1);
        elementList.add(element2);

        elements.setElements(elementList);

        try {
            System.out.println("------- Object to XML -----------\n");
            JAXBContext jaxbContext = JAXBContext.newInstance(Elements.class);
            Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

            // output pretty printed
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

            jaxbMarshaller.marshal(elements, System.out);

            System.out.println("\n------- XML to Object -----------\n");

            String xml = "<elements><element><items><item><id>1</id><name>Test1</name></item><item><id>2</id><name>Test2</name></item></items><property1>prop1</property1><property2>prop2</property2><type>2</type></element><element><items><item><id>1</id><name>Test1</name></item><item><id>2</id><name>Test2</name></item></items><property1>prop11</property1><property2>prop22</property2><type>22</type></element></elements>";
            StringReader reader = new StringReader(xml);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
            Elements elementsOut = (Elements) jaxbUnmarshaller.unmarshal(reader);
            System.out.println(elementsOut);

        } catch (JAXBException e) {
            e.printStackTrace();
        }    
    }
}

Elements.java

元素.java

import java.lang.reflect.Field;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name="elements")
public class Elements {

    List<Element> elements;

    @XmlElement(name="element")
    public List<Element> getElements() {
        return elements;
    }

    public void setElements(List<Element> elements) {
        this.elements = elements;
    }

    @Override
    public String toString() {
        Field[] fields = this.getClass().getDeclaredFields();
        String res = "";
        try {
            for (Field field : fields) {
                res += field.getName() + " :\n" + field.get(this);
            }
        } catch (Exception e) {
            e.printStackTrace(); 
        }

        return res;
    }
}

Element.java

元素.java

import java.lang.reflect.Field;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;

public class Element {

    Integer type;
    String property1;
    String property2;
    List<Item> items;

    public Integer getType() {
        return type;
    }

    public void setType(Integer type) {
        this.type = type;
    }

    public String getProperty1() {
        return property1;
    }

    public void setProperty1(String property1) {
        this.property1 = property1;
    }

    public String getProperty2() {
        return property2;
    }

    public void setProperty2(String property2) {
        this.property2 = property2;
    }

    @XmlElementWrapper(name="items")
    @XmlElement(name = "item")
    public List<Item> getItems() {
        return items;
    }

    public void setItems(List<Item> items) {
        this.items = items;
    }

    @Override
    public String toString() {
        Field[] fields = this.getClass().getDeclaredFields();
        String res = "\n";
        try {
            for (Field field : fields) {
                res += field.getName() + " : " + field.get(this) + "\n";
            }
        } catch (Exception e) {
            e.printStackTrace(); 
        }

        return res;
    }
}

Item.java

项目.java

import java.lang.reflect.Field;


public class Item {
    Integer id;
    String name; 

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        Field[] fields = this.getClass().getDeclaredFields();
        String res = "{";
        try {
            for (Field field : fields) {
                res += field.getName() + " : " + field.get(this);
            }
            res += "}";
        } catch (Exception e) {
            e.printStackTrace(); 
        }

        return res;
    }
}

Because the elementstag is root element you can't use @XmlElementWrapper, but itemsis not root, so you can use that there, thus you don't have to implement the Itemsclass. Ignore the toStringimplementation, it's just to print the objects in a meaningful way.

因为elements标签是根元素,你不能使用@XmlElementWrapper,但items不是根元素,所以你可以在那里使用它,因此你不必实现Items类。忽略toString实现,只是以有意义的方式打印对象。

Object to XML Output

对象到 XML 输出

------- Object to XML -----------

------- 对象到 XML -----------

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<elements>
    <element>
        <items>
            <item>
                <id>1</id>
                <name>Test1</name>
            </item>
            <item>
                <id>2</id>
                <name>Test2</name>
            </item>
        </items>
        <property1>prop1</property1>
        <property2>prop2</property2>
        <type>2</type>
    </element>
    <element>
        <items>
            <item>
                <id>1</id>
                <name>Test1</name>
            </item>
            <item>
                <id>2</id>
                <name>Test2</name>
            </item>
        </items>
        <property1>prop11</property1>
        <property2>prop22</property2>
        <type>22</type>
    </element>
</elements>

XML to Object Output

XML 到对象输出

------- XML to Object -----------

elements :
[
type : 2
property1 : prop1
property2 : prop2
items : [{id : 1name : Test1}, {id : 2name : Test2}]
, 
type : 22
property1 : prop11
property2 : prop22
items : [{id : 1name : Test1}, {id : 2name : Test2}]
]