简体   繁体   English

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

[英]Unmarshalling nested list of xml items using JAXB

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. 对于所有列表元素,Type,property1和property2值应该相同。 Is there any possibility to solve this problem using JAXB? 有没有可能使用JAXB解决这个问题?

Main.java 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 Elements.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 Element.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 Item.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 elements tag is root element you can't use @XmlElementWrapper , but items is not root, so you can use that there, thus you don't have to implement the Items class. 因为elements标记是root元素,所以你不能使用@XmlElementWrapper ,但是items不是root,所以你可以在那里使用它,因此你不必实现Items类。 Ignore the toString implementation, it's just to print the objects in a meaningful way. 忽略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}]
]

You will need to define a custom XmlAdapter . 您需要定义自定义XmlAdapter The complicated part in your case is that you want to map one XML element into multiple Java Element objects. 您的案例中复杂的部分是您希望将一个XML element映射到多个Java Element对象。 This means that, in Java., your XmlAdapter needs to be configured for collection of Element objects. 这意味着,在Java中,需要配置XmlAdapter以收集Element对象。 Assuming your example XML fragment is part of a document: 假设您的示例XML片段是文档的一部分:

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

Then you will need to configure the XmlAdapter for the List<Element> field in the Java Document class: 然后,您需要为Java Document类中的List<Element>字段配置XmlAdapter

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

Then you your CustomAdapter class 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 - Customized Marshaling和Unmarshaling

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM