Cannot parse XML using Jackson, model never gets populated - java

I am trying to parse bellow xml using Jackson library but with no luck. I tried few things with my model, and I don't see the problem...
XML:
<?xml version="1.0" encoding="UTF-8"?>
<litre version="1.1" creator="Dummy Creator"
xsi:schemaLocation="http://www.dummy.com/xmlschemas/DummyExtension.xsd>
<metadata>
<link href="dummy.com">
<text>Dummy</text>
</link>
<time>2012-10-24T23:22:51.000Z</time>
</metadata>
<krt>
<name>Untitled</name>
<geskrt>
<pkrt data1="123" data2="321">
<ints>100</ints>
<time>2012-10-24T22:21:15.000Z</time>
<extensions>
<axtpx:DummyExtension>
<xtpx:hor>40000</xtpx:hor>
</axtpx:DummyExtension>
</extensions>
</pkrt>
<pkrt data1="543" data2="345">
<ints>100</ints>
<time>2012-10-24T23:29:40.000Z</time>
<extensions>
<axtpx:DummyExtension>
<xtpx:hor>50000</xtpx:hor>
</axtpx:DummyExtension>
</extensions>
</pkrt>
</geskrt>
</krt>
</litre>
POJO:
#JacksonXmlRootElement(localName = "litre")
public #Data class Model {
#JacksonXmlProperty(localName = "pkrt")
#JacksonXmlElementWrapper(useWrapping = false)
private List<Data> entries;
public static #Data class Data {
#JacksonXmlProperty(isAttribute = true, localName = "data1")
private double dataOne;
#JacksonXmlProperty(isAttribute = true, localName = "data2")
private double dataTwo;
#JacksonXmlProperty(localName = "ints")
private double inters;
private String time;
#JacksonXmlProperty(namespace = "xtpx:hor")
private long hours;
}
}
While trying to deserialize with:
Model model = mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.readValue(filePath.toFile(), Model.class);
parsing always passes with no exception, but entries list is always empty...
I would appreciate any help, thanx!

You most certainly have to do something like this:
#JacksonXmlRootElement(localName = "litre")
public #Data class Litre {
#JacksonXmlProperty(localName = "krt")
private Krt krt;
public static #Data class Krt {
#JacksonXmlProperty(localName = "geskrt")
private Geskrt geskrt;
}
public static #Data class Geskrt {
#JacksonXmlProperty(localName = "pkrt")
#JacksonXmlElementWrapper(useWrapping = false)
private List<Pkrt> pkrt;
}
public static #Data class Pkrt {
#JacksonXmlProperty(isAttribute = true, localName = "data1")
private double dataOne;
#JacksonXmlProperty(isAttribute = true, localName = "data2")
private double dataTwo;
#JacksonXmlProperty(localName = "ints")
private double inters;
private String time;
#JacksonXmlProperty(namespace = "xtpx:hor")
private long hours;
}
}

Related

Jackson XML :: Trying to write an attribute when there is no open start element

I have a class in Java that I want to serialize/deserialize to/from XML. Each property of this class should be serialized/deserialized to/from attributes of the XML element.
The XML looks something like:
<element fullName="Asim" age="30" score="0.78" readonly="true" bounds="[0,0][10,20]" tags="tag1,tag2,tag3">
...
...
</element>
If the properties are simple (String, int, boolean), this works. I can simply use #JacksonXmlProperty annotation and it gets the job done:
#JacksonXmlProperty(localName = "fullName", isAttribute = true)
private String fullName;
However, some of the properties are class objects (bounds, list) that I need to convert during serialization/deserialization. I have been able to use #JsonDeserialize annotation to read XML:
#JacksonXmlProperty(localName = "bounds", isAttribute = true)
#JsonDeserialize(using = BoundsDeserializer.class)
private Rectangle bounds;
Serializing these field, on the other hand, is proving to be quite a challenge. I've tried using JsonSerialize(using = BoundsSerializer.class) and JsonSerialize(converter = BoundsConverter.class) and nothing works. Either I get the following exception:
com.fasterxml.jackson.core.JsonGenerationException: Trying to write an attribute when there is no open start element.
Or the resulting XML looks like:
<element fullName="Asim" age="30" score="0.78" readonly="true">
<bounds>
<x>0</x>
<y>0</y>
<width>10</width>
<height>20</width>
</bounds>
<tags tags="tag1" tags="tag2" tags="tag3" />
...
...
</element>
How can I serialize a non-primitive property of a class as a string attribute in XML?
Edit
The main invocation code:
try {
XmlMapper mapper = new XmlMapper();
mapper.enable(SerializationFeature.INDENT_OUTPUT);
String xml = mapper.writeValueAsString(this);
return xml;
}
catch (Exception ex) { ... }
Relevant bits of the class to be serialized/deserialized: The commented lines are alternate approaches I tried (and failed).
#JacksonXmlRootElement(localName = "root")
#JsonIgnoreProperties(ignoreUnknown = true)
#Getter
#EqualsAndHashCode
#ToString
#NoArgsConstructor
#AllArgsConstructor
#Builder(toBuilder = true)
#Slf4j
public class XML {
#JacksonXmlProperty(localName = "text", isAttribute = true)
private String text;
#JacksonXmlProperty(localName = "tags", isAttribute = true)
#JsonDeserialize(using = ListDeserializer.class)
#JsonSerialize(converter = ListConverter.class)
//#JsonSerialize(using = ListSerializer.class)
//#JsonUnwrapped
private List<String> tags;
#JacksonXmlProperty(localName = "bounds", isAttribute = true)
#JsonDeserialize(using = BoundsDeserializer.class)
//#JsonSerialize(using = BoundsSerializer.class, contentAs = String.class)
private Rectangle bounds;
}
Bounds deserializer:
public class BoundsDeserializer extends JsonDeserializer<Rectangle> {
private static final Pattern BOUNDS_PATTERN = Pattern.compile("\\[(-?\\d+),(-?\\d+)]\\[(-?\\d+),(-?\\d+)]");
#Override
#Nullable
public Rectangle deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = p.getValueAsString();
if (value.isBlank()) {
return null;
}
Matcher m = BOUNDS_PATTERN.matcher(value);
if (!m.matches()) {
return ctxt.reportInputMismatch(Rectangle.class, "Not a valid bounds string: '%s'", value);
}
final int x1 = Integer.parseInt(m.group(1));
final int y1 = Integer.parseInt(m.group(2));
final int x2 = Integer.parseInt(m.group(3));
final int y2 = Integer.parseInt(m.group(4));
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
}
}
List deserializer:
public class ListDeserializer extends JsonDeserializer<List<String>> {
#Override
#Nullable
public List<String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String value = p.getValueAsString();
if (value.isBlank()) {
return null;
}
String deBracketed = value.trim().replaceAll("^\\[(.*)]$", "$1");
List<String> listValues = Arrays.stream(deBracketed.split(","))
.map(String::trim)
.filter(Predicate.not(String::isEmpty))
.collect(Collectors.toUnmodifiableList());
return listValues;
}
}
List converter:
public class ListConverter extends StdConverter<List<String>, String> {
#Override
public String convert(List<String> list) {
return String.join(",", list);
}
}
Thank you!
Asim
So the way I hacked my way around this issue was as follows:
#JacksonXmlProperty(localName = "tags", isAttribute = true)
#JsonDeserialize(using = ListDeserializer.class)
#JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private List<String> tags;
#JacksonXmlProperty(localName = "tags", isAttribute = true)
#JsonProperty(access = JsonProperty.Access.READ_ONLY)
private String tagsAsString() {
return String.join(",", this.tags);
}
The first field is write-only, so it will be deserialized only. The second field is read-only, so it will be serialized only. However, this feels really hackish and I think there has to be a better solution than this. :/
I came up with a better way to do the same thing:
// Used during serialization
#JacksonXmlProperty(localName = "bounds", isAttribute = true)
#JsonSerialize(converter = RectangleToStringConverter.class)
// Used during deserialization
#JsonProperty("bounds")
#JsonDeserialize(converter = StringToRectangleConverter.class)
private Rectangle bounds;

