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
Unmarshalling nested list of xml items using JAXB
提问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 element
into multiple Java Element
objects. This means that, in Java., your XmlAdapter
needs to be configured for collection of Element
objects. 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 XmlAdapter
for the List<Element>
field in the Java Document
class:
然后你需要在 Java类中XmlAdapter
为List<Element>
字段配置Document
:
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
回答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 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.
Ignore the toString
implementation, 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}]
]