繁体   English   中英

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

[英]Unmarshalling nested list of xml items 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>

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

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

我想在解组后得到它们的清单。 对于所有列表元素,Type,property1和property2值应该相同。 有没有可能使用JAXB解决这个问题?

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

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

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

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;
    }
}

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

对象到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到对象输出

------- 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}]
]

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

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

然后,您需要为Java Document类中的List<Element>字段配置XmlAdapter

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

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

例如,检查JAXB XmlAdapter - Customized Marshaling和Unmarshaling

暂无
暂无

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

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