With the use of Spring RestTemplate, how can map following XML result to some Domain Object?
As a solution I have designed following Domain classes but I am wonder whether how can I map those contain values (ex: 100, 200, 300) to domain object property.
Thanks.
XML result
<counting>
<value id="1" name="Robin" date="2015-09-03">100</value>
<value id="2" name="Joy" date="2015-09-03">200</value>
<value id="3" name="Tan" date="2015-09-03">300</value>
<counting>
Domain Class
#XmlRootElement(name = "counting")
public class Count {
private Value value;
public Count() {}
// Getters and setters
}
#XmlRootElement(name = "value")
public class Value {
public Value() {}
private long id;
private String name;
private Date date;
// Getters and setters
}
I have solved the issue with following data model
#XmlRootElement(name = "counting")
public class Count {
private List<Value> value;
public Count() {}
// Getters and setters
#XmlElement
public List<Value> getValue() {
return value;
}
public void setValue(List<Value> value) {
return this.value = value;
}
}
#XmlAccessorType(XmlAccessorType.FIELD)
public class Value {
public Value() {}
#XmlAttribute
private long id;
#XmlAttribute
private String name;
#XmlAttribute
private String date;
#XmlValue
private String xmlValue;
// Getters and setters
}
Related
I don't quite understand how #XmlIDREF and #XmlID work together. By using XmlIDREF I only create a reference to the actual element. However what is the use case for XmlID.
I want to create a reference to the class Publication. Is it enough to annotate the publication List with #XmlIDREF?
public class Author {
private String id;
private String name;
private List<Publication> publications = new LinkedList<>();
public Author() {
super();
}
#XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
#XmlElement
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlIDREF
public List<Publication> getPublications() {
return publications;
}
I want to create a reference to the class Publication.
Is it enough to annotate the publication List with #XmlIDREF?
No, that's only one half of what you need.
You already have this:
With #XmlIDREF you mark the referencing side of the relation
(pointing from Author to Publication).
public class Author {
...
#XmlIDREF
#XmlElement(name = "publication")
public List<Publication> getPublications() {
return publications;
}
...
}
You also need to mark the referenced side (the Publication itself)
by annotating one of its properties with #XmlID, for example like this:
public class Publication {
...
#XmlID
#XmlElement
public String getId() {
return id;
}
...
}
Then you are able to process XML content like this example:
<root>
<publication>
<id>p-101</id>
<title>Death on the Nile</title>
</publication>
<publication>
<id>p-102</id>
<title>The murder of Roger Ackroyd</title>
</publication>
...
<author>
<id>a-42</id>
<name>Agatha Christie</name>
<publication>p-101</publication>
<publication>p-102</publication>
</author>
...
</root>
You see, the XML references (like <publication>p-101</publication>)
are mapped to Java object references (in List<Publication> publications).
I want the Country class to store the "ISO_3166-1_Alpha-2_Code" code. The code currently gets back the "ISO_3166-1_Numeric-3_Code" code. Can't figure out how to tweak the Country class to get the specific attribute I want.
XML:
<?xml version='1.0' encoding='UTF-8'?>
<wd:Message_Event_Configuration">
<wd:Message_Event_Configuration_Data>
<wd:Country_Reference wd:Descriptor="Saint Martin">
<wd:ID wd:type="WID">66b7082a21e510000961bb6d82b5002a</wd:ID>
<wd:ID wd:type="ISO_3166-1_Alpha-2_Code">MF</wd:ID>
<wd:ID wd:type="ISO_3166-1_Alpha-3_Code">MAF</wd:ID>
<wd:ID wd:type="ISO_3166-1_Numeric-3_Code">663</wd:ID>
</wd:Country_Reference>
<wd:Country_Reference wd:Descriptor="Saint Barthelemy">
<wd:ID wd:type="WID">881527f6cec910000ba81e8dccf61127</wd:ID>
<wd:ID wd:type="ISO_3166-1_Alpha-2_Code">BL</wd:ID>
<wd:ID wd:type="ISO_3166-1_Alpha-3_Code">BLM</wd:ID>
<wd:ID wd:type="ISO_3166-1_Numeric-3_Code">652</wd:ID>
</wd:Country_Reference>
</wd:Message_Event_Configuration_Data>
</wd:Message_Event_Configuration>
Country List:
#XmlRootElement(name = "Message_Event_Configuration")
#XmlAccessorType(XmlAccessType.FIELD)
public class Countries {
#XmlElementWrapper(name = "Message_Event_Configuration_Data")
#XmlElement(name = "Country_Reference")
private List<Country> countries = new ArrayList<Country>();
public List<Country> getCountries() {
return countries;
}
public void setCountries(List<Country> countries) {
this.countries = countries;
}
}
Country:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "Country_Reference")
public class Country {
#XmlElement(name = "ID")
private String isoCode;
public Country() {
}
public Country(String isoCode) {
this.isoCode = isoCode;
}
#XmlAttribute(name = "ISO_3166-1_Alpha-2_Code")
public String getISOCode() {
return isoCode;
}
public void setISOCode(String isoCode) {
this.isoCode = isoCode;
}
}
The <Country_Reference> XML element contains the ISO codes in a rather
sophisticated way within several <wd:ID> XML elements.
It is therefore much too simple to model them as a Java String property.
Instead, you need to model the Java-structure with more similarity to the XML-structure.
The sequence of XML elements <wd:ID> can be modeled by a property List<ID> idList
which needs to be annotated by#XmlElement(name="ID") .
The XML attribute wd:Descriptor="...." can be modeled by a property String descriptor
which needs to be annotated by #XmlAttribute(name="Descriptor").
For your convenience you can add an all-arguments-constructor and some methods for getting
the WID and ISO codes from the List<ID>.
#XmlAccessorType(XmlAccessType.FIELD)
public class Country {
#XmlAttribute(name = "Descriptor")
private String descriptor;
#XmlElement(name = "ID")
private List<ID> idList;
public Country() {
}
public Country(String descriptor, String wid, String isoAlpha2Code, String isoAlpha3Code, String isoNumeric3Code) {
this.descriptor = descriptor;
idList = new ArrayList<>();
idList.add(new ID("WID", wid));
idList.add(new ID("ISO_3166-1_Alpha-2_Code", isoAlpha2Code));
idList.add(new ID("ISO_3166-1_Alpha-3_Code", isoAlpha3Code));
idList.add(new ID("ISO_3166-1_Numeric-3_Code", isoNumeric3Code));
}
public String getWid() {
return getIdByType("WID");
}
public String getIsoAlpha2Code() {
return getIdByType("ISO_3166-1_Alpha-2_Code");
}
public String getIsoAlpha3Code() {
return getIdByType("ISO_3166-1_Alpha-3_Code");
}
public String getIsoNumeric3Code() {
return getIdByType("ISO_3166-1_Numeric-3_Code");
}
private String getIdByType(String idType) {
for (ID id : idList) {
if (id.getType().equals(idType))
return id.getValue();
}
return null;
}
}
The XML elements <wd:ID> are quite complex. Therefore we need a separate POJO class for modeling them.
Let's call the class ID.
The XML text between <wd:ID ..> and </wd:ID> is modeled by the property String value
which needs to be annotated by #XmlValue.
The XML attribute wd:type="..." is modeled by the property String type
which needs to be annotated by #XmlAttribute.
For convenient use by the class Country above, an all-arguments-constructor is added.
#XmlAccessorType(XmlAccessType.FIELD)
public class ID {
#XmlAttribute
private String type;
#XmlValue
private String value;
public ID() {
}
public ID(String type, String value) {
this.type = type;
this.value = value;
}
// public getters and setters (omitted here fro brevity)
}
The screenshot below (taken from within the debugger) visualizes the Java structure
and confirms that the unmarshalling of your XML example works correctly:
I need to marshall a java class to get a xml, but i don't know how to delete a tag inside the one generated.
I have a class with an object list with this form
#XmlRootElement(name = "Element")
public class Element {
private List<Foo> foos;
#XmlElementWrapper("fooList")
public List<Foo> getfoos() {
return foos;
}
public void setFoos(List<Foo> foos) {
this.foos = foos;
}
}
And the class Foo of the list is lie this:
#XmlRootElement
public class Foo {
private String id;
private String code;
#XmlElement
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#XmlElement
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
}
When marshalling to get xml I get this:
<Element>
<fooList>
<foos>
<string1>asd</string1>
<string2>qwe</string2>
</foos>
<foos>
<string1>poi</string1>
<string2>lkj</string2>
</foos>
</fooList>
</Element>
But I want to get it without the tag foos, like this:
<Element>
<fooList>
<string1>asd</string1>
<string2>qwe</string2>
<string1>poi</string1>
<string2>lkj</string2>
</fooList>
</Element>
Can anyone help me?
Thanks a lot!!
You could do something like this:
#XmlRootElement(name = "Element")
#XmlAccessorType(XmlAccessType.FIELD)
public class Element {
#XmlElementWrapper(name = "fooList")
#XmlElements({
#XmlElement(name = "id", type = Id.class),
#XmlElement(name = "code", type = Code.class),
})
private List<FooItem> foos;
public List<FooItem> getfoos() {
return foos;
}
public void setFoos(List<FooItem> foos) {
this.foos = foos;
}
}
and then Id and Code classes look similar:
public class Id implements FooItem {
#XmlValue
private String id;
public Id() {}
public Id(String id) {
this.id = id;
}
}
They are bounded by an interface that doesn't do much:
public interface FooItem { }
This structure will allow you to marshal into xml as the one you specified you need.
The challenge with the class structure you had is that class Foo had 2 fields and #XmlValue can be applied only to one field per class. So having 2 fields "forces" them to stand for #XmlElement and they in turn have to be children of an xml element. This is why you had the "intermediate" foo elements in your xml for each Foo instance in your List.
I'm new in dealing with XML in Java, but one of services I use returns it as result. Until now, I've dealt with mapping XML into POJO, using #XmlRootElement-like annotations. But now I have absolutely no idea to do with this document:
<?xml version="1.0" encoding="windows-1251"?>
<response>
<status>
<code>0</code>
</status>
<result>
<limit>2</limit>
...
<data>
<row0>
<ID>85427</ID>
<name>Default</name>
<siteID>40628</siteID>
... some elements
</row0>
</data>
</result>
</response>
Until now, I used these classes to bind XML (except 'data' node) into POJO:
#XmlRootElement(name="response")
public class Response {
private Status status;
private String result;
public Status getStatus() {
return status;
}
#XmlElement(name = "status")
public void setStatus(Status status) {
this.status = status;
}
public String getResult() {
return result;
}
#XmlElement(name ="result")
public void setResult(String result) {
this.result = result;
}
}
#XmlRootElement(name = "status")
public class Status {
private String ID;
private String code;
private String error;
public String getID() {
return ID;
}
#XmlElement(name = "ID")
public void setID(String ID) {
this.ID = ID;
}
public String getCode() {
return code;
}
#XmlElement(name = "code")
public void setCode(String code) {
this.code = code;
}
public String getError() {
return error;
}
#XmlElement(name = "error")
public void setError(String error) {
this.error = error;
}
}
But now I need to bind content as collection of elements. I've looked for examples, and everywhere people use specific tag to define root element for collection's item, but in this document, root tags will be as <row0>, <row1> etc.
I use Jackson, which, if I understand correctly, uses JAXB annotations to define XML to POJO bind rules. So could this deal be solved this way, or I have to manipulate this document in DOM-style?
You can solve your problem by using something like this :
Create your Row class that represents your <row0>,<row1> etc... and map it with JAXB like you would do it normally.
Then create a class that extends XmlAdapter<List<Row>,List<Element>> and define the abstracts methods marshall and unmarshall.
Here is some Javadoc to help you :
XmlAdapter : http://docs.oracle.com/javaee/5/api/javax/xml/bind/annotation/adapters/XmlAdapter.html
Element : http://docs.oracle.com/javase/1.5.0/docs/api/org/w3c/dom/Element.html
Then create a Data class :
public class Data{
private List<Row> rows;
public List<Row> getRows() {
return rows;
}
#XmlAnyElement
#XmlJavaTypeAdapter(MyRowsAdapter.class)
public void setRows(List<Row> result) {
this.rows = rows;
}
}
Then you can add this mapping to your Response class :
private Data data;
public Data getData() {
return data;
}
#XmlElement(name="data")
public void setData(Data data) {
this.data = data;
}
Note that for this solution to work, your <data> element must only contains elements like your Row.
Also, you cannot use #XmlElementWrapper instead of using a Data class because of a bug in JAXB which make incompatible #XmlElementWrapper and #XmlJavaTypeAdapter : https://java.net/jira/browse/JAXB-787
Given this XML:
<response>
<detail Id="123" Length="10" Width="20" Height="30" />
</response>
This is what I have now, but it is not working (I'm getting empty result):
#XmlRootElement(name="response")
public class MyResponse {
List<ResponseDetail> response;
//+getters +setters +constructor
}
public class MyResponseDetail {
Integer Id;
Integer Length;
Integer Width;
Integer Height;
//+getters +setters
}
I'm making a call to a remote service using RestOperations and I want to parse the <detail ..> element. I've tried passing both MyResponse and MyResponseDetail classes to RestOperations but the result is always empty.
What should my object structure look like to match that XML?
You need to annotate your classes like that:
#XmlRootElement
public class Response {
private List<Detail> detail;
public void setDetail(List<Detail> detail) {
this.detail = detail;
}
public List<Detail> getDetail() {
return detail;
}
}
public class Detail {
private String id;
/* add other attributes here */
#XmlAttribute(name = "Id")
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}