Is there a way to map (using xstream) a List<Person> to <friends> and List<Things> to <stuff> for example?
Thanks!
Yes.
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
*
* #author nicholasdunn
*/
public class XStreamTest {
private List<Person> friends = new ArrayList<Person>();
private List<Thing> stuff = new ArrayList<Thing>();
public XStreamTest(List<Person> people, List<Thing> stuff) {
this.friends.addAll(people);
this.stuff.addAll(stuff);
}
private static class Person {
private String name;
public Person(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
private static class Thing {
private String description;
public Thing(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
};
public static void main(String[] args) {
XStream xstream = new XStream(new DomDriver());
xstream.alias("test", XStreamTest.class);
xstream.alias("person", Person.class);
xstream.alias("thing", Thing.class);
XStreamTest test = new XStreamTest(Arrays.asList(new Person("Fred")), Arrays.asList(new Thing("Xbox 360")));
System.out.println(xstream.toXML(test));
}
}
Prints
<test>
<friends>
<person>
<name>Fred</name>
</person>
</friends>
<stuff>
<thing>
<description>Xbox 360</description>
</thing>
</stuff>
</test>
If you mean something else, please clarify the question.
Why not use JAXB instead? If you don't like the annotations you can use EclipseLink MOXy's XML metata representation:
import java.util.Arrays;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
public class JAXBTest {
#XmlRootElement
public static class Root {
private List<Person> friend;
private List<Thing> stuff;
#XmlElementWrapper(name="friends")
public List<Person> getFriend() {
return friend;
}
public void setFriend(List<Person> friend) {
this.friend = friend;
}
#XmlElementWrapper(name="stuff")
public List<Thing> getStuff() {
return stuff;
}
public void setStuff(List<Thing> stuff) {
this.stuff = stuff;
}
}
public static class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
public static class Thing {
private String description;
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
public static void main(String[] args) throws JAXBException {
JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
Root root = new Root();
Person fred = new Person();
fred.setName("Fred");
root.setFriend(Arrays.asList(fred));
Thing xbox = new Thing();
xbox.setDescription("Xbox 360");
root.setStuff(Arrays.asList(xbox));
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
This prints the same XML as the XStream example:
<root>
<friends>
<friend>
<name>Fred</name>
</friend>
</friends>
<stuff>
<stuff>
<description>Xbox 360</description>
</stuff>
</stuff>
</root>
Related
I have a xml format like below:
<list>12
<item name="a">
<child parent="b" age="1">David Beckham</child>
</item>
</list>
The question is how could i extract 12 using JAXB? Which annotation supports it? Thank a lot.
Following is the working example.
import java.io.StringReader;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import javax.xml.bind.annotation.XmlMixed;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;
import javax.xml.transform.stream.StreamSource;
public class TestJAXBMixed {
public static void main(String[] args) throws Exception {
final String str =
"<list>12<item name=\"a\"><child parent=\"b\" age=\"1\">David Beckham</child></item></list>";
final JAXBContext jaxbContext = JAXBContext.newInstance(Child.class, Item.class, ListElement.class);
final JAXBElement<ListElement> obj = jaxbContext.createUnmarshaller().unmarshal(new StreamSource(new StringReader(str)), ListElement.class);
// The following is an array of objects representing the <list> content in order,
// i.e. it is a sequence of a String (12) and an Object (Item)
final List<Object> content = obj.getValue().getContent();
System.out.println(content);
}
}
#XmlRootElement(name="child")
class Child {
private String parent;
private String age;
private String text;
public String getParent() {
return parent;
}
#XmlAttribute(name="parent")
public void setParent(String parent) {
this.parent = parent;
}
public String getAge() {
return age;
}
#XmlAttribute(name="age")
public void setAge(String age) {
this.age = age;
}
public String getText() {
return text;
}
#XmlValue
public void setText(String text) {
this.text = text;
}
}
#XmlRootElement(name="item")
class Item {
private String name;
private Child child;
public String getName() {
return name;
}
#XmlAttribute(name="name")
public void setName(String name) {
this.name = name;
}
public Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
}
#XmlRootElement(name="list")
class ListElement {
private List<Object> content;
public List<Object> getContent() {
return content;
}
#XmlMixed
#XmlElementRefs({
#XmlElementRef(name="item", type=Item.class)
})
public void setContent(List<Object> content) {
this.content = content;
}
}
SimpleXml can do it:
final String data = ...
final SimpleXml simple = new SimpleXml();
final Element element = simple.fromXml(data);
System.out.println(element.text);
Will output:
12
From maven central:
<dependency>
<groupId>com.github.codemonstur</groupId>
<artifactId>simplexml</artifactId>
<version>1.4.0</version>
</dependency>
I'm trying to create a XML file from a HashMap. For each key of the hash i want an XML file. The value of the key is an ArrayList of Objects. I am using JAXB but the XML files are not created, as the output is not XML valid.
The object class:
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "Product")
public class Product implements Comparable<Product>{
String ID,description, gtin;
double price;
String date;
Product()
{
}
public String toString()
{
return ID+" "+description+" "+gtin+" "+price+" "+date;
}
public String getID() {
return ID;
}
#XmlElement
public void setID(String ID) {
this.ID = ID;
}
public String getDescription() {
return description;
}
#XmlElement
public void setDescription(String description) {
this.description = description;
}
public String getGtin() {
return gtin;
}
#XmlElement
public void setGtin(String gtin) {
this.gtin = gtin;
}
public double getPrice() {
return price;
}
#XmlElement
public void setPrice(Double price) {
this.price = price;
}
}
The class where i try to create the XMLs:
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class CreateXML {
static void create(HashMap<String, ArrayList<Product> > map) {
try {
JAXBContext jaxbContext = JAXBContext.newInstance(ProdsList.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Set setOfKeys = map.keySet();
Iterator iterator = setOfKeys.iterator();
while (iterator.hasNext()) {
String keys = (String) iterator.next();
String filename= "C:\\Users\\As\\Desktop\\Sups\\"+keys+22+".xml";
File file = new File(filename);
ArrayList<Product> value = map.get(keys);
jaxbMarshaller.marshal(value, file);
jaxbMarshaller.marshal(value, System.out);
}
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
The class for the root of the xml:
import java.util.*;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso;
//#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name="Products")
//#XmlSeeAlso({ArrayList.class})
class ProdsList {
#XmlElement(name="Product")
ArrayList<Product> prods;
public ProdsList(){
prods=new ArrayList<Product>();
}
public ArrayList<Product> getProducts() {
return prods;
}
public void setProducts(ArrayList<Product> prods) {
this.prods = prods;
}
}
How can i fix this. Thanks in advance.
You need to marshal an instance of ProdsList. Instead you are trying to marshall
an ArrayList of Products.
Change
jaxbMarshaller.marshal(value, file);
jaxbMarshaller.marshal(value, System.out);
To
jaxbMarshaller.marshal(new ProdsList(value), file);
jaxbMarshaller.marshal(new ProdsList(value), System.out);
I am having an issue with my unmarshaller. I have a file that looks like the following:
<Employee xmlns="namespace here">
<Employee>
<Id>2</Id>
<Name>idk</Name>
</Employee>
</Employee>
The problem is the root element and the list of elements are the same name "Employee". When I go to unmarshal I get a classcastexception.
#XmlRootElement(name="Employee")
public class EmployeeInformation {
List<EmployeeInformationElement> elements;
private String errorCode;
private String errorMessage;
public List<EmployeeInformationElement> getElements() {
return elements;
}
#XmlElement(name="Employee")
public void setElements(List<EmployeeInformationElement> elements) {
this.elements = elements;
}
public String getErrorCode() {
return errorCode;
}
#XmlElement(name="ErrorCode")
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}
public String getErrorMessage() {
return errorMessage;
}
#XmlElement(name="ErrorMessage")
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
I am able to use this code to marshal a file that looks exactly like the file I need to unmarshal. So I am confused. What is missing so when I unmarshal, the unmarshaller does not give me the following exception:
java.lang.ClassCastException: XXXX.EmployeeInformationElement cannot be cast to XXXX.EmployeeInformation
Unable to reproduce (tested on Java 1.8.0_65).
Since you didn't provide an MCVE (Minimal, Complete, and Verifiable example), here is one that works.
Only known difference is that namespace was removed for simple testing.
import java.io.StringReader;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
public class Test {
public static void main(String[] args) throws Exception {
String xml = "<Employee>\r\n" +
"<Employee>\r\n" +
" <Id>2</Id>\r\n" +
" <Name>idk</Name>\r\n" +
"</Employee>\r\n" +
"</Employee>\r\n";
JAXBContext jaxbContext = JAXBContext.newInstance(EmployeeInformation.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
EmployeeInformation empInfo = (EmployeeInformation)unmarshaller.unmarshal(new StringReader(xml));
System.out.println(empInfo);
}
}
#XmlRootElement(name="Employee")
class EmployeeInformation {
private List<EmployeeInformationElement> elements;
#XmlElement(name="Employee")
public List<EmployeeInformationElement> getElements() {
return elements;
}
public void setElements(List<EmployeeInformationElement> elements) {
this.elements = elements;
}
}
class EmployeeInformationElement {
private int id;
private String name;
#XmlElement(name="Id")
public int getId() {
return this.id;
}
public void setId(int id) {
this.id = id;
}
#XmlElement(name="Name")
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
}
I am using JAXB to covert xml to objects. After doing some tutorial, I can successfully convert a simple xml (which has single object and unique element tag) to object. Then I need to deal with more complicated xml which has multiple instances and one parent tag. I still use the similar structure. But I couldn't get the expected output of three country objects. what is wrong with my code? Please help.
IntelliJ IDE console output is:
Countries#5e20a82a
Process finished with exit code 0
xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Countries>
<Country>
<Country_Name>Spain</Country_Name>
<Country_Capital>Madrid</Country_Capital>
<Country_Continent>Europe</Country_Continent>
</Country>
<Country>
<Country_Name>USA</Country_Name>
<Country_Capital>Washington</Country_Capital>
<Country_Continent>America</Country_Continent>
</Country>
<Country>
<Country_Name>Japan</Country_Name>
<Country_Capital>Tokyo</Country_Capital>
<Country_Continent>Asia</Country_Continent>
</Country>
</Countries>
Countries.java
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlType( propOrder = { "name", "capital", "foundation", "continent" , "population"} )
#XmlRootElement( name = "Countries" )
public class Countries {
private int population;
private String name;
private String capital;
private int importance;
private String foundation;
private String continent;
#XmlElement(name = "Country_Population")
public void setPopulation(int population) {
this.population = population;
}
#XmlElement(name = "Country_Name")
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "Country_Capital")
public void setCapital(String capital) {
this.capital = capital;
}
#XmlAttribute(name = "importance", required = true)
public void setImportance(int importance) {
this.importance = importance;
}
#XmlElement(name = "Country_foundation")
public void setFoundation(String foundation) {
this.foundation = foundation;
}
#XmlElement(name = "Country_Continent")
public void setContinent(String continent) {
this.continent = continent;
}
}
CountryReader.java
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
public class CountryReader {
public static void main(String[] args) throws JAXBException {
File file = new File("country.xml");
JAXBContext jaxbContext = JAXBContext.newInstance( Countries.class );
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Countries countres = (Countries)jaxbUnmarshaller.unmarshal( file );
System.out.println( countres );
}
}
You should separate the mapping of the root element and the nested collection elements.
So you'd have something like this:
#XmlRootElement( name = "Countries" )
public class Countries {
private List<Country> countries;
#XmlElement(name = "Country")
public void setCountries(List<Country> countries) {
this.countries = countries;
}
}
#XmlType( propOrder = { "name", "capital", "foundation", "continent" , "population"} )
#XmlRootElement( name = "Country" )
public class Country {
private int population;
private String name;
private String capital;
private int importance;
private String foundation;
private String continent;
#XmlElement(name = "Country_Population")
public void setPopulation(int population) {
this.population = population;
}
#XmlElement(name = "Country_Name")
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "Country_Capital")
public void setCapital(String capital) {
this.capital = capital;
}
#XmlAttribute(name = "importance", required = true)
public void setImportance(int importance) {
this.importance = importance;
}
#XmlElement(name = "Country_foundation")
public void setFoundation(String foundation) {
this.foundation = foundation;
}
#XmlElement(name = "Country_Continent")
public void setContinent(String continent) {
this.continent = continent;
}
}
For more information about dealing with collections in JAXB, see this blog post. #XmlElementWrapper would seem suitable for your task, but I don't think it can be used directly with root elements.
I have found some examples of JAXB2 #XmlRegistry over the internet but no good in-depth tutorials that talk about the concept of using #XmlRegistry with #XmlElementDecl, wonder if its a concept not much explored in general.
Anyways here is my question, first some sample classes that I am using to unmarshall an xml using JAXB:
The main class I am trying to unmarshal using JAXB - Employee.java
package com.test.jaxb;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
import com.test.jaxb.dto.Address;
#XmlRootElement
public class Employee {
private int id;
private String name;
private String email;
private List<Address> addresses;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public List<Address> getAddresses() {
return addresses;
}
public void setAddresses(List<Address> addresses) {
this.addresses = addresses;
}
#SuppressWarnings("unused")
#XmlRegistry
public static class XMLObjectFactory {
#XmlElementDecl(scope = Employee.class, name= "id")
JAXBElement<String> createEmployeeId(String value) {
return new JAXBElement<String>(new QName("id"), String.class, "100");
}
#XmlElementDecl(scope = Employee.class, name= "name")
JAXBElement<String> createName(String value) {
return new JAXBElement<String>(new QName("name"), String.class, "Fake Name");
}
#XmlElementDecl(scope = Employee.class, name= "email")
JAXBElement<String> createEmail(String value) {
return new JAXBElement<String>(new QName("email"), String.class, value);
}
#XmlElementDecl(scope = Employee.class, name= "addresses")
JAXBElement<List> createAddresses(List value) {
return new JAXBElement<List>(new QName("addresses"), List.class, value);
}
}
}
The child class - Address.java
package com.test.jaxb.dto;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.namespace.QName;
import com.test.jaxb.Employee;
#XmlRootElement
public class Address {
private String addressLine1;
private String addressLine2;
private String addressLine3;
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(String addressLine2) {
this.addressLine2 = addressLine2;
}
public String getAddressLine3() {
return addressLine3;
}
public void setAddressLine3(String addressLine3) {
this.addressLine3 = addressLine3;
}
#SuppressWarnings("unused")
#XmlRegistry
private static class XMLObjectFactory {
#XmlElementDecl(scope = Employee.class, name= "addressLine1")
JAXBElement<String> createAddressLine1(String value) {
return new JAXBElement<String>(new QName("addressLine1"), String.class, value);
}
#XmlElementDecl(scope = Employee.class, name= "addressLine2")
JAXBElement<String> createAddressLine2(String value) {
return new JAXBElement<String>(new QName("addressLine2"), String.class, value);
}
#XmlElementDecl(scope = Employee.class, name= "addressLine3")
JAXBElement<String> createAddressLine3(String value) {
return new JAXBElement<String>(new QName("addressLine3"), String.class, value);
}
}
}
The xml to be unmarshalled - employee.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee>
<id>1</id>
<name>Vaishali</name>
<email>Vaishali#example.com</email>
<addresses>
<address>
<addressLine1>300</addressLine1>
<addressLine2>Mumbai</addressLine2>
<addressLine3>India</addressLine3>
</address>
<address>
<addressLine1>301</addressLine1>
<addressLine2>Pune</addressLine2>
<addressLine3>India</addressLine3>
</address>
</addresses>
</employee>
Unmarshalling Code :
package com.test.jaxb;
import java.io.FileReader;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
public class ObjectFactoryTest {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("resources/employee.xml");
JAXBContext context = JAXBContext.newInstance(Employee.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Object obj = unmarshaller.unmarshal(reader);
System.out.println(obj);
}
}
When I unmarshal the employee xml using above code, the address list does not get populated. The resulting employee object only has a blank list of adresses. Is there anything wrong with my mappings?
To find out what is going on and see if the employee objects are actually being created using the Object Factory (having the #XMLRegistry annotation), I changed the value of id and name in factory methods, however that had no effect in the output, which tells me JAXB is not actually using the ObjectFactory, why?
Am I going aboout this all wrong? Any help would be appreciated.
#XmlRegistry - how does it work?
#XmlRegistry is used to mark a class that has #XmlElementDecl annotations. To have your JAXB implementation process this class you need to ensure that it is included in the list of classes used to bootstrap the JAXBContext. It is not enough for it to be a static inner class of one of your domain model classes:
JAXBContext context = JAXBContext.newInstance(Employee.class, Employee.XMLObjectFactory.class);
#XmlElementDecl - how does it work?
If the value of the field/property is going to be a JAXBElement then you need to leverage #XmlElementDecl. A JAXBElement captures information that is can be useful:
Element name, this is necessary if you are mapping to a choice structure where multiple elements are of the same type. If the element name does not correspond to a unique type then you would not be able to round-trip the document.
JAXBElement can be used to represent an element with xsi:nil="true".
XmlObjectFactory
#XmlElementDecl also allows you to specify a scope. I have modified the model from you post a bit. I have introduced an XmlObjectFactory class that has two #XmlElementDecl. Both specify a name of address. I have leveraged the scope property so that for properties within the Employee class the #XmlElementDecl corresponding to the Address class with be used.
package forum11078850;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
#XmlRegistry
public class XmlObjectFactory {
#XmlElementDecl(scope = Employee.class, name = "address")
JAXBElement<Address> createAddress(Address value) {
return new JAXBElement<Address>(new QName("address"), Address.class, value);
}
#XmlElementDecl(name = "address")
JAXBElement<String> createStringAddress(String value) {
return new JAXBElement<String>(new QName("address"), String.class, value);
}
}
Employee
The #XmlElementRef annotation will cause the value of the property to be matched on its root element name. Possible matches will include classes mapped with #XmlRootElement or #XmlElementDecl.
package forum11078850;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlType(propOrder = { "id", "name", "email", "addresses" })
public class Employee {
private int id;
private String name;
private String email;
private List<JAXBElement<Address>> addresses;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#XmlElementWrapper
#XmlElementRef(name="address")
public List<JAXBElement<Address>> getAddresses() {
return addresses;
}
public void setAddresses(List<JAXBElement<Address>> addresses) {
this.addresses = addresses;
}
}
ObjectFactoryTest
package forum11078850;
import java.io.FileReader;
import javax.xml.bind.*;
public class ObjectFactoryTest {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("src/forum11078850/input.xml");
JAXBContext context = JAXBContext.newInstance(Employee.class, XmlObjectFactory.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Object obj = unmarshaller.unmarshal(reader);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(obj, System.out);
}
}
The Address class and input.xml from my original answer can be used to run this example.
ORIGINAL ANSWER
I'm not sure how you are attempting to use #XmlRegistry, so I will focus on the following part of your post:
When I unmarshal the employee xml using above code, the address list
does not get populated. The resulting employee object only has a blank
list of adresses. Is there anything wrong with my mappings?
Your list of Address objects is wrapped in a grouping element (addresses), so you need to use the #XmlElementWrapper annotation to map this use case. Below is a complete example:
Employee
package forum11078850;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlType(propOrder = { "id", "name", "email", "addresses" })
public class Employee {
private int id;
private String name;
private String email;
private List<Address> addresses;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#XmlElementWrapper
#XmlElement(name = "address")
public List<Address> getAddresses() {
return addresses;
}
public void setAddresses(List<Address> addresses) {
this.addresses = addresses;
}
}
Address
package forum11078850;
public class Address {
private String addressLine1;
private String addressLine2;
private String addressLine3;
public String getAddressLine1() {
return addressLine1;
}
public void setAddressLine1(String addressLine1) {
this.addressLine1 = addressLine1;
}
public String getAddressLine2() {
return addressLine2;
}
public void setAddressLine2(String addressLine2) {
this.addressLine2 = addressLine2;
}
public String getAddressLine3() {
return addressLine3;
}
public void setAddressLine3(String addressLine3) {
this.addressLine3 = addressLine3;
}
}
ObjectFactoryTest
package forum11078850;
import java.io.FileReader;
import javax.xml.bind.*;
public class ObjectFactoryTest {
public static void main(String[] args) throws Exception {
FileReader reader = new FileReader("src/forum11078850/input.xml");
JAXBContext context = JAXBContext.newInstance(Employee.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Object obj = unmarshaller.unmarshal(reader);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(obj, System.out);
}
}
input.xml/Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<employee>
<id>1</id>
<name>Vaishali</name>
<email>Vaishali#example.com</email>
<addresses>
<address>
<addressLine1>300</addressLine1>
<addressLine2>Mumbai</addressLine2>
<addressLine3>India</addressLine3>
</address>
<address>
<addressLine1>301</addressLine1>
<addressLine2>Pune</addressLine2>
<addressLine3>India</addressLine3>
</address>
</addresses>
</employee>
You have to take a List object of Address. In that object, you will have to add the object which contains data like addressline1. addressline2 and so on.
i.e.
List addrObjList = new List();
addrObjList.add(object); // Bind an object containing data and add one by one