Jackson: deserialize custom attributes in XML to POJO

I would like to deserialize and map to class following values by name attribute.
This is piece of my XML file.
<custom-attributes>
<custom-attribute name="Name1" dt:dt="string">VALUE</custom-attribute>
<custom-attribute name="Name2" dt:dt="string">
<value>1111</value>
<value>1111</value>
<value>1111</value>
</custom-attribute>
<custom-attribute name="Name3" dt:dt="string">VALUE2</custom-attribute>
<custom-attribute dt:dt="boolean" name="Name3">VALUE3</custom-attribute>
<custom-attribute dt:dt="boolean" name="Name4">VALUE4</custom-attribute>
</custom-attributes>
And This is piece of my pojo class
#JsonIgnoreProperties(ignoreUnknown = true)
public class CustomAttributes {
#JacksonXmlProperty(localName="name3", isAttribute = true)
private String roleID;
public String getRoleID() {
return roleID;
}
public void setRoleID(String roleID) {
this.roleID = roleID;
}
}
Do you know ho to properly read values from those attribues by name ? Currently im receiving null
I am not sure what the result is supposed to look like, but if you want
to parse the complete xml into matching objects they would look like this:
public class CustomAttributeList {
#JacksonXmlProperty(localName = "custom-attributes")
private List<CustomAttributes> list;
...
}
#JacksonXmlRootElement(localName = "custom-attribute")
public class CustomAttributes {
// the name attribute
#JacksonXmlProperty
private String name;
// the datatype from the dt:dt field
#JacksonXmlProperty(namespace = "dt")
private String dt;
// the content between the tags (if available)
#JacksonXmlText
private String content;
// the values in the content (if available)
#JacksonXmlProperty(localName = "value")
#JacksonXmlElementWrapper(useWrapping = false)
private List<String> values;
...
}
Note that the localName="name3" from your question is not referring to a property at all.

SimpleXMLConverter parse xml nodes

I'm stuck. How to parse Node with same name child node?
In this example i need nodes with rate attribute.
<xml>
<Rates>
<Rates winrate_cap="9999">
<Rates rate="323"/>
<Rates rate="343"/>
<Rates rate="2338"/>
<Rates rate="233"/>
</Rates>
</Rates>
</xml>
My response wrapper class:
#Root(name = "xml", strict = false)
public class XMLResponse {
#ElementList(entry = "Rates")
public List<Rates> response;
public static class Rates {
#Attribute(name = "winrate_cap", required = false)
public String winrate_cup;
#ElementList(required = false, entry = "Rates")
public List<Rates> rates;
}
public static class Rates {
#Attribute(name = "rate", required = false)
public String rate;
}
}
You are on the right way. As you have many Rates here, better name the class more with more context and set the xml name via Annotation.
I've separated the XMLResponse and Rates classes, but this doesn't make any difference.
The class XMLRespone maps the <xml>...</xml> part:
#Root(name = "xml")
public class XMLRespone
{
#Element(name = "Rates")
private Rates rates;
// ...
}
All types for <Rates...>...</Rates> is done by Rates class (and it's inner classes, which map the structure:
#Root(name = "Rates")
public class Rates
{
#Element(name = "Rates")
private RateList rates;
// ...
public static class RateList
{
#ElementList(entry = "Rates", inline = true)
private ArrayList<RateValue> values;
#Attribute(name = "winrate_cap", required = true)
private int winrateCap;
// ...
}
public static class RateValue
{
#Attribute(name = "rate", required = true)
private int rate;
// ...
}
}
Deserializing your XML gives this output (using generated toString()):
XMLRespone{rates=Rates{rates=RateList{values=[RateValue{rate=323}, RateValue{rate=343}, RateValue{rate=2338}, RateValue{rate=233}], winrateCap=9999}}}

Cannot parse response with JAXB

I am trying to send a REST request and parse the response, but it returns NullPointerException. I assume the issue is with namespace.
When I have package-info.java file, it returns NullPointerException and when I do not it returns following:
Exception in thread "main"
org.springframework.http.converter.HttpMessageNotReadableException:
Could not unmarshal to [class com.expedia.HotelListResponse]: unexpected
element (uri:"http://v3.hotel.wsapi.ean.com/", local:"HotelListResponse").
Expected elements are <{}ChargeableRateInfo>,<{}HotelList>,
<{}HotelListResponse>,<{}HotelSummary>,<{}NightlyRate>,
<{}NightlyRatesPerRoom>,<{}RateInfo>,<{}RoomRateDetails>,
<{}RoomRateDetailsList>,<{}Surcharge>,<{}Surcharges>,<{}ValueAdd>,
<{}ValueAdds>; nested exception is javax.xml.bind.UnmarshalException:
unexpected element (uri:"http://v3.hotel.wsapi.ean.com/",
local:"HotelListResponse"). Expected elements are <{}ChargeableRateInfo>,
<{}HotelList>,<{}HotelListResponse>,<{}HotelSummary>,<{}NightlyRate>,
<{}NightlyRatesPerRoom>,<{}RateInfo>,<{}RoomRateDetails>,
<{}RoomRateDetailsList>,<{}Surcharge>,<{}Surcharges>,<{}ValueAdd>,
<{}ValueAdds>
If I remove qualified part of package-info the code shows following:
>>>0ABD9-732-A12-124-2BE4FD21A
>>>1
nullPointerException
....
Sample partial response
<ns2:HotelListResponse>
<customerSessionId>0ABD9-732-A12-124-2BE4FD21A
</customerSessionId>
<numberOfRoomsRequested>1</numberOfRoomsRequested>
<moreResultsAvailable>true</moreResultsAvailable>
<cacheKey>168951a:159922be3fd:-11ce</cacheKey>
<cacheLocation>19.11.13.19:7300</cacheLocation>
<HotelList size="20" activePropertyCount="1231">
<HotelSummary order="0">
<hotelId>335698</hotelId>
<name>Park Plaza Westminster Bridge London</name>
<address1>200 Westminster Bridge Road</address1>
<city>London</city>
<postalCode>SE1 7UT</postalCode>
<countryCode>GB</countryCode>
<airportCode>LCY</airportCode>
<supplierType>E</supplierType>
<propertyCategory>1</propertyCategory>
<hotelRating>4.0</hotelRating>
<confidenceRating>45</confidenceRating>
<amenityMask>1511947</amenityMask>
<locationDescription>Near London Aquarium</locationDescription>
<shortDescription><p><b>Property Location</b>
<br />A stay at Park Plaza Westminster Bridge London places
you in the heart of London, steps from London Aquarium and London
Dungeon. This 4-star hotel is close to</shortDescription>
<highRate>314.27</highRate>
<lowRate>254.35</lowRate>
<rateCurrencyCode>USD</rateCurrencyCode>
<latitude>51.50111</latitude>
<longitude>-0.11733</longitude>
<proximityDistance>0.7890795</proximityDistance>
<proximityUnit>MI</proximityUnit>
<hotelInDestination>true</hotelInDestination>
<thumbNailUrl>/hotels/4000000/3120000/3113100/3113039/3113039_31_t.jpg
</thumbNailUrl>
<deepLink>http://www.travelnow.com/templates/441384/hotels/335698/overview?lang=en&currency=USD&standardCheckin=11/23/2016&standardCheckout=11/25/2016&roomsCount=1&rooms[0].adultsCount=1
</deepLink>
<RoomRateDetailsList>
<RoomRateDetails>
<roomTypeCode>200750627</roomTypeCode>
<rateCode>203729567</rateCode>
<maxRoomOccupancy>2</maxRoomOccupancy>
<quotedRoomOccupancy>1</quotedRoomOccupancy>
<minGuestAge>0</minGuestAge>
<roomDescription>Superior Twin Room, 2 Single Beds
</roomDescription>
<promoId>209171300</promoId>
<promoDescription>Save 15%</promoDescription>
<currentAllotment>9</currentAllotment>
<propertyAvailable>true</propertyAvailable>
<propertyRestricted>false</propertyRestricted>
<expediaPropertyId>3113039</expediaPropertyId>
<rateKey>81300a5d-b697-457e-a059-2c22f6ce389b</rateKey>
<RateInfo priceBreakdown="true" promo="true" rateChange="true">
<ChargeableRateInfo averageBaseRate="263.30"
averageRate="217.28" commissionableUsdTotal="521.48"
currencyCode="USD" maxNightlyRate="222.61" nightlyRateTotal="434.57"
surchargeTotal="86.91" total="521.48">
<NightlyRatesPerRoom size="2">
<NightlyRate baseRate="269.75" rate="222.61" promo="true" />
<NightlyRate baseRate="256.84" rate="211.96" promo="true" />
</NightlyRatesPerRoom>
<Surcharges size="1">
<Surcharge type="TaxAndServiceFee" amount="86.91" />
</Surcharges>
</ChargeableRateInfo>
</RateInfo>
<ValueAdds size="1">
<ValueAdd id="2048">
<description>Free Wireless Internet</description>
</ValueAdd>
</ValueAdds>
</RoomRateDetails>
</RoomRateDetailsList>
</HotelSummary>
<HotelSummary order="1">
Request
final String URL = "http://api.ean.com/ean-services/rs/hotel/v3/list?cid="+CID+ "&apikey=" +API_KEY +"&sig= " + sig + "&apiExperience=PARTNER_WEBSITE&arrivalDate=12/11/2016&departureDate=12/18/2016&room1=1&city=London&stateProvinceCode=LN&countryCode=UK";
System.err.println("URL:" + URL);
RestTemplate restTemplate = new RestTemplate();
HotelListResponse hotelResponse = restTemplate.getForObject(URL,HotelListResponse.class);
System.err.println(">>>" + hotelResponse.getCacheKey());
System.err.println(">>>" + hotelResponse.getNumberOfRoomsRequested());
System.err.println(" Hotel Summaries Size>>>" + hotelResponse.getHotelList().getHotelSummaries().size());
package-info.java
#XmlSchema(
namespace = "http://v3.hotel.wsapi.ean.com/",
elementFormDefault = XmlNsForm.QUALIFIED)
package com.expedia;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
HotelListResponse
#XmlRootElement(name = "HotelListResponse")
#XmlAccessorType(XmlAccessType.FIELD)
public class HotelListResponse {
#XmlElement(name = "customerSessionId")
private String customerSessionId;
#XmlElement(name = "numberOfRoomsRequested")
private short numberOfRoomsRequested;
#XmlElement(name = "moreResultsAvailable")
private boolean moreResultsAvailable;
#XmlElement(name = "cacheKey")
private String cacheKey;
#XmlElement(name = "cacheLocation")
private String cacheLocation;
#XmlElement(name = "hotelList")
private HotelList hotelList;
getters and setters go here
HotelList
#XmlRootElement(name="HotelList")
#XmlAccessorType(XmlAccessType.FIELD)
public class HotelList {
#XmlAttribute(name="size")
private int size;
#XmlAttribute(name="activePropertyCount")
private int activePropertyCount;
private List<HotelSummary> hotelSummaries;
getters and setters go here
HotelSummary
#XmlRootElement(name="HotelSummary")
#XmlAccessorType(XmlAccessType.FIELD)
public class HotelSummary {
#XmlAttribute(name="order")
private int order;
#XmlElement(name="hotelId")
private int hotelId;
#XmlElement(name="name")
private String name;
#XmlElement(name="address1")
private String address1;
#XmlElement(name="city")
private String city;
#XmlElement(name="stateProvinceCode")
private String stateProvinceCode;
#XmlElement(name="postalCode")
private int postalCode;
#XmlElement(name="countryCode")
private String countryCode;
#XmlElement(name="airportCode")
private String airportCode;
#XmlElement(name="supplierType")
private String supplierType;
#XmlElement(name="propertyCategory")
private int propertyCategory;
#XmlElement(name="hotelRating")
private float hotelRating;
#XmlElement(name="confidenceRating")
private int confidenceRating;
#XmlElement(name="amenityMask")
private int amenityMask;
#XmlElement(name="locationDescription")
private String locationDescription;
#XmlElement(name="shortDescription")
private String shortDescription;
#XmlElement(name="highRate")
private double highRate;
#XmlElement(name="lowRate")
private double lowRate;
#XmlElement(name="rateCurrencyCode")
private String rateCurrencyCode;
#XmlElement(name="latitude")
private double latitude;
#XmlElement(name="longitude")
private double longitude;
#XmlElement(name="proximityDistance")
private double proximityDistance;
#XmlElement(name="proximityUnit")
private String proximityUnit;
#XmlElement(name="hotelInDestination")
private boolean hotelInDestination;
#XmlElement(name="thumbNailUrl")
private String thumbNailUrl;
#XmlElement(name="deepLink")
private String deepLink;
#XmlElement(name="RoomRateDetailsList")
private RoomRateDetailsList roomRateDetailsList;
getters and setters go here
RoomRateDetailsList
#XmlRootElement(name = "RoomRateDetailsList")
#XmlAccessorType(XmlAccessType.FIELD)
public class RoomRateDetailsList {
#XmlElement(name = "RoomRateDetails")
private RoomRateDetails roomRateDetails;
getters and setters go here
RoomRateDetails
#XmlRootElement(name = "RoomRateDetails")
#XmlAccessorType(XmlAccessType.FIELD)
public class RoomRateDetails {
#XmlElement(name = "roomTypeCode")
private int roomTypeCode;
#XmlElement(name = "rateCode")
private int rateCode;
#XmlElement(name = "maxRoomOccupancy")
private int maxRoomOccupancy;
#XmlElement(name = "quotedRoomOccupancy")
private int quotedRoomOccupancy;
#XmlElement(name = "minGuestAge")
private int minGuestAge;
#XmlElement(name = "roomDescription")
private String roomDescription;
#XmlElement(name = "currentAllotment")
private int currentAllotment;
#XmlElement(name = "propertyAvailable")
private boolean propertyAvailable;
#XmlElement(name = "propertyRestricted")
private boolean propertyRestricted;
#XmlElement(name = "expediaPropertyId")
private int expediaPropertyId;
#XmlElement(name = "rateKey")
private String rateKey;
#XmlElement(name="RateInfo")
private RateInfo rateInfo;
#XmlElement(name="ValueAdds")
private ValueAdds valueAdds;
getters and setters go here
RateInfo
#XmlRootElement(name="RateInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class RateInfo {
#XmlAttribute(name="priceBreakdown")
private boolean priceBreakdown;
#XmlAttribute(name="promo")
private boolean promo;
#XmlAttribute(name="rateChange")
private boolean rateChange;
#XmlElement(name="ChargeableRateInfo")
private ChargeableRateInfo chargeableRateInfo;
getters and setters go here
ChargeableRateInfo
#XmlRootElement(name = "ChargeableRateInfo")
#XmlAccessorType(XmlAccessType.FIELD)
public class ChargeableRateInfo {
#XmlAttribute(name = "averageBaseRate")
private double averageBaseRate;
#XmlAttribute(name = "averageRate")
private double averageRate;
#XmlAttribute(name = "commissionableUsdTotal")
private double commissionableUsdTotal;
#XmlAttribute(name = "currencyCode")
private String currencyCode;
#XmlAttribute(name = "maxNightlyRate")
private double maxNightlyRate;
#XmlAttribute(name = "nightlyRateTotal")
private double nightlyRateTotal;
#XmlAttribute(name = "surchargeTotal")
private double surchargeTotal;
#XmlAttribute(name = "total")
private double total;
#XmlElement(name = "NightlyRatesPerRoom")
private NightlyRatesPerRoom nightlyRatesPerRoom;
#XmlElement(name = "Surcharges")
private Surcharges surcharges;
getters and setters go here
NightlyRatesPerRoom
#XmlRootElement(name = "NightlyRatesPerRoom")
#XmlAccessorType(XmlAccessType.FIELD)
public class NightlyRatesPerRoom {
#XmlAttribute(name = "size")
private int size;
#XmlElement(name = "NightlyRate")
private List<NightlyRate> nightlyRates;
getters and setters go here
NightlyRate
#XmlRootElement(name = "NightlyRate")
#XmlAccessorType(XmlAccessType.FIELD)
public class NightlyRate {
#XmlAttribute(name = "baseRate")
private double baseRate;
#XmlAttribute(name = "rate")
private double rate;
#XmlAttribute(name = "promo")
private boolean promo;
getters and setters go here
Surcharges
#XmlRootElement(name = "Surcharges")
#XmlAccessorType(XmlAccessType.FIELD)
public class Surcharges {
#XmlAttribute(name = "size")
private int size;
#XmlElement(name = "Surcharge")
private List<Surcharge> surcharges;
getters and setters go here
Surcharge
#XmlRootElement(name = "Surcharge")
#XmlAccessorType(XmlAccessType.FIELD)
public class Surcharge {
#XmlAttribute(name = "type")
private String type;
#XmlAttribute(name = "amount")
private double amount;
getters and setters go here
ValueAdds
#XmlRootElement(name = "ValueAdds")
#XmlAccessorType(XmlAccessType.FIELD)
public class ValueAdds {
#XmlElement(name = "size")
private int size;
#XmlElement(name = "ValueAdd")
private ValueAdd valueAdd;
getters and setters go here
ValueAdd
#XmlRootElement(name = "ValueAdd")
#XmlAccessorType(XmlAccessType.FIELD)
public class ValueAdd {
#XmlElement(name = "description")
private String description;
getters and setters go here
Your schema declares elementFormDefault="qualified" as we can see in your package-info, so you must remove the ns2 prefix at the root Element, or you must add it to all the inner elements, depends on the xmlns declaration (that we can't see).

Correct way to parse XML using Simple Framework

I'm using Simple framework to deserialize an xml on my android app .
The issue is on a portion of the xml because I can get the objects of the other portions of it .
Here is the part of the xml that I struggle with :
<webtv name="channelname" date="2014-10-31">
<config>
<pathVideo extension="mp4">http://vodflash.channelname.com/tv_conn/1/country/</pathVideo>
<pathBigImage extension="jpg">http://vodflash.channelname.com/tv_conn/1/country/pic/320x180/</pathBigImage>
<pathImage extension="jpg">http://vodflash.channelname.com/tv_conn/1/country/pic/160x90/</pathImage>
<pays>GB;IE</pays>
</config>
Here is my XmlMapper class :
#Root(name="webtv", strict = false)
public class XmlModelMapper {
public ConfigObject getConfigObjects() {
return configObject;
}
#Element(name="config")
public ConfigObject configObject = new ConfigObject();
#ElementList(name = "itemList")
private List<Videos> itemList = new ArrayList<Videos>();
public List<Videos> getItemList() {
return itemList;
}
#ElementList(name = "chaineList")
private List<Chaine> chaineList = new ArrayList<Chaine>();
public List<Chaine> getChaineList() {
return chaineList;
}
}
If I change my mapper class to this :
#Root(name="webtv", strict = false)
public class XmlModelMapper {
public List<ConfigObject> getConfigObjects() {
return configObject;
}
//change is here using a list not an object
#ElementList(name="config")
public List<ConfigObject> configObjects = new ArrayList<ConfigObject>();
#ElementList(name = "itemList")
private List<Videos> itemList = new ArrayList<Videos>();
public List<Videos> getItemList() {
return itemList;
}
#ElementList(name = "chaineList")
private List<Chaine> chaineList = new ArrayList<Chaine>();
public List<Chaine> getChaineList() {
return chaineList;
}
}
and the log the size of the List I get 4 which is correct , but how to get each object in a distinct way including the extension (attribute)
Please help me solving this issue .
Thanks
#ElementList(name="config")
public List<ConfigObject> configObjects = new ArrayList<ConfigObject>();
This wont match with your xml listed above. While the #Element-based solution (example 1) will create a proper config-tag, the list adds another "list-tag"; here's an example:
<config> <!-- This is the list's tag, wrapping all elements -->
<config> <!-- This is the actual element's tag -->
<pathVideo extension="mp4">http://video.com</pathVideo>
<pathBigImage extension="jpg">http://bigimg.com</pathBigImage>
<pathImage extension="jpg">http://image.com</pathImage>
<pays>GB;IE</pays>
</config>
<!-- some more <config>...</config> -->
</config>
The solution: Use athe inline list - those don't have the "list-tag".
#ElementList(name = "config", inline = true, entry = "config")
public List<ConfigObject> configObjects = new ArrayList<>();
For the sake of completeness, here are my classes used for testing:
class Chaine { /* empty - enough for testing */ }
class Videos { /* empty - enough for testing */ }
#Root
public class ConfigObject
{
#Element(name = "pathVideo")
private PathConfig video;
#Element(name = "pathBigImage")
private PathConfig bigImage;
#Element(name = "pathImage")
private PathConfig image;
#Element(name = "pays")
private String pays;
// ...
}
#Root
public class PathConfig
{
#Attribute(name = "extension")
private String extension;
#Text
private String path;
// ...
}
Solved my issue and learned alot about simple framework which is great and light weight , but I prefer ollo's answer
Please discard ormlite annotations
My classes :
#Root(name="webtv", strict = false)
public class XmlModelMapper {
public ConfigObject getConfigObject() {
return configObject;
}
#Element(name="config")
public ConfigObject configObject = new ConfigObject();
//rest of the elements
...
}
and
#Root(name = "config" , strict = false)
public class ConfigObject {
#Element
PathVideo pathVideo;
#Element
PathImage pathImage;
#Element
PathBigImage pathBigImage ;
//rest of the elements
}
and
#Root(name = "pathImage")
#DatabaseTable(tableName = "imageconfig")
public class PathImage {
#DatabaseField(generatedId = true)
Integer id ;
#Attribute
#DatabaseField
String extension;
#Text
#DatabaseField
String pathImage;
//rest of the elements...
}
and
#Root(name = "pathVideo")
#DatabaseTable(tableName = "videoconfig")
public class PathVideo {
#DatabaseField(generatedId = true)
Integer id ;
#Attribute
#DatabaseField
String extension;
#Text
#DatabaseField
String pathVideo;
}
and finally
#Root(name = "pathBigImage")
#DatabaseTable(tableName = "bigimageconfig")
public class PathBigImage {
#DatabaseField(generatedId = true)
Integer id ;
#Attribute
#DatabaseField
String extension;
#Text
#DatabaseField
String pathBigImage;
//rest of the elements...
}

Categories