I have an XML doc:
<?xml version="1.0" encoding="UTF-8"?>
<Log>
<logEntry>
<severity>WARN</severity>
<dateTime>2011-03-17 15:25</dateTime>
<message>Here is the text from the application</message>
<class>(class name)</class>
<program> TB Reception</program>
</logEntry>
<logEntry>
<severity>WARN</severity>
<dateTime>2011-03-17 15:25</dateTime>
<message>Here is the text from the application</message>
<class>(class name)</class>
<program> TB Reception</program>
</logEntry>
</Log>
and two POJOs:
package org.jwes.jaxb.jax;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="Log")
public class Log {
#XmlElementWrapper(name = "logEntry")
private List<LogEntry> logList;
public List<LogEntry> getLogEntries() {
return logList;
}
public void setLogEntries(List<LogEntry> logList) {
this.logList = logList;
}
}
package org.jwes.jaxb.jax;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlRootElement(name="LogEntry")
public class LogEntry{
private String source;
private String message;
private String severity;
private String program;
private String className;
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getSeverity() {
return severity;
}
public void setSeverity(String severity) {
this.severity = severity;
}
public String getProgram() {
return program;
}
public void setProgram(String program) {
this.program = program;
}
#XmlElement(name = "class")
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}
I'd like to retrieve the values of the XML nodes using JAXB. I wrote this quick code:
public class App
{
public static void main( String[] args ) throws JAXBException, IOException
{
JAXBContext jc = JAXBContext.newInstance(Log.class);
Unmarshaller um = jc.createUnmarshaller();
Log logElement=(Log)um.unmarshal(new FileReader("src/main/resources/log.xml"));
System.out.println(logElement.getLogEntries().toArray().length);
}
}
When i run it I always get value of zero.
You shouldn't be using #XmlElementWrapper here, just #XmlElement:
#XmlRootElement(name="Log")
public class Log {
#XmlElement(name = "logEntry")
private List<LogEntry> logList;
Related
Hi i'm new to JAXB Conversions.
I'm Unmarshalling an xml into java objects. For single occurrence sections there is no issue, but for multiple occurrence not able to map properly. Each time I'm getting null list for multiple occurrence section.
Please suggest me any useful url's or suggest me changes need to be done.
XML ::
<?xml version="1.0" encoding="UTF-8"?>
<designTheory>
<Administartor>
<circuitId>67565675476</circuitId>
<processId>567855</processId>
<version>01</version>
<circuitReferenceValue>ciruit-0001</circuitReferenceValue>
<property>cal-circuit</property>
</Administartor>
<designSec>
<priloc>priloc</priloc>
<secloc>secloc</secloc>
<remarks>remarks field</remarks>
</designSec>
<designNotes>
<notesNumber>1</notesNumber>
<notes>designNotes 1</notes>
</designNotes>
<designNotes>
<notesNumber>2</notesNumber>
<notes>designNotes 2</notes>
</designNotes>
<designNotes>
<notesNumber>3</notesNumber>
<notes>designNotes 3</notes>
</designNotes>
<designNotes>
<notesNumber>4</notesNumber>
<notes>designNotes 4</notes>
</designNotes>
</designTheory>
Code Snippets are as below :
DesignTheory.java
package org.manjunath.jaxbconversions.beans;
import java.util.List;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "designTheory")
public class DesignTheory {
#XmlElement(name = "Administartor", required = true)
private Administartor admin;
#XmlElement(name = "designSec", required = true)
private DesignSec designSec;
#XmlElementWrapper
#XmlElementRef(name = "designNotes")
private List<JAXBElement<DesignNotes>> designNotesList;
public void setAdministartor(Administartor admin){
this.admin = admin;
}
public Administartor getAdministartor() {
return admin;
}
public DesignSec getDesignSec() {
return designSec;
}
public void setDesignSec(DesignSec designSec) {
this.designSec = designSec;
}
public List<JAXBElement<DesignNotes>> getDlrnotes() {
return designNotesList;
}
public void setDlrnotes(List<JAXBElement<DesignNotes>> designNotesList) {
this.designNotesList = designNotesList;
}
}
Administartor.java
package org.manjunath.jaxbconversions.beans;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "Administartor")
public class Administartor {
#XmlElement(name = "circuitId")
private String circuitId;
#XmlElement(name = "processId")
private String processId;
#XmlElement(name = "version")
private String version;
#XmlElement(name = "circuitReferenceValue")
private String circuitReferenceValue;
#XmlElement(name = "property")
private String property;
public String getcircuitId() {
return circuitId;
}
public void setcircuitId(String circuitId) {
this.circuitId = circuitId;
}
public String getprocessId() {
return processId;
}
public void setprocessId(String processId) {
this.processId = processId;
}
public String getVer() {
return version;
}
public void setVer(String version) {
this.version = version;
}
public String getcircuitReferenceValue() {
return circuitReferenceValue;
}
public void setcircuitReferenceValue(String circuitReferenceValue) {
this.circuitReferenceValue = circuitReferenceValue;
}
public String getproperty() {
return property;
}
public void setproperty(String property) {
this.property = property;
}
}
DesignSec.java
package org.manjunath.jaxbconversions.beans;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "designSec")
public class DesignSec {
#XmlElement (name = "priloc")
private String priloc;
#XmlElement (name = "secloc")
private String secloc;
#XmlElement (name = "remarks")
private String remarks;
public String getpriloc() {
return priloc;
}
public void setpriloc(String priloc) {
this.priloc = priloc;
}
public String getSecloc() {
return secloc;
}
public void setSecloc(String secloc) {
this.secloc = secloc;
}
public String getremarks() {
return remarks;
}
public void setEcspc(String remarks) {
this.remarks = remarks;
}
}
DesignNotes.java
package org.manjunath.jaxbconversions.beans;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "designNotes")
#XmlAccessorType(XmlAccessType.FIELD)
public class DesignNotes {
#XmlElement (name = "notesNumber")
private String notesNumber;
#XmlElement (name = "notes")
private String notes;
public String getnotesNumber() {
return notesNumber;
}
public void setnotesNumber(String notesNumber) {
this.notesNumber = notesNumber;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
}
And I found somewhere the #XmlRegistry and #XmlElementDecl will solve my problem.
But I'm not so good with these annotations, but I tried by using ObjectFactory.java class. No use of this class
ObjectFactory.java
package org.manjunath.jaxbconversions.factory;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;
import org.manjunath.jaxbconversions.beans.DesignNotes;
#XmlRegistry
public class ObjectFactory {
private final static QName _DesignNotes_QNAME = new QName("designNotes");
public ObjectFactory(){
}
#XmlElementDecl(name="designNotes")
public JAXBElement<DesignNotes> createDesignNotes(DesignNotes value) {
return new JAXBElement<DesignNotes>(_DesignNotes_QNAME, DesignNotes.class, value);
}
}
Please suggest me to solve this problem
In your class DesignTheory the definition
#XmlElementWrapper
#XmlElementRef(name = "designNotes")
private List<JAXBElement<DesignNotes>> designNotesList;
is wrong.
In your XML you have
<designNotes>
...
</desinNotes>
<designNotes>
...
</designNotes>
...
But you do not have an additional wrapper around these <designNotes> like this
<designNotesList>
<designNotes>
...
</desinNotes>
<designNotes>
...
</designNotes>
...
<designNotesList>
That's why you need to remove the #XmlElementWrapper annotation.
And you should change its type from List<JAXBElement<DesignNotes>>
to List<DesignNotes>. So you end up with
#XmlElementRef(name = "designNotes")
private List<DesignNotes> designNotesList;
Also change the associated getter and setter from List<JAXBElement<DesignNotes>>
to List<DesignNotes>.
Then you don't need the ObjectFactory anymore and can remove it completely.
I verified the corrected classes with your XML and the following test-code
#Test
public void testUnmarshall() throws Exception {
JAXBContext context = JAXBContext.newInstance(DesignTheory.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
File file = new File("design-theory.xml");
DesignTheory designTheory = (DesignTheory) unmarshaller.unmarshal(file);
Assert.assertNotNull(designTheory.getDlrnotes());
Assert.assertEquals(4, designTheory.getDlrnotes().size());
}
The unmarshalled designTheory correctly has a non-null List<DesignNotes> with 4 elements.
I have a not-little problem with my current project, and probably you can help me with this...
When I worked before with xml messages, marshalling converted java objects to xml, where the java object attributes were set to xml nodes. But now I need to set that object attributes to xml node attributes, as I show here:
<Identification_List counter="">
<Identification number="XXXXXXX" letter="X" name="PERSON">
<TravelList counter="">
<Travel travelType="">
</TravelList>
</Identification>
</Identification_List>
How can I do this? What framework should I use? Thank you!
Edit: Example java class:
public class Identification {
private int number;
private char letter;
private String name;
private List<Travel> travelList;
//Add here constructors, getters and setters
}
That java class is the one that should be marshalled, where number, letter and name are the xml object properties
You need to add the appropriate JAXB annotations to your classes, to tell JAXB how to map your class to XML. For example:
#XmlRootElement(name = "Identification_List")
#XmlAccessorType(XmlAccessType.FIELD)
public class IdentificationList {
#XmlAttribute
private int counter;
#XmlElement(name = "Identification")
private List<Identification> identifications;
// getters and setters
}
#XmlAccessorType(XmlAccessType.FIELD)
public class Identification {
#XmlAttribute
private int number;
#XmlAttribute
private char letter;
#XmlAttribute
private String name;
#XmlElementWrapper(name = "TravelList")
#XmlElement(name = "Travel")
private List<Travel> travels;
// getters and setters
}
#XmlAccessorType(XmlAccessType.FIELD)
public class Travel {
#XmlAttribute
private String travelType;
// getters and setters
}
Do you need to convert java to xml ? use the same library ,
Here an Example
1-IdentificationList Class
package test;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
#XmlRootElement(name = "Identification_List")
public class IdentificationList {
private int counter;
private List<Identification> identificationList;
public IdentificationList() {
}
public IdentificationList(List<Identification> identificationList) {
this.identificationList = identificationList;
this.counter = identificationList == null ? 0 : identificationList.size();
;
}
#XmlElement(name = "Identification")
public List<Identification> getIdentificationList() {
return identificationList;
}
public void setIdentificationList(List<Identification> identificationList) {
this.identificationList = identificationList;
}
#XmlAttribute
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
}
}
2-Identification Class
package test;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
#XmlType(propOrder = {"number", "letter", "name","travelList"})
public class Identification {
private int number;
private String letter;
private String name;
private TravelList travelList;
public Identification() {
}
public Identification(int number, String letter, String name, TravelList travelList) {
this.number = number;
this.letter = letter;
this.name = name;
this.travelList = travelList;
}
#XmlAttribute
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
#XmlAttribute
public String getLetter() {
return letter;
}
public void setLetter(String letter) {
this.letter = letter;
}
#XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement(name = "TravelList")
public TravelList getTravelList() {
return travelList;
}
public void setTravelList(TravelList travelList) {
this.travelList = travelList;
}
}
3-TravelList Class
package test;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import java.util.List;
public class TravelList {
private List<Travel>travels;
private int counter;
public TravelList() {
}
public TravelList(List<Travel> travels) {
this.travels = travels;
this.counter=travels==null?0:travels.size();
}
#XmlElement(name = "Travel")
public List<Travel> getTravels() {
return travels;
}
public void setTravels(List<Travel> travels) {
this.travels = travels;
}
#XmlAttribute
public int getCounter() {
return counter;
}
public void setCounter(int counter) {
this.counter = counter;
}
}
4-Travel Class
package test;
import javax.xml.bind.annotation.XmlAttribute;
public class Travel {
private String travelType;
public Travel() {
}
public Travel(String travelType) {
this.travelType = travelType;
}
#XmlAttribute
public String getTravelType() {
return travelType;
}
public void setTravelType(String travelType) {
this.travelType = travelType;
}
}
5-IdentificationToXML Class
package test;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.FileOutputStream;
import java.util.ArrayList;
public class IdentificationToXML {
public static void main(String ...args) throws Exception {
JAXBContext contextObj = JAXBContext.newInstance(IdentificationList.class);
Marshaller marshallerObj = contextObj.createMarshaller();
marshallerObj.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Travel travel1=new Travel("My First Travel");
Travel travel2=new Travel("My Second Travel");
Travel travel3=new Travel("My Third Travel");
Travel travel4=new Travel("My Fourth Travel");
ArrayList<Travel> list=new ArrayList<Travel>();
list.add(travel1);
list.add(travel2);
ArrayList<Travel> list2=new ArrayList<Travel>();
list2.add(travel3);
list2.add(travel4);
Identification identification1=new Identification(111,"c","My Name",new TravelList(list));
Identification identification2=new Identification(222,"d","My Name",new TravelList(list2));
ArrayList<Identification> list3=new ArrayList<Identification>();
list3.add(identification1);
list3.add(identification2);
IdentificationList identification=new IdentificationList(list3);
marshallerObj.marshal(identification, new FileOutputStream("identification.xml"));
}
}
6-Output :
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Identification_List counter="2">
<Identification number="111" letter="c" name="My Name">
<TravelList counter="2">
<Travel travelType="My First Travel"/>
<Travel travelType="My Second Travel"/>
</TravelList>
</Identification>
<Identification number="222" letter="d" name="My Name">
<TravelList counter="2">
<Travel travelType="My Third Travel"/>
<Travel travelType="My Fourth Travel"/>
</TravelList>
</Identification>
</Identification_List>
I create an java class:
public class ReturnObj {
private String returncode;
private String returndesc;
private Pkg pkg;
public String getReturncode() {
return returncode;
}
public void setReturncode(String returncode) {
this.returncode = returncode;
}
public String getReturndesc() {
return returndesc;
}
public void setReturndesc(String returndesc) {
this.returndesc = returndesc;
}
}
and other class:
public class Pkg {
private String packagecode;
private String cycle;
private String price;
private String desc;
public String getPackagecode() {
return packagecode;
}
public void setPackagecode(String packagecode) {
this.packagecode = packagecode;
}
public String getCycle() {
return cycle;
}
public void setCycle(String cycle) {
this.cycle = cycle;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
And I Want to convert object ReturnObj to this XML
<return>
<returncode>1</returncode>
<returndesc>DANG_KY_THANH_CONG</returndesc>
<package>
<packagecode>BD30</packagecode>
<cycle>1</cycle>
<price>15000</price>
<desc> BD30</desc>
</package>
</return>
So how do I serialize an attribute pkg to package in XML? Because Java doesn't allow to name variable as an keyword anh package is an keyword in Java !
You can use JAXB marshling in your class it will convert the object to XML, here is link to help you JAXB Marshling
Try xstream
XStream xstream = new XStream();
xstream.alias("package", Pkg.class);
String xml = xstream.toXML(myReturnObj);
You can use JAXB API that comes with java for converting java object to XML.
Below is the code that will solve your requirement.
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "return")
public class ReturnObj {
private String returncode;
private String returndesc;
private Pkg pkg;
public Pkg getPkg() {
return pkg;
}
#XmlElement(name = "package")
public void setPkg(Pkg pkg) {
this.pkg = pkg;
}
public String getReturncode() {
return returncode;
}
#XmlElement(name = "returncode")
public void setReturncode(String returncode) {
this.returncode = returncode;
}
public String getReturndesc() {
return returndesc;
}
#XmlElement(name = "returndesc")
public void setReturndesc(String returndesc) {
this.returndesc = returndesc;
}
}
#XmlRootElement
public class Pkg {
private String packagecode;
private String cycle;
private String price;
private String desc;
public String getPackagecode() {
return packagecode;
}
#XmlElement(name="packagecode")
public void setPackagecode(String packagecode) {
this.packagecode = packagecode;
}
public String getCycle() {
return cycle;
}
#XmlElement(name="cycle")
public void setCycle(String cycle) {
this.cycle = cycle;
}
public String getPrice() {
return price;
}
#XmlElement(name="price")
public void setPrice(String price) {
this.price = price;
}
public String getDesc() {
return desc;
}
#XmlElement
public void setDesc(String desc) {
this.desc = desc;
}
}
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class JAXBExample {
private static final String FILE_NAME = "C:\\ru\\jaxb-returnObj.xml";
public static void main(String[] args) {
ReturnObj returnObj = new ReturnObj();
returnObj.setReturncode("1");
returnObj.setReturndesc("DANG_KY_THANH_CONG");
Pkg pkg = new Pkg();
pkg.setCycle("1");
pkg.setPrice("15000");
pkg.setDesc("BD30");
returnObj.setPkg(pkg);
jaxbObjectToXML(returnObj);
}
private static void jaxbObjectToXML(ReturnObj emp) {
try {
JAXBContext context = JAXBContext.newInstance(ReturnObj.class);
Marshaller m = context.createMarshaller();
// for pretty-print XML in JAXB
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
// Write to System.out, this will print the xml on console
m.marshal(emp, System.out);
// Write to File
m.marshal(emp, new File(FILE_NAME));
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
Explanation:
#XmlRootElement: This is a must have annotation for the Object to be used in JAXB. It defines the root element for the XML content.
#XmlElement: This will create the element. If you want to give some other name to the xml element when converting java object to xml then you can pass name attribute to the #XmlElement Example:
#XmlElement(name = "package")
Execute above code to see the desired output.
Happy Coding.
This is gonna be lengthy but I need some enlightenment. I'm new to JAXB so please be lenient with me.
CourseApp:
package Courses;
import java.io.File;
import java.util.ArrayList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
public class CoursesApp {
public static void main(String[] args) {
Courselist courselist = new Courselist();
courselist.setclassType("Lecture");
courselist.setcourseCode("2002");
courselist.setgroupIndex("1");
courselist.setprofessor("Professor James");
try{
File file = new File("C:\\Courselist.xml");
JAXBContext jaxbContext = JAXBContext.newInstance(Courselist.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(courselist, file);
jaxbMarshaller.marshal(courselist, System.out);
}catch(JAXBException e)
{
e.printStackTrace();
}
}
}
Courselist:
package Courses;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Courselist {
String courseCode;
String classType;
String groupIndex;
String professor;
public String getcourseCode() {
return courseCode;
}
#XmlElement
public void setcourseCode(String courseCode) {
this.courseCode = courseCode;
}
public String getclassType() {
return classType;
}
#XmlElement
public void setclassType(String classType) {
this.classType = classType;
}
public String getgroupIndex() {
return groupIndex;
}
#XmlElement
public void setgroupIndex(String groupIndex) {
this.groupIndex = groupIndex;
}
public String getprofessor() {
return professor;
}
#XmlElement
public void setprofessor(String professor) {
this.professor = professor;
}
}
Output:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
- <courselist>
<classType>Lecture</classType>
<courseCode>2002</courseCode>
<groupIndex>1</groupIndex>
<professor>Professor James</professor>
</courselist>
What I want is to create another instance of courselist within the same XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
- <courselist>
-<course>
<classType>Lecture</classType>
<courseCode>2002</courseCode>
<groupIndex>1</groupIndex>
<professor>Professor James</professor>
</course>
-<course>
<classType>Lecture</classType>
<courseCode>2003</courseCode>
<groupIndex>2</groupIndex>
<professor>Professor John</professor>
</course>
</courselist>
I would recommend to have one member in CourseList: List<Course> when Course will include all the members currently in CourseList.
This is the code:
#XmlRootElement
public class Courselist {
#XmlElement List<Course> course = new ArrayList<Course>();
}
Courselist
As oshai answered I would have a model with two classes Courselist and Course. Below is what the Courselist class would look like. To match Java programming conventions the package name is normally lower case. Also it is also often based on a domain name (such as com.example.courses). By default JAXB (JSR-222) implementations look for metadata on the property (get or set methods) so I've put them there (see: http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html).
package courses;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Courselist {
List<Course> courses;
#XmlElement(name="course")
public List<Course> getCourses() {
return courses;
}
public void setCourses(List<Course> courses) {
this.courses = courses;
}
}
Course
The information you had in the Courselist class I have moved to a new Course class. JAXB is configuration by exception so you only need to add annotations where you wish the XML representation to differ from the default. In your use case you don't need any annotations on this class (see: http://blog.bdoughan.com/2012/07/jaxb-no-annotations-required.html). I have fixed the casing on your property methods to match the normal Java coding conventions.
package courses;
public class Course {
String courseCode;
String classType;
String groupIndex;
String professor;
public String getCourseCode() {
return courseCode;
}
public void setCourseCode(String courseCode) {
this.courseCode = courseCode;
}
public String getClassType() {
return classType;
}
public void setClassType(String classType) {
this.classType = classType;
}
public String getGroupIndex() {
return groupIndex;
}
public void setGroupIndex(String groupIndex) {
this.groupIndex = groupIndex;
}
public String getProfessor() {
return professor;
}
public void setProfessor(String professor) {
this.professor = professor;
}
}
There's ugly XML file that has to be unmarshalled:
<?xml version="1.0" ?>
<configuration>
<section name="default_options">
<value name="default_port">8081</value>
<value name="log_level">WARNING</value>
</section>
<section name="custom_options">
<value name="memory">64M</value>
<value name="compatibility">yes</value>
</section>
</configuration>
Resulting Java Objects should be:
public class DefaultOptions {
private int defaultPort;
private String logLevel;
// etc...
}
public class CustomOptions {
private String memory;
private String compatibility;
// etc...
}
This question's answer is very close but I can't figure out the final solution.
How about?
Introduce a common super class called Options:
import javax.xml.bind.annotation.XmlAttribute;
public abstract class Options {
private String name;
#XmlAttribute
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Then on your class with the list of options (Configuration in this example), specify an #XmlJavaTypeAdapter on that property:
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
public class Configuration {
private List<Options> section = new ArrayList<Options>();
#XmlJavaTypeAdapter(OptionsAdapter.class)
public List<Options> getSection() {
return section;
}
public void setSection(List<Options> section) {
this.section = section;
}
}
The XmlAdapter will look something like this:
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class OptionsAdapter extends XmlAdapter<AdaptedOptions, Options> {
#Override
public Options unmarshal(AdaptedOptions v) throws Exception {
if("default_options".equals(v.name)) {
DefaultOptions options = new DefaultOptions();
options.setName(v.getName());
options.setDefaultPort(Integer.valueOf(v.map.get("default_port")));
options.setLogLevel(v.map.get("log_level"));
return options;
} else {
CustomOptions options = new CustomOptions();
options.setName(v.getName());
options.setCompatibility(v.map.get("compatibility"));
options.setMemory(v.map.get("memory"));
return options;
}
}
#Override
public AdaptedOptions marshal(Options v) throws Exception {
AdaptedOptions adaptedOptions = new AdaptedOptions();
adaptedOptions.setName(v.getName());
if(DefaultOptions.class == v.getClass()) {
DefaultOptions options = (DefaultOptions) v;
adaptedOptions.map.put("default_port", String.valueOf(options.getDefaultPort()));
adaptedOptions.map.put("log_level", options.getLogLevel());
} else {
CustomOptions options = (CustomOptions) v;
adaptedOptions.map.put("compatibility", options.getCompatibility());
adaptedOptions.map.put("memory", options.getMemory());
}
return adaptedOptions;
}
}
AdaptedOptions looks like:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlValue;
public class AdaptedOptions extends Options {
#XmlAttribute String name;
#XmlElement List<Value> value = new ArrayList<Value>();
Map<String, String> map = new HashMap<String, String>();
public void beforeMarshal(Marshaller marshaller) {
for(Entry<String, String> entry : map.entrySet()) {
Value aValue = new Value();
aValue.name = entry.getKey();
aValue.value = entry.getValue();
value.add(aValue);
}
}
public void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
for(Value aValue : value) {
map.put(aValue.name, aValue.value);
}
}
private static class Value {
#XmlAttribute String name;
#XmlValue String value;
}
}
You may create a separate classes to represent structure of your XML:
public class Section {
#XmlAttribute
public String name;
#XmlElement(name = "value")
public List<Value> values;
}
public class Value {
#XmlAttribute
public String name;
#XmlValue
public String value;
}
and then use an XmlAdapter to perform conversion:
public class OptionsAdapter extends XmlAdapter<Section, Options> {
public Options unmarshal(Section s) {
if ("default_options".equals(s.name)) {
...
} else if (...) {
...
}
...
}
...
}
#XmlElement
public class Configuration {
#XmlElement(name = "section")
#XmlJavaTypeAdapter(OptionsAdapter.class)
public List<Options> options;
}
public class DefaultOptions extends Options { ... }
public class CustomOptions extends Options { ... }