JAXB annotations for nested element lists - java

I have the following XML:
<mappings>
<mapping>
<parameter attr = "value">asdas</parameter>
<parameter attr = "value2">d123asdsad</parameter>
<parameter attr = "value3">0</parameter>
</mapping>
<mapping>
<parameter attr = "value">23123s</parameter>
<parameter attr = "value2">qwerty</parameter>
<!-- more parameter elements -->
</mapping>
<!-- more mapping elements -->
</mappings>
I have the following java classes to map it to:
#XmlRootElement(name = "mappings")
public class Mappings {
#XmlElement(name = "mapping")
private List<Mapping> mMappings;
public List<Mapping> getMappings() {
return mMappings;
}
public void setMappings(List<Mapping> aMappings) {
this.mMappings = aMappings;
}
}
public class Mapping {
#XmlElement(name = "parameter")
private List<Parameter> mParameters;
public List<Parameter> getParameters() {
return mParameters;
}
public void setParameters(List<Parameter> aParameters) {
this.mParameters = aParameters;
}
}
public class Parameter {
#XmlAttribute(name = "attr")
private String mName;
#XmlValue
private String mValue;
public String getName() {
return mName;
}
public void setName(String aName) {
this.mName = aName;
}
public String getValue() {
return mValue;
}
public void setValue(String aValue) {
this.mValue = aValue;
}
}
When I try to unmarshall it with
JAXBContext context = JAXBContext.newInstance(BundleMappings.class);
Unmarshaller um = context.createUnmarshaller();
mappings = (BundleMappings)um.unmarshal(new File(myFile));
I get this error
If a class has #XmlElement property, it cannot have #XmlValue property.
I need parameter to have both the 'attr' attribute and content, so what am I doing wrong?

By default JAXB (JSR-222) implementations consider public properties (get/set methods) and annotated fields as mapped (and separate). The default mapping is #XmlElement so your properties will be considered as mapped this way.
Solution #1
Since you are annotating the fields you need to add #XmlAccessorType(XmlAccessType.FIELD) on your classes.
#XmlAccessorType(XmlAccessType.FIELD)
public class Parameter {
#XmlAttribute(name = "attr")
private String mName;
#XmlValue
private String mValue;
public String getName() {
return mName;
}
public void setName(String aName) {
this.mName = aName;
}
public String getValue() {
return mValue;
}
public void setValue(String aValue) {
this.mValue = aValue;
}
}
Solution #2
Annotate the get (or set) methods.
public class Parameter {
private String mName;
private String mValue;
#XmlAttribute(name = "attr")
public String getName() {
return mName;
}
public void setName(String aName) {
this.mName = aName;
}
#XmlValue
public String getValue() {
return mValue;
}
public void setValue(String aValue) {
this.mValue = aValue;
}
}
For More Information
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html
UPDATE
You will also need to use the #XmlElement annotation on the mappings property to specify the element name should be mapping.
#XmlRootElement(name = "mappings")
public class Mappings {
private List<Mapping> mMappings;
#XmlElement(name="mapping")
public List<Mapping> getMappings() {
return mMappings;
}
public void setMappings(List<Mapping> aMappings) {
this.mMappings = aMappings;
}
}

Related

SAXParser parse complex object

I am a novice in SAXParser. I don't know is it possible to parse complex object with SAXParser. I have a class which contain Item list. And my response xml is like that :
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><GetPaymentServiceInfoResponse xmlns="http://quetzalcoatlus/EpulPaymentService"><GetPaymentServiceInfoResult><ResultCodes>OK</ResultCodes><Description>User is temporary blocked</Description><Items><Item><Amount>122</Amount></Item><Item><Amount>23232</Amount></Item></Items></GetPaymentServiceInfoResult></GetPaymentServiceInfoResponse></s:Body></s:Envelope>
And my POJO class is like following:
#XmlRootElement(name = "PGResponse")
public class CheckAbonSuccessResponseModel {
private String message;
private String message_code;
private BigDecimal amount;
private String invoiceCode;
private String operationCode;
private List<Item> items;
#XmlElement(name = "message")
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
#XmlElement(name = "message_code")
public String getMessage_code() {
return message_code;
}
public void setMessage_code(String message_code) {
this.message_code = message_code;
}
#XmlElement(name = "amount")
public BigDecimal getAmount() {
return amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
#XmlElement(name = "invoice_code")
public String getInvoiceCode() {
return invoiceCode;
}
public void setInvoiceCode(String invoiceCode) {
this.invoiceCode = invoiceCode;
}
#XmlElement(name = "operation_code")
public String getOperationCode() {
return operationCode;
}
public void setOperationCode(String operationCode) {
this.operationCode = operationCode;
}
#XmlElement(name = "items")
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
#XmlRootElement(name = "item")
public static class Item {
private String label;
private String value;
#XmlElement(name = "label")
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
#XmlElement(name = "value")
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}
How I can parse my xml string to CheckAbonSuccessResponseModel. Is it possible or not? I was trying but it shows just amount inside Result element.I need just know how I must write DefaultHandler class.
Thanks in advance.

JAXB check if XML-Tag has specific attribute

I'm working at a Method to filter a collection (FileList) of xml-files if a specific xml-tag has an attribute...
In detail... I want to filter all xml-files where the xml-tag has an attribute "is_special", but I've problems to setup my model-classes for the attribute.
At the end I want to store the name of the file and a list of its items, where the value has the attribute is_special="true"
Also I'm using the JAXB Framework with the Moxy extension...
The XML-Structure as followed:
<document>
<id>75C8866AB078DCE541256D16002CF636</id>
<size>806220</size>
<author>xxx</author>
<last_modified>2017.06.12 07:15:41 GMT</last_modified>
<added_to_file>2016.07.05 09:50:44 GMT</added_to_file>
<created>2003.04.28 08:11:06 GMT</created>
<items>
<item>
<name>someName/name>
<type>LNITEMTYPE_DATETIMES</type>
<values>
<value is_special="true"/>
</values>
<last_modified>2003.04.28 08:11:10 GMT</last_modified>
...
</item>
<item>
<name>someName/name>
<type>LNITEMTYPE_TEXT</type>
<values>
<value>SOMETEXT</value>
<value>SOMETEXT</value>
</values>
<last_modified>2003.04.28 08:11:10 GMT</last_modified>
...
</item>
</items>
Therefor I've got 3 Classes for the XML-File...
"XMLDocument.java" implements the list of "Items.java" which implements the list of "Value.java"
XMLDocument.java
#XmlRootElement(name = "notes_document")
public class XMLDocument {
...
private List<Item> items;
...
#XmlElementWrapper(name = "items")
#XmlElement(name = "item")
public List<Item> getItems() {
return items;
}
public void setItems(List<Item> items) {
this.items = items;
}
}
item.java
#XmlRootElement(name = "items")
public class Item {
private String name;
private List<String> values;
private boolean valueIsSpecial;
#XmlElement(name = "name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElementWrapper(name = "values")
#XmlElement(name = "value")
public List<String> getValues() {
return values;
}
public void setValues(List<String> values) {
this.values = values;
}
#XmlPath("value/#is_special")
public boolean getValueIsSpecial() {
return valueIsSpecial;
}
public void setValueIsSpecial(boolean valueIsSpecial) {
this.valueIsSpecial = valueIsSpecial;
}
}
value.java
#XmlRootElement(name = "values")
public class Value {
#XmlElement(name = "value")
private String itemValue;
#XmlPath("value/#is_special")
private boolean isSpecial;
public String getValue() {
return itemValue;
}
public void setValue(String value) {
this.itemValue = value;
}
public boolean getValueIsSpecial() {
return isSpecial;
}
public void setValueIsSpecial(boolean isSpecial) {
this.isSpecial = isSpecial;
}
}
My Method so far...
public void FilterTree_isSpecial() throws JAXBException, FileNotFoundException {
for(String file: FileList) {
if (file.endsWith(".xml") && !file.contains("databaseinfo.xml")) {
JAXBContext context = JAXBContext.newInstance(NotesDocumentMetaFile.class);
Unmarshaller um = context.createUnmarshaller();
NotesDocumentMetaFile docMetaFile = (XMLDocument) um.unmarshal(new FileReader(file));
for (int i = 0; i < docMetaFile.getItems().size(); i++) {
// CHECK IF THE <value> OF THIS ITEM HAS ATTRIBUTE is_special
}
}
}
}
Much text... I hope anyone can give me a solution :/
Actually the xpath in your Item.java needs to be : values/value/#is_special like #XmlPath("values/value/#is_special")
If you want the is_special in your Value.java also your xpath should be :
#is_special like : #XmlPath(#is_special)
Also your Item.java, Value.java needs a little change. You don't need #XmlRootElement, you already had it in your XmlDocument.java
Your Item.java should be :
public class Item
{
private String name;
private String type;
private String lastModified;
private List<Value> values;
private String isSpecial;
#XmlPath("values/value/#is_special")
public String getIsSpecial() {
return isSpecial;
}
public void setIsSpecial(String isSpecial) {
this.isSpecial = isSpecial;
}
#XmlElement(name="type")
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
#XmlElement(name="last_modified")
public String getLastModified() {
return lastModified;
}
public void setLastModified(String lastModified) {
this.lastModified = lastModified;
}
#XmlElement(name="name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElementWrapper(name="values")
#XmlElement(name="value")
public List<Value> getValues() {
return values;
}
public void setValues(List<Value> values) {
this.values = values;
}
}
Your Value.java should be :
public class Value
{
#XmlPath("text()")
private String value;
#XmlPath("#is_special")
private String isSpecial;
public String getIsSpecial() {
return isSpecial;
}
public void setIsSpecial(String isSpecial) {
this.isSpecial = isSpecial;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Note that to get value and is_special in Value.java, you could use #XmlPath.
Now you can call getIsSpecial() on Item.java to check if it is special.

How to convert xml string to list of java objects using jaxb having different root and child element

I have below mentioned xml string and Team class. I want to convert all the row element to list of team using jaxb.
<team-all>
<query-output>
<row teamId="1" teamName ="MyTeam1" />
<row teamId="2" teamName ="MyTeam2" />
</query-output>
</team-all>
public class Team {
private String teamId;
private String teamName;
public String getTeamId() {
return teamId;
}
public void setTeamId(String teamId) {
this.teamId = teamId;
}
public String getTeamName() {
return teamName;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
}
#XmlRootElement(name="team-all")
#XmlAccessorType(XmlAccessType.FIELD)
public class AllTeam{
#XmlElementWrapper(name="query-output")
#XmlElement(name="row")
private List<Team> teams;
//getters and setters
}
#XmlAccessorType(XmlAccessType.FIELD)
public class Team {
#XmlAttribute
private String teamId;
#XmlAttribute
private String teamName;
public String getTeamId() {
return teamId;
}
public void setTeamId(String teamId) {
this.teamId = teamId;
}
public String getTeamName() {
return teamName;
}
public void setTeamName(String teamName) {
this.teamName = teamName;
}
}
Then
Unmarshaller um = JAXBContext.newInstance(AllTeam.class).createUnmarshaller();
AllTeam tm = um.unmarshall(new File("pathToXml"));
The unmarshall method can accept different inputs, if the file doesn't suits you.

Unable to unmarshall XML to POJO using jackson in camel route

I'm trying to unmarshall XML to POJO VmML class to pass it throught our system. The POJO classes was created from dtd file using jaxb2 maven plugin. When I use feature camel-jaxb in karaf I was able to unmarshall XML file into object of class VmML without any problem, but for some reasons I have to pull back this approach, and finally I end up with camel-jacksonxml.
In the route now I'm using unmarshall tag as below.
<dataFormats>
<jacksonxml id="jack" unmarshalTypeName="com.company.generated.VmML"/>
</dataFormats>
<rest path="/service"
consumes="application/xml"
produces="text/plain">
<post uri="/requestXmlCfg"
type="com.company.generated.VmML"
outType="java.lang.String">
<route>
<unmarshal ref="jack"/>
<to uri="bean:messageProcessot?method=process"/>
</route>
</post>
</rest>
I want to emphasize that it works earlier without unmarshaling tag, when I use simple camel-jaxb feature.
Now I get the exception which appears here often, but in my case the solutions are not proper because the data is provided and I don't want to skip anything. The error is:
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "ReportType" (class com.company.generated.CarrierReport), not marked as ignorable (3 known properties: "CarrierReportSnapshot", "CarrierReportHeader", "CarrierReportPeriod"])
at [Source: org.apache.camel.component.netty4.http.NettyChannelBufferStreamCache#612e834b; line: 6, column: 42] (through reference chain: com.company.generated.VmML["CarrierReport"]->java.util.ArrayList[0]->com.company.generated.CarrierReport["ReportType"])
POJO classes was created bas on: http://www.vmml.org/spec/VmML_v0.1.dtd
And the XML is filled properly
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE VmML SYSTEM "http://www.vmml.org/spec/VmML_v0.1.dtd">
<VmML Version="0.1">
<CarrierReport>
<CarrierReportHeader>
<ReportType SystemReference="aa">VMML</ReportType>
<ReportTimestamp Timezone="0" TimeFormat="RFC822">Tue, 07 May 2013 15:21:14 %2B0000</ReportTimestamp>
<SenderId SystemReference="aa">aa</SenderId>
<ReceiverId SystemReference="aa">aa</ReceiverId>
<SystemSource>aa</SystemSource>
<SystemDestination>aa</SystemDestination>
</CarrierReportHeader>
<CarrierReportSnapshot>
<Event>
<EventHeader>
<EventTimestamp Timezone="0" TimeFormat="RFC822">Tue, 07 May 2013 15:21:14 %2B0000</EventTimestamp>
<EventCode SystemReference="aa">aa</EventCode>
<EventText>aa</EventText>
</EventHeader>
</Event>
</CarrierReportSnapshot>
</CarrierReport>
</VmML>
VMML class:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"carrierReport"
})
#XmlRootElement(name = "VmML")
public class VmML {
#XmlAttribute(name = "Version", required = true)
#XmlJavaTypeAdapter(NormalizedStringAdapter.class)
protected String version;
#XmlAttribute(name = "id")
#XmlJavaTypeAdapter(NormalizedStringAdapter.class)
protected String id;
#XmlElement(name = "CarrierReport", required = true)
protected List<CarrierReport> carrierReport;
public String getVersion() {
return version;
}
public void setVersion(String value) {
this.version = value;
}
public String getId() {
return id;
}
public void setId(String value) {
this.id = value;
}
public List<CarrierReport> getCarrierReport() {
if (carrierReport == null) {
carrierReport = new ArrayList<CarrierReport>();
}
return this.carrierReport;
}
}
CarrierReport class:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"carrierReportHeader",
"carrierReportSnapshot",
"carrierReportPeriod"
})
#XmlRootElement(name = "CarrierReport")
public class CarrierReport {
#XmlElement(name = "CarrierReportHeader", required = true)
protected CarrierReportHeader carrierReportHeader;
#XmlElement(name = "CarrierReportSnapshot")
protected CarrierReportSnapshot carrierReportSnapshot;
#XmlElement(name = "CarrierReportPeriod")
protected CarrierReportPeriod carrierReportPeriod;
public CarrierReportHeader getCarrierReportHeader() {
return carrierReportHeader;
}
public void setCarrierReportHeader(CarrierReportHeader value) {
this.carrierReportHeader = value;
}
public CarrierReportSnapshot getCarrierReportSnapshot() {
return carrierReportSnapshot;
}
public void setCarrierReportSnapshot(CarrierReportSnapshot value) {
this.carrierReportSnapshot = value;
}
public CarrierReportPeriod getCarrierReportPeriod() {
return carrierReportPeriod;
}
public void setCarrierReportPeriod(CarrierReportPeriod value) {
this.carrierReportPeriod = value;
}
}
ReportType
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"value"
})
#XmlRootElement(name = "ReportType")
public class ReportType {
#XmlAttribute(name = "SystemReference")
#XmlJavaTypeAdapter(NormalizedStringAdapter.class)
protected String systemReference;
#XmlValue
protected String value;
public String getSystemReference() {
return systemReference;
}
public void setSystemReference(String value) {
this.systemReference = value;
}
public String getvalue() {
return value;
}
public void setvalue(String value) {
this.value = value;
}
}
Vmml > Carier Report > Carier Report Header > ReportType class
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"reportType",
"reportTimestamp",
"senderId",
"receiverId",
"systemSource",
"systemDestination",
"missionId",
"missionName"
})
#XmlRootElement(name = "CarrierReportHeader")
public class CarrierReportHeader {
#XmlElement(name = "ReportType", required = true)
protected ReportType reportType;
#XmlElement(name = "ReportTimestamp", required = true)
protected ReportTimestamp reportTimestamp;
#XmlElement(name = "SenderId", required = true)
protected SenderId senderId;
#XmlElement(name = "ReceiverId")
protected ReceiverId receiverId;
#XmlElement(name = "SystemSource", required = true)
protected String systemSource;
#XmlElement(name = "SystemDestination")
protected String systemDestination;
#XmlElement(name = "MissionId")
protected MissionId missionId;
#XmlElement(name = "MissionName")
protected String missionName;
public ReportType getReportType() {
return reportType;
}
public void setReportType(ReportType value) {
this.reportType = value;
}
public ReportTimestamp getReportTimestamp() {
return reportTimestamp;
}
public void setReportTimestamp(ReportTimestamp value) {
this.reportTimestamp = value;
}
public SenderId getSenderId() {
return senderId;
}
public void setSenderId(SenderId value) {
this.senderId = value;
}
public ReceiverId getReceiverId() {
return receiverId;
}
public void setReceiverId(ReceiverId value) {
this.receiverId = value;
}
public String getSystemSource() {
return systemSource;
}
public void setSystemSource(String value) {
this.systemSource = value;
}
public String getSystemDestination() {
return systemDestination;
}
public void setSystemDestination(String value) {
this.systemDestination = value;
}
public MissionId getMissionId() {
return missionId;
}
public void setMissionId(MissionId value) {
this.missionId = value;
}
public String getMissionName() {
return missionName;
}
public void setMissionName(String value) {
this.missionName = value;
}
}

Convert Java ENUM to XML

I want to make a xml from enum Type with parameters.
e.g:
#XmlRootElement(name="category")
#XmlAccessorType(XmlAccessType.NONE)
public enum category{
FOOD(2, "egg"),
private final double value;
#XmlElement
private final String description;
private Category(double value, String name){
this.value = value;
this.description = name;
}
}
I want to the generated XML be like this
<category>
FOOD
<description>Egg</description>
</category>
but, this is what I have:
<category>FOOD</category>
Any annotation from javax.xml.bind.annotation can do this?
Sorry for my bad English
You may want this
marshaller.marshal(new Root(), writer);
output <root><category description="egg">FOOD</category></root>
since #XmlValue and #XmlElement would not be allow to be in a same class
i change it to attribute
#XmlJavaTypeAdapter(CategoryAdapter.class)
enum Category {
FOOD(2D, "egg");
private double value;
#XmlAttribute
String description;
Category(double value, String name) {
this.value = value;
this.description = name;
}
}
#XmlRootElement(name = "root")
#XmlAccessorType(XmlAccessType.FIELD)
class Root {
#XmlElementRef
Category c = Category.FOOD;
}
#XmlRootElement(name = "category")
#XmlAccessorType(XmlAccessType.NONE)
class PrintableCategory {
#XmlAttribute
//#XmlElement
String description;
#XmlValue
String c;
}
class CategoryAdapter extends XmlAdapter<PrintableCategory, Category> {
#Override
public Category unmarshal(PrintableCategory v) throws Exception {
return Category.valueOf(v.c);
}
#Override
public PrintableCategory marshal(Category v) throws Exception {
PrintableCategory printableCategory = new PrintableCategory();
printableCategory.description = v.description;
printableCategory.c = v.name();
return printableCategory;
}
}

Categories

Resources