JAXB parsing a wrapper class which contains a single string property - java

The xml structure I am trying to parse is:
<contentFiles>
<contentFile>
<fileNumbers>
<fileNumber>123<fileNumber>
</fileNumbers>
</contentFile>
<contentFile/>
<contentFiles>
How do I parse this using JAXB ?
I used the annotations on getters described above but I only get the last element in the multiples of FileNumbers saved. I want to save all the elements of FileNumbers in the list. How do I do this ?
EDIT:::
#XmlRootElement(name = "contentFiles")
public class RtSuperQuickMetadata
{
private List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems;
#XmlElement(name = "contentFile")
public final List<RtSuperQuickMetadataItem> getRtSuperQuickMetadataItems()
{
return rtSuperQuickMetadataItems;
}
// Setter
}
public class RtSuperQuickMetadataItem
{
private List<FileNumber> fileNumbers;
public RtSuperQuickMetadataItem()
{
fileNumbers = new ArrayList<FileNumber>();
}
#XmlElement(name = "fileNumbers")
public List<FileNumber> getFileNumbers()
{
return fileNumbers;
}
//setter
}
#XmlRootElement(name="fileNumber")
public class FileNumber
{
private String fileNumber;
/**
* Default no-arg constructor.
*/
public FileNumber()
{
// public no-arg constructor for JAXB
}
/**
* Accept a filenumber as constructor arg.
* #param fileNumber is the fileNumber
*/
public FileNumber(final String fileNumber)
{
this.fileNumber = fileNumber;
}
/**
* Getter.
* #return the fileNumber
*/
//#XmlElement(name = "fileNumber")
public final String getFileNumber()
{
return fileNumber;
}
/**
* Setter.
* #param fileNumber to be set.
*/
public final void setFileNumber(final String fileNumber)
{
this.fileNumber = fileNumber;
}
#Override
public final String toString()
{
return fileNumber;
}
}

The reason I'm asking for a larger XML file representation is that your code will completely depend on the requirements of the XML file. For instance, this bit of your code works with the following XML file:
Code:
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.*;
import javax.xml.bind.*;
public class JaxbTest {
private static final String RESOURCE_NAME = "data.txt";
public static void main(String[] args) {
// marshallTest();
unmarshallTest();
}
private static void unmarshallTest() {
JAXBContext context;
try {
context = JAXBContext.newInstance(RtSuperQuickMetadata.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
RtSuperQuickMetadata metaData = (RtSuperQuickMetadata) unmarshaller
.unmarshal(JaxbTest.class.getResourceAsStream(RESOURCE_NAME));
System.out.println(metaData);
} catch (JAXBException e) {
e.printStackTrace();
}
}
private static void marshallTest() {
RtSuperQuickMetadata data = new RtSuperQuickMetadata();
List<RtSuperQuickMetadataItem> metaItemList = new ArrayList<RtSuperQuickMetadataItem>();
RtSuperQuickMetadataItem metaDataItem = new RtSuperQuickMetadataItem();
List<FileNumber> fileNumbers = new ArrayList<FileNumber>();
fileNumbers.add(new FileNumber("123"));
fileNumbers.add(new FileNumber("124"));
fileNumbers.add(new FileNumber("125"));
fileNumbers.add(new FileNumber("126"));
metaDataItem.setFileNumbers(fileNumbers);
metaItemList.add(metaDataItem);
data.setRtSuperQuickMetadataItems(metaItemList);
JAXBContext context;
try {
context = JAXBContext.newInstance(RtSuperQuickMetadata.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(data, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
#XmlRootElement(name = "contentFiles")
class RtSuperQuickMetadata {
private List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems;
#XmlElement(name = "contentFile")
public final List<RtSuperQuickMetadataItem> getRtSuperQuickMetadataItems() {
return rtSuperQuickMetadataItems;
}
public void setRtSuperQuickMetadataItems(
List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems) {
this.rtSuperQuickMetadataItems = rtSuperQuickMetadataItems;
}
#Override
public String toString() {
return "RtSuperQuickMetadata [rtSuperQuickMetadataItems="
+ rtSuperQuickMetadataItems + "]";
}
}
class RtSuperQuickMetadataItem {
private List<FileNumber> fileNumbers;
public RtSuperQuickMetadataItem() {
fileNumbers = new ArrayList<FileNumber>();
}
#XmlElement(name = "fileNumbers")
public List<FileNumber> getFileNumbers() {
return fileNumbers;
}
public void setFileNumbers(List<FileNumber> fileNumbers) {
this.fileNumbers = fileNumbers;
}
#Override
public String toString() {
return "RtSuperQuickMetadataItem [fileNumbers=" + fileNumbers + "]";
}
}
#XmlRootElement(name = "fileNumber")
class FileNumber {
private String fileNumber;
public FileNumber() {}
public FileNumber(final String fileNumber) {
this.fileNumber = fileNumber;
}
// #XmlElement(name = "fileNumber")
public final String getFileNumber() {
return fileNumber;
}
public final void setFileNumber(final String fileNumber) {
this.fileNumber = fileNumber;
}
#Override
public final String toString() {
return fileNumber;
}
}
The xml file, assuming it's in the same directory as your class files:
jaxbTest.xml
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<contentFiles>
<contentFile>
<fileNumbers>
<fileNumber>123</fileNumber>
</fileNumbers>
<fileNumbers>
<fileNumber>124</fileNumber>
</fileNumbers>
<fileNumbers>
<fileNumber>125</fileNumber>
</fileNumbers>
<fileNumbers>
<fileNumber>126</fileNumber>
</fileNumbers>
</contentFile>
</contentFiles>
However if this is not your desired XML structure, then the code must change.
Edit
If you want to not nest each fileNumber element in a fileNumbers element, then get rid of the FileNumbers class and instead use a List<String> with the #XmlElementWrapper annotation.
#XmlElementWrapper(name = "fileNumbers")
#XmlElement(name = "fileNumber")
public List<String> getFileNumbers() {
return fileNumbers;
}
For instance please check out this code:
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.*;
import javax.xml.bind.*;
public class JaxbTest {
private static final String RESOURCE_NAME = "data.xml";
public static void main(String[] args) {
// marshallTest();
unmarshallTest();
}
private static void unmarshallTest() {
JAXBContext context;
try {
context = JAXBContext.newInstance(RtSuperQuickMetadata.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
RtSuperQuickMetadata metaData = (RtSuperQuickMetadata) unmarshaller
.unmarshal(JaxbTest.class.getResourceAsStream(RESOURCE_NAME));
System.out.println(metaData);
} catch (JAXBException e) {
e.printStackTrace();
}
}
private static void marshallTest() {
RtSuperQuickMetadata data = new RtSuperQuickMetadata();
List<RtSuperQuickMetadataItem> metaItemList = new ArrayList<RtSuperQuickMetadataItem>();
RtSuperQuickMetadataItem metaDataItem = new RtSuperQuickMetadataItem();
// List<FileNumber> fileNumbers = new ArrayList<FileNumber>();
// fileNumbers.add(new FileNumber("123"));
// fileNumbers.add(new FileNumber("124"));
// fileNumbers.add(new FileNumber("125"));
// fileNumbers.add(new FileNumber("126"));
List<String> fileNumbers = new ArrayList<String>();
fileNumbers.add("123");
fileNumbers.add("124");
fileNumbers.add("125");
fileNumbers.add("126");
metaDataItem.setFileNumbers(fileNumbers);
metaItemList.add(metaDataItem);
data.setRtSuperQuickMetadataItems(metaItemList);
JAXBContext context;
try {
context = JAXBContext.newInstance(RtSuperQuickMetadata.class);
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(data, System.out);
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
#XmlRootElement(name = "contentFiles")
class RtSuperQuickMetadata {
private List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems;
#XmlElement(name = "contentFile")
public final List<RtSuperQuickMetadataItem> getRtSuperQuickMetadataItems() {
return rtSuperQuickMetadataItems;
}
public void setRtSuperQuickMetadataItems(
List<RtSuperQuickMetadataItem> rtSuperQuickMetadataItems) {
this.rtSuperQuickMetadataItems = rtSuperQuickMetadataItems;
}
#Override
public String toString() {
return "RtSuperQuickMetadata [rtSuperQuickMetadataItems="
+ rtSuperQuickMetadataItems + "]";
}
}
class RtSuperQuickMetadataItem {
private List<String> fileNumbers;
public RtSuperQuickMetadataItem() {
fileNumbers = new ArrayList<String>();
}
#XmlElementWrapper(name = "fileNumbers")
#XmlElement(name = "fileNumber")
public List<String> getFileNumbers() {
return fileNumbers;
}
public void setFileNumbers(List<String> fileNumbers) {
this.fileNumbers = fileNumbers;
}
#Override
public String toString() {
return "RtSuperQuickMetadataItem [fileNumbers=" + fileNumbers + "]";
}
}
Will work with this XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<contentFiles>
<contentFile>
<fileNumbers>
<fileNumber>123</fileNumber>
<fileNumber>124</fileNumber>
<fileNumber>125</fileNumber>
<fileNumber>126</fileNumber>
</fileNumbers>
</contentFile>
</contentFiles>

It's been a while since I've done JAX-B but I think this should do the trick (only relevant sections posted). If you want to avoid creating the FileNumberList class you can probably do so with an adapter but that will be more work than it is worth.
public class RtSuperQuickMetadataItem {
#XmlElement
public FileNumberList getFileNumbers() {
}
}
public class FileNumberList {
#XmlElement(name="fileNumber")
public List<String> getList() {
}
}

Related

Parsing an XML tag with colon in java jaxb

<?xml version="1.0" encoding="UTF-8"?>
<REQ-IF xmlns="http://www.omg.org/spec/ReqIF/20110401/reqif.xsd" xmlns:reqif-xhtml="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<THE-VALUE>
<reqif-xhtml:div>Hello</reqif-xhtml:div>
</THE-VALUE>
</REQ-IF>
I need to get the "Hello" message. While parsing this xml I am getting null value,
I have tried multiple thing, but issue did not resolve. My question is how to parse such tags with colon (namespaces).
public static void main(String[] args) {
InputStream is = new FileInputStream(file);
JAXBContext jaxbContext = JAXBContext.newInstance(REQ_IF.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
REQ_IF req_if = (REQ_IF) jaxbUnmarshaller.unmarshal(is);
THE_VALUE the_value = req_if.getThe_value();
DIV div = the_value.getDiv();
String value = div.getValue();
System.out.println(value);
}
I have created three classes.
First is REQ_IF
#XmlRootElement(name="REQ-IF")
#XmlAccessorType(XmlAccessType.FIELD)
public class REQ_IF implements Serializable {
private static final long serialVersionUID = 1L;
#XmlElement(name="THE-VALUE")
THE_VALUE the_value;
public REQ_IF() {
super();
}
public REQ_IF(THE_VALUE the_value) {
super();
this.the_value = the_value;
}
public THE_VALUE getThe_value() {
return the_value;
}
public void setThe_value(THE_VALUE the_value) {
this.the_value = the_value;
}
}
Second is THE_VALUE
#XmlRootElement(name="THE-VALUE")
#XmlAccessorType(XmlAccessType.FIELD)
public class THE_VALUE implements Serializable {
private static final long serialVersionUID = 1L;
#XmlElement(name="div")
DIV div;
public THE_VALUE() {
super();
}
public THE_VALUE(DIV div) {
super();
this.div = div;
}
public DIV getDiv() {
return div;
}
public void setDiv(DIV div) {
this.div = div;
}
}
And third one is DIV
#XmlRootElement(name = "div", namespace = "http://www.w3.org/1999/xhtml")
#XmlAccessorType(XmlAccessType.NONE)
public class DIV implements Serializable {
private static final long serialVersionUID = 1L;
#XmlValue
String value;
public DIV() {
super();
}
public DIV(String value) {
super();
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Here is my package-info.java
#javax.xml.bind.annotation.XmlSchema(
namespace = "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd",
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED,
xmlns = {
#javax.xml.bind.annotation.XmlNs(prefix = "", namespaceURI = "http://www.omg.org/spec/ReqIF/20110401/reqif.xsd"),
#javax.xml.bind.annotation.XmlNs(prefix = "reqif-xhtml", namespaceURI = "http://www.w3.org/1999/xhtml")
}
)
package com.abc.xyz;

why JAXB java xml unmarshaller return null

I am trying to unmarshal XML to java class as follows:-
My xml file as follows:-
<Features_res>
<StartWeek>202017</StartWeek>
<EndWeek>202035</EndWeek>
<Pno12>ABCDEEB</Pno12>
<FeatureList>
<Feature>
<Code>T002</Code>
</Feature>
<Feature>
<Code>T002</Code>
</Feature>
</FeatureList>
</Features_res>
Java InteriorResponse:-
#XmlRootElement(name = "Features_res")
public class InteriorResponse {
#XmlElement(name = "StartWeek")
private int sWeek;
#XmlElement(name = "EndWeek")
private int eWeek;
#XmlElement(name = "Pno12")
private String p12;
List<Feature> featureList;
public InteriorResponse() {
}
public InteriorResponse(int startWeek, int endWeek, String pno12) {
super();
this.sWeek = startWeek;
this.eWeek = endWeek;
this.p12 = pno12;
}
public int getStartWeek() {
return sWeek;
}
public void setStartWeek(int startWeek) {
this.sWeek = startWeek;
}
public int getEndWeek() {
return eWeek;
}
public void setEndWeek(int endWeek) {
this.eWeek = endWeek;
}
public String getPno12() {
return p12;
}
public void setPno12(String pno12) {
this.p12 = pno12;
}
public List<Feature> getFeatureList() {
return featureList;
}
#XmlElement(name = "FeatureList")
public void setFeatureList(List<Feature> featureList) {
this.featureList = featureList;
}
}
Another Java Feature:-
#XmlRootElement(name = "Feature")
public class Feature {
//#XmlElement(name = "Feature")
private String feature_;
#XmlElement(name = "code")
private String code_;
public String getCode() {
return code_;
}
public void setCode(String code) {
this.code_ = code;
}
public String getFeature_() {
return feature_;
}
public void setFeature_(String feature_) {
this.feature_ = feature_;
}
}
I am using above class as :-
public static void xmlToInterior() {
File file = new File("minxml.xml");
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance(InteriorResponse.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InteriorResponse interiorFeatures = (InteriorResponse) unmarshaller.unmarshal(file);
List<Feature> list_feat = interiorFeatures.getFeatureList();
for(Feature ft : list_feat) {
System.out.println(ft.getCode());
}
} catch (JAXBException e) {
e.printStackTrace();
}
}
Output I have as:-
list_feat
code_ null
feature_ null
And list_feat has size 1. It should 2.
Also I have to name class member sWeek instead of startWeek. Otherwise, jaxbContext = JAXBContext.newInstance(InteriorResponse.class) throws exception like 2 element exist with same name.
XML additional part
I thought I could do the reaming part of the XML. I was trying part by part. But I couldn't do it. I really need to find some good tutorial or book about JXB. All I find a short overview of JXB. Any suggestion about where to read in details?
<Features_res>
<StartWeek>202017</StartWeek>
<EndWeek>202035</EndWeek>
<Pno12>ABCDEEB</Pno12>
<FeatureList>
<Feature>
<Code>T002</Code>
</Feature>
<Feature>
<Code>T002</Code>
</Feature>
</FeatureList>
<OptionList>
<Option>001048</Option>
<Option>000050</Option>
<Option>000790</Option>
</OptionList>
</Features_res>
So I made new class as:-
public class OptionList {
private List<Option> options;
#XmlElement(name = "Option")
public List<Option> getOptions() {
return options;
}
public void setOptions(List<Option> options) {
this.options = options;
}
}
Another class as :-
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
public class Option {
#XmlElement(name = "Option")
private String option_;
public String getOption() {
return option_;
}
public void setOption(String option) {
this.option_ = option;
}
}
And updated for InteriorResponse class as:-
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "Features_res")
public class InteriorResponse {
#XmlElement(name = "StartWeek")
private int sWeek;
#XmlElement(name = "EndWeek")
private int eWeek;
#XmlElement(name = "Pno12")
private String p12;
private FeatureList featureList;
private OptionList optionList;
public InteriorResponse() {}
public InteriorResponse(int startWeek, int endWeek, String pno12) {
super();
this.sWeek = startWeek;
this.eWeek = endWeek;
this.p12 = pno12;
}
public int getStartWeek() {
return sWeek;
}
public void setStartWeek(int startWeek) {
this.sWeek = startWeek;
}
public int getEndWeek() {
return eWeek;
}
public void setEndWeek(int endWeek) {
this.eWeek = endWeek;
}
public String getPno12() {
return p12;
}
public void setPno12(String pno12) {
this.p12 = pno12;
}
#XmlElement(name = "FeatureList")
public FeatureList getFeatureList() {
return featureList;
}
public void setFeatureList(FeatureList featureList) {
this.featureList = featureList;
}
#XmlElement(name = "OptionList")
public OptionList getOptionList() {
return optionList;
}
public void setOptionList(OptionList optionList) {
this.optionList = optionList;
}
#Override
public String toString() {
return "InteriorResponse{"
+ "sWeek="
+ sWeek
+ ", eWeek="
+ eWeek
+ ", p12='"
+ p12
+ '\''
+ ", featureList="
+ featureList
+ '}';
}
}
I couldn't get the Option.
option null
The total xml is really huge. I still would like to try the remaing parts by myself part by part.
You need to design your classes according to XML structure. Find below the classes.
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name = "Features_res")
public class InteriorResponse {
#XmlElement(name = "StartWeek")
private int sWeek;
#XmlElement(name = "EndWeek")
private int eWeek;
#XmlElement(name = "Pno12")
private String p12;
private FeatureList featureList;
private OptionList optionList;
public InteriorResponse() {}
public InteriorResponse(int startWeek, int endWeek, String pno12) {
super();
this.sWeek = startWeek;
this.eWeek = endWeek;
this.p12 = pno12;
}
public int getStartWeek() {
return sWeek;
}
public void setStartWeek(int startWeek) {
this.sWeek = startWeek;
}
public int getEndWeek() {
return eWeek;
}
public void setEndWeek(int endWeek) {
this.eWeek = endWeek;
}
public String getPno12() {
return p12;
}
public void setPno12(String pno12) {
this.p12 = pno12;
}
#XmlElement(name = "FeatureList")
public FeatureList getFeatureList() {
return featureList;
}
public void setFeatureList(FeatureList featureList) {
this.featureList = featureList;
}
#XmlElement(name = "OptionList")
public OptionList getOptionList() {
return optionList;
}
public void setOptionList(OptionList optionList) {
this.optionList = optionList;
}
#Override
public String toString() {
return "InteriorResponse{"
+ "sWeek="
+ sWeek
+ ", eWeek="
+ eWeek
+ ", p12='"
+ p12
+ '\''
+ ", featureList="
+ featureList
+ ", optionList="
+ optionList
+ '}';
}
}
Class for Feature object
import javax.xml.bind.annotation.XmlElement;
public class Feature {
#XmlElement(name = "Code")
private String code_;
public String getCode() {
return code_;
}
public void setCode(String code) {
this.code_ = code;
}
#Override
public String toString() {
return "Feature{" + "code_='" + code_ + '\'' + '}';
}
}
Class for FeatureList
import javax.xml.bind.annotation.XmlElement;
import java.util.List;
public class FeatureList {
private List<Feature> features;
#XmlElement(name = "Feature")
public List<Feature> getFeatures() {
return features;
}
public void setFeatures(List<Feature> features) {
this.features = features;
}
}
Class for OptionList
import javax.xml.bind.annotation.XmlElement;
import java.util.List;
public class OptionList {
private List<String> option;
#XmlElement(name = "Option")
public List<String> getOption() {
return option;
}
public void setOption(List<String> option) {
this.option = option;
}
}
For testing and simplicity, I have written a small java test program below.
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.util.List;
public class Test {
public static void main(String[] args) {
File file =
new File("E:\\so\\xml\\minxml.xml");
JAXBContext jaxbContext;
try {
jaxbContext = JAXBContext.newInstance(InteriorResponse.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
InteriorResponse interiorFeatures = (InteriorResponse) unmarshaller.unmarshal(file);
List<Feature> list_feat = interiorFeatures.getFeatureList().getFeatures();
List<String> optionList = interiorFeatures.getOptionList().getOption();
for (String option : optionList) {
System.out.println("Option Value : " + option);
}
for (Feature ft : list_feat) {
System.out.println(ft.getCode());
}
} catch (JAXBException e) {
e.printStackTrace();
}
}
}
I also provide the sample xml structure below.
<Features_res>
<StartWeek>202017</StartWeek>
<EndWeek>202035</EndWeek>
<Pno12>ABCDEEB</Pno12>
<FeatureList>
<Feature>
<Code>T002</Code>
</Feature>
<Feature>
<Code>T002</Code>
</Feature>
</FeatureList>
<OptionList>
<Option>001048</Option>
<Option>000050</Option>
<Option>000790</Option>
</OptionList>
</Features_res>
I knew very little about JAXB stuff. I have learned a lot from Sambit who helped a lot and gave me the way to start with this JAXB. Later I have implemented my version with less number of Java class and more smart use of JAXB annotations.
My version of InteriorResponse class:-
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
#XmlRootElement(name = "Features_res")
public class InteriorResponse {
#XmlElement(name = "StartWeek")
private int startWeek;
#XmlElement(name = "EndWeek")
private int endWeek;
#XmlElement(name = "Pno12")
private String pno12;
#XmlElementWrapper(name = "FeatureList")
#XmlElement(name = "Feature")
private List<Feature> featureList;
#XmlElementWrapper(name = "OptionList")
#XmlElement(name = "Option")
private List<String> optionList;
public InteriorResponse() {
}
public InteriorResponse(int startWeek, int endWeek, String pno12) {
super();
this.startWeek = startWeek;
this.endWeek = endWeek;
this.pno12 = pno12;
}
#XmlTransient
public int getStartWeek() {
return startWeek;
}
public void setStartWeek(int startWeek) {
this.startWeek = startWeek;
}
#XmlTransient
public int getEndWeek() {
return endWeek;
}
public void setEndWeek(int endWeek) {
this.endWeek = endWeek;
}
#XmlTransient
public String getPno12() {
return pno12;
}
public void setPno12(String pno12) {
this.pno12 = pno12;
}
#XmlTransient
public List<Feature> getFeatureList() {
return featureList;
}
public void setFeatureList(List<Feature> featureList) {
this.featureList = featureList;
}
#XmlTransient
public List<String> getOptionList() {
return optionList;
}
public void setOptionList(List<String> optionList) {
this.optionList = optionList;
}
#Override
public String toString() {
return "InteriorResponse{" + "sWeek=" + startWeek + ", eWeek=" + endWeek + ", pno12='" + pno12 + '\'' + ", featureList=" + featureList + ", optionList="
+ optionList + '}';
}
}
My version of Feature class:-
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlTransient;
public class Feature {
#XmlElement(name = "Code")
private String code;
#XmlTransient
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
#Override
public String toString() {
return "Feature{" + "code_='" + code + '\'' + '}';
}
}
Note that I don't need any extra wrapper class for FeatuerList and OptionList. It can be done by the JAXB annotation #XmlElementWrapper(name = "FeatureList"). Also, a very important lesson learned. We have to mark all the property's getter method as #XmlTransient. Otherwise, JAXB throws an exception 2 properties found with the same name. Because our class all properties is visible to the JAXB. So we have to mark one as #XmlTransient.
In my opion, it is a better solution than the accepted answer. I gave all the credit to Sambit. I hove this will help others.

why do I get null when unmarshalling?

I am trying to read a XML file using JAXB, I'm also placing these into a list.
data code:
package xmll;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="data")
public class data {
private int millis;
private String stamp;
private String datetime;
private int light;
private double temp;
private double vcc;
#XmlElement
public int getMillis() {
return millis;
}
public void setMillis(int millis) {
this.millis = millis;
}
#XmlElement
public String getStamp() {
return stamp;
}
public void setStamp(String stamp) {
this.stamp = stamp;
}
#XmlElement
public String getDatetime() {
return datetime;
}
public void setDatetime(String datetime) {
this.datetime = datetime;
}
#XmlElement
public int getLight() {
return light;
}
public void setLight(int light) {
this.light = light;
}
#XmlElement
public double getTemp() {
return temp;
}
public void setTemp(double temp) {
this.temp = temp;
}
#XmlElement
public double getVcc() {
return vcc;
}
public void setVcc(double vcc) {
this.vcc = vcc;
}
public data(int millis, String stamp, String datetime, int light, double temp, double vcc){
super();
this.millis = millis;
this.stamp = stamp;
this.datetime = datetime;
this.light = light;
this.temp = temp;
this.vcc = vcc;
}
public data(){
super();
}
datalist code:
public class DataList {
private List<data> listData = new ArrayList<data>();
#XmlElement(name="Data")
public List<data> getDataList(){
return listData;
}
public void setListData(List<data> listData) {
this.listData = listData;
}
}
Main code:
public class jaxb {
public static void main(String[] args)throws JAXBException, FileNotFoundException {
try {
JAXBContext jc = JAXBContext.newInstance(DataList.class);
Unmarshaller ums = jc.createUnmarshaller();
DataList dl = (DataList)ums.unmarshal(new File(".\\data\fridgelogdata.xml"));
System.out.println("the data bitch");
for (data d: dl.getDataList()){
System.out.println("millis=" + d.getMillis());
System.out.println("stamp=" + d.getStamp());
System.out.println("datetime=" + d.getDatetime());
System.out.println("light=" + d.getLight());
System.out.println("temp=" + d.getTemp());
System.out.println("vcc=" + d.getVcc());
}
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Does the problem lie within the actual xml file I'm using?
Thankful for any help :)
Here is the first row of xml, the xml file is quite large and includes thousand of rows so I cant display the whole file. Apologies for any beginner mistakes.
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<millis>1000</millis>
<stamp> 1273010254</stamp>
<datetime> 2010/5/4 21:57:34</datetime>
<light> 333</light>
<temp> 78.32</temp>
<vcc> 3.54</vcc>
</row>
Your xml is completely different to the annotations in your data and datalist code.
Considering xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
<row>
<millis>1000</millis>
<stamp>1273010254</stamp>
<datetime>2010/5/4 21:57:34</datetime>
<light>333</light>
<temp>78.32</temp>
<vcc>3.54</vcc>
</row>
</root>
An correctly annotation class could be:
Root.java
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"row"
})
#XmlRootElement(name = "root")
public class Root {
#XmlElement(required = false)
protected List<Row> row;
public List<Row> getRow() {
if (row == null) {
row = new ArrayList<Row>();
}
return this.row;
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"millis",
"stamp",
"datetime",
"light",
"temp",
"vcc"
})
public static class Row {
protected Integer millis;
protected String stamp;
protected String datetime;
protected Integer light;
protected double temp;
protected double vcc;
public Integer getMillis() {
return millis;
}
public void setMillis(Integer value) {
this.millis = value;
}
public String getStamp() {
return stamp;
}
public void setStamp(String value) {
this.stamp = value;
}
//-...continue with the other getters and setters
}
}
EDIT Add method to unmarshall as asked in comment
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller ums = jc.createUnmarshaller();
Root root = (Root)ums.unmarshal(new File("pathToYourFile"));
for (Root.Row r: root.getRow()){
System.out.println("millis=" + r.getMillis());
//ecc...
}

JAXB getting original xml while unmarshalling for a list of elements

I have an xml input as below
<Confirmations>
<SystemConf>
<SysCnf>
<MessageId>1</MessageId>
</SysCnf>
<SysCnf>
<MessageId>2</MessageId>
</SysCnf>
</SystemConf>
</Confirmations>
and these are my classes
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "Confirmations")
public class Confirmations
{
#XmlElementWrapper(name = "SystemConf")
#XmlElement(name = "SysCnf")
private List<SystemConfirmation> systemConfirmations = null;
public List<SystemConfirmation> getSystemConfirmations()
{
return systemConfirmations;
}
public void setSystemConfirmations(List<SystemConfirmation> systemConfirmations)
{
this.systemConfirmations = systemConfirmations;
}
}
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "SysCnf")
public class SystemConfirmation
{
#XmlElement(name = "MessageId")
private String messageId;
public void setMessageId(String messageId)
{
this.messageId = messageId;
}
public String getMessageId()
{
return messageId;
}
#XmlAnyElement(value = SysConfXmlStringHandler.class)
private String xml;
public String getXml()
{
return xml;
}
}
public class SysConfXmlStringHandler implements DomHandler<String, StreamResult>
{
private static final String SYSCONF_START_TAG = "<SycCnf>";
private static final String SYSCONF_END_TAG = "</SysCnf>";
private StringWriter xmlWriter = new StringWriter();
#Override
public StreamResult createUnmarshaller(ValidationEventHandler errorHandler)
{
return new StreamResult(xmlWriter);
}
#Override
public String getElement(StreamResult rt)
{
String xml = rt.getWriter().toString();
System.out.println(xml);
int beginIndex = xml.indexOf(SYSCONF_START_TAG) + SYSCONF_START_TAG.length();
int endIndex = xml.indexOf(SYSCONF_END_TAG);
return xml.substring(beginIndex, endIndex);
}
#Override
public Source marshal(String n, ValidationEventHandler errorHandler)
{
try
{
String xml = SYSCONF_START_TAG + n.trim() + SYSCONF_END_TAG;
StringReader xmlReader = new StringReader(xml);
return new StreamSource(xmlReader);
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
}
Question
In the xml field of the SystemConfirmation class I want the whole xml of that particular SystemConfirmation block xmml element, which would be below
<SysCnf>
<MessageId>1</MessageId>
</SysCnf>
Does anyone know how to achieve this? I tried the above code but I was only getting MessageId block in the xml and if I add multiple fields in SystemConfirmation than I only get the first one.

Simple-XML - how to serialize derived classes in a collection?

I want to serialize a object hierarchy including a list of objects which derive from the base class 'Thing'. This works fine, including deserialization - but XML-Simple insists in writing an attribute which specifies the actual used Java-class
when I create a xml file with the java code below, the content is like this:
<example1>
<things>
<fruit class="com.mumpitz.simplexmltest.Apple" id="17">
<sugar>212</sugar>
</fruit>
<fruit class="com.mumpitz.simplexmltest.Orange" id="25" weight="11.2"/>
</things>
</example1>
but this is not what I want.
I'd like to have
<example1>
<things>
<apple id="17">
<sugar>212</sugar>
</apple>
<orange id="25" weight="11.2"/>
</things>
</example1>
'apple' and 'orange' elements without a class attribute, not 'fruit' with such an attribute. Is this possible?
(The second xml complies to a existing schema; adding extra attributes is not an option)
Here's the code:
package com.mumpitz.simplexmltest;
import java.io.File;
import java.util.ArrayList;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
class Fruit {
#Attribute(name = "id")
protected final int id;
Fruit(
#Attribute(name = "id")
int id) {
this.id = id;
}
int getObjectId() {
return id;
}
}
#Root
class Apple extends Fruit {
private final int sugar;
#Element(type = Fruit.class)
public Apple(
#Attribute(name = "id")
int id,
#Element(name = "sugar")
int sugar) {
super(id);
this.sugar = sugar;
}
#Element(name = "sugar")
public int getSugar() {
return this.sugar;
}
#Override
public String toString() {
return "id: " + id + ", sugar: " + sugar;
}
}
#Root
class Orange extends Fruit {
#Attribute
public double weight;
public Orange(
#Attribute(name = "id")
int id) {
super(id);
}
#Override
public String toString() {
return "id: " + id + ", weight: " + weight;
}
}
#Root
public class Example1 {
#ElementList
public ArrayList<Fruit> things = new ArrayList<Fruit>();
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("things:\n");
for (int i=0; i<things.size(); i++) {
sb.append(" " + things.get(i).toString() + "\n");
}
return sb.toString();
}
//////////////////////////////////
static Example1 createDummy() {
Example1 d = new Example1();
d.things.add(new Apple(17, 212));
Orange or = new Orange(25);
or.weight = 11.2;
d.things.add(or);
return d;
}
static String msg;
static Example1 res;
static public String getMessage() {
String m = msg;
msg = null;
return m;
}
static public boolean write(String path) {
Serializer serializer = new Persister();
Example1 example = Example1.createDummy();
File result = new File(path);
try {
serializer.write(example, result);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
static public boolean read(String path) {
Serializer serializer = new Persister();
File source = new File(path);
try {
res = serializer.read(Example1.class, source);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
public static Object getResult() {
return res;
}
}
some hours later I found the solution. You simply have to
Read the manual
Use the #ElementListUnion annotation
package com.mumpitz.simplexmltest;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.ElementListUnion;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
// the base class
#Element
class Thing {
static int count=0;
Thing() {
this.id = ++count;
}
#Attribute
protected int id;
public int getId() {
return id;
}
}
// first derived class
#Element
class Car extends Thing {
#Attribute
private String name;
Car(#Attribute(name="name") String name) {
this.name = name;
}
public String getName() {
return name;
}
#Override
public String toString() {
return "ID: " + id + " Car: " + name;
}
}
// second derived class
#Element
class House extends Thing {
#Attribute
private int price;
House(#Attribute(name="price") int price) {
this.price = price;
}
public int getPrice() {
return this.price;
}
#Override
public String toString() {
return "ID: " + id + " House: " + price;
}
}
// a class with a list of base class instances
#Root(name="ListOfThings")
public class Example4 {
// specify the derived classes used in the list
#ElementListUnion({
#ElementList(entry="house", inline=true, type=House.class),
#ElementList(entry="car", inline=true, type=Car.class)
})
private ArrayList<Thing> list = new ArrayList<Thing>();
public void add(Thing t) {
list.add(t);
}
public List<Thing> getProperties() {
return list;
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("Example4 contains " + list.size() + " elements:\n");
for (Thing t : list) {
sb.append(" " + t.toString() + "\n");
}
return sb.toString();
}
//////////////////////////////////
// test code
//////////////////////////////////
static String msg;
static Example4 res;
static public String getMessage() {
String m = msg;
msg = null;
return m;
}
static private Example4 createDummy() {
Example4 d = new Example4();
d.add(new Car("Mercedes"));
d.add(new House(34000000));
d.add(new Car("VW"));
d.add(new House(230000));
return d;
}
//////////////////////////////////
// serialize / deserialize
//////////////////////////////////
static public boolean write(String path) {
Serializer serializer = new Persister();
File result = new File(path);
Example4 example = Example4.createDummy();
try {
serializer.write(example, result);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
static public boolean read(String path) {
Serializer serializer = new Persister();
File source = new File(path);
try {
res = serializer.read(Example4.class, source);
} catch (Exception e) {
e.printStackTrace();
msg = e.getMessage();
return false;
}
return true;
}
public static Object getResult() {
return res;
}
}

Categories

Resources