I want to create xml from my object, but instead of xml nodes I'd like to create attribute i.e.
#XmlRootElement
class MyObject{
private String name;
private String age;
...getters/setters...
}
And I want my object to create this xml :
<MyObject name="something">
<age></age>
</MyObject>
How can I do this?
You can use the #XmlAttribute annotation to map to an XML attribute.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
class MyObject{
#XmlAttribute // Maps to an XML attribute
private String name;
private String age; // Maps to an XML element
...getters/setters...
}
Related
I have a String object with xml data in it .
I want that data in POJO , i tried using JAXB unmarshaller to convert but it always give me null values in the object attributes.
this is my code :
ResponseEntity<String> response = restTemplate.getForEntity("https://api.flickr.com/services/rest/?api_key=MY_API_KEY&method=flickr.photos.search&tags=nature", String.class);
String resp = response.getBody();
JAXBContext jaxBcontext = JAXBContext.newInstance(Resp.class);
Unmarshaller unmarshaller = jaxBcontext.createUnmarshaller();
Resp respObj = (Resp)unmarshaller.unmarshal(new StringReader(resp));
the value in String is :
<rsp stat="ok">
<photos page="1" pages="4226" perpage="100" total="422597">
<photo id="28534349567" owner="79805131#N08" secret="b8bd7fe7cb"
server="843" farm="1" title="Savoie S006." ispublic="1" isfriend="0"
isfamily="0"/>
<photo id="43355895332" owner="155237230#N05" secret="75fd48d040"
server="1769" farm="2" title="IMG_3139" ispublic="1" isfriend="0"
isfamily="0"/>
<photo id="41595746070" owner="125407841#N08" secret="1f216ab8b8"
server="1822" farm="2" title="" ispublic="1" isfriend="0" isfamily="0"/>
</photos>
</rsp>
the POJOS are :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "rsp")
public class Resp {
#XmlElement(name="stat")
private String stat;
#XmlElement(name="photos" , type = Photos.class)
private Photos photos;
public String getStat() {
return stat;
}
//constructors and getter setters
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "photos")
public class Photos {
#XmlElement(name="total")
private String total;
#XmlElement(name="page")
private String page;
#XmlElement(name="pages")
private String pages;
#XmlElement(name="perpage")
private String perpage;
#XmlElement(name="photo" , type=Photo.class)
private List<Photo> photoObject = new ArrayList<Photo>();
// constructors and getter setters.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "photo")
public class Photo {
#XmlElement(name="id")
private String id;
#XmlElement(name="isfamily")
private String isfamily;
#XmlElement(name="title")
private String title;
#XmlElement(name="ispublic")
private String ispublic;
#XmlElement(name="owner")
private String owner;
#XmlElement(name="secret")
private String secret;
#XmlElement(name="server")
private String server;
#XmlElement(name="isfriend")
private String isfriend;
// constructors and setter getter
the response i get is null values in all these objects.
Resp [stat=null, photos=Photos [total=null, page=null, pages=null,
perpage=null, photo=]]
the value in String which i get is absolutely correct , but when i try to map my data to a POJO it starts giving error.
Other approach I used it to get the data directly in the object , like I have mentioned in my other question , but it also have some issues in that.
RestTemplate returns data in String but not populate list nested objects
if anyone can help in either one of these that'd be helpful.
As #f1sh already already commented,
your problems are caused by several issues within your POJO classes
In your XML response you have
<rsp stat="ok">...</rsp> (i.e. statis an XML attribute)
instead of <rsp><stat>ok</stat>...</rsp> (statbeing an XML element).
Therefore, in your Resp class the statproperty needs to annotated with
#XmlAttribute instead of #XmlElement.
For the same reason, in your Photos class, all properties
except for the photoObjectproperty need to be annotated with
#XmlAttribute instead of #XmlElement.
For the same reason, in your Photo class all properties
need to be annotated with #XmlAttribute instead of #XmlElement.
Some more best practices to consider:
In your Photos and Photo classes you can remove the #XmlRootElement annotation
because theses are not root elements.
Only the Resp class is a root element and therefore needs #XmlRootElement.
In your Photos class you should rename the photoObject property to photoObjects
(with a plural s) because it is a list. This would make the code easier to understand.
I found the solution .
The annotations #XMLAttribute and #XmlElements needed to be put on setters .
Did not work for getters and declarations.
i am trying to use one class to map the response i get from an XML request.
But the xml response differs, depending own some settings. For example in a response i get the tag "owner" which is filled with the ID of the owner object. If i add a setting in my request i will get back the full owner data, like the firstname and lastname. Now i want to map the owner tag to either a String variable or a Class depending on the response.
Example :
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "domain")
public class Response {
#XmlElement
private String name;
#XmlElement(name = "owner")
private String ownerSimple;
#XmlElement(name = "owner")
private Owner ownerComplex;
}
#XmlRootElement(name = "ownerc")
public class OwnerC {
#XmlElement
int id;
#XmlElement
String fname;
#XmlElement
String lname;
}
XML to map :
<response>
<name>Foo</name>
<owner>1234</owner> <!-- in this case it's only a id -->
</response>
<response>
<name>Foo</name>
<owner> <!-- in this case it's the owner class -->
<id>1234</id>
<fname>Jon</fname>
<lname>Doe</lname>
</owner>
</response>
You can use #XmlAnyElement(lax=true) to handle this use case. This annotation allows you to unmarshall any XML to a Java object (DOM Node). In a second step, it is possible to unmarshall the Node to the required Object
Response
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "domain")
public class Response {
#XmlElement
private String name;
#XmlAnyElement(lax=true)
private Object owner;
private String ownerSimple;
#XmlTransient
private Owner ownerComplex;
Owner
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "owner")
public class Owner {
#XmlElement
int id;
#XmlElement
String fname;
#XmlElement
String lname;
Unmarshaller
//Unmarshaller. Step 1 - Decodes Response and set a DOM Node at Owner
//Important. Owner class must not be present in JAXB context, letting next step to decode the object properly.
//Owner variable at Response class is annotated with #XmlTransient
JAXBContext jaxbContext = JAXBContext.newInstance(Response.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
Response response = (Response) jaxbUnmarshaller.unmarshal(reader);
//Unmarshaller. Step 2. Convert Node to the suitable Object
//Considering both cases, simple-> String complex -> Owner Object.
String ownerSimple = ((Node)response.getOwner()).getFirstChild().getNodeValue();
if (ownerSimple != null){
response.setOwnerSimple(ownerSimple);
} else {
JAXBContext jaxbContextOwner = JAXBContext.newInstance(Owner.class);
Unmarshaller jaxbUnmarshallerOwner = jaxbContextOwner.createUnmarshaller();
Owner ownerComplex = (Owner) jaxbUnmarshallerOwner.unmarshal((Node)response.getOwner());
response.setOwnerComplex(ownerComplex);
}
//Marshaller to system.out. Your object is well mapped in both cases
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(rx, System.out);
I wish to have an XML structure like this:
<?xml version="1.0" encoding="UTF-8"?>
<MSG>
<CASE>
<Field1></Field1>
<Field2></Field2>
</CASE>
</MSG>
The problem is, with the #XmlElementWrapper, I need a collection of items but there will be only 1 case item. How can I have multiple root elements, for a single collection of elements? Preferably in a single class.
I want something like this, but it throws an exception.
#XmlRootElement( name="MSG")
public class XMLStructure {
#XmlElementWrapper(name="CASE")
#XmlElement(name = "Field1")
private String field1;
#XmlElementWrapper(name="CASE")
#XmlElement(name = "Field2")
private String field2;
}
In the EclipseLink MOXy implementation of JAXB (JSR-222) we have an #XmlPath extension that enables you to map this as:
#XmlRootElement( name="MSG")
#XmlAccessorType(XmlAccessType.FIELD)
public class XMLStructure {
#XmlPath("CASE/Field1/text()")
private String field1;
#XmlPath("CASE/Field2/text()")
private String field2;
}
For More Information
I have written more about the #XmlPath extension on my blog:
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
I need to map my XML snippet onto Java class using JAXB, but have a tricky case. I have the following XML:
<person>
<name part="first">Richard</name>
<name part="last">Brooks</name>
</person>
and need to map it onto the following class
public class Person {
private String firstName;
private String lastName;
}
Could you please help me to figure out JAXB annotations to make it possible?
You can do this with MOXy, see #XmlPath.
#XmlPath("name[#part='first']/text()")
private String firstName;
#XmlPath("name[#part='last']/text()")
private String lastName;
Related questions:
Using #XmlPath with jaxb/MOXy to map complex type
Here is one approach you could take, but would require you to create a separate class for Name:
#XmlRootElement
public class Person {
#XmlElement(name="name")
private List<Name> names;
...
}
public class Name {
#XmlAttribute
private String part; //would be set to "first" or "last"
#XmlValue
private String nameValue;
...
}
Its easier to explain with an example,
Sample XML:
<root>
<company>
<name>xyz</name>
<employees>
<employeeref>emp1</employeeref>
<employeeref>emp2</employeeref>
</employees>
</company>
<employee id="emp1">
<name>a</name>
<age>12</age> </employee>
<employee id="emp2">
<name>b</name>
<age>24</age> </employee>
<employee id="emp3">
<name>c</name>
<age>36</age>
</employee>
</root>
This would need Company.java and Employee.java.
My question is,
How do i bind the xml to java objects using Jaxb annotations?
You can use #XmlID in combination with #XmlIDREF
Employee
On the Employee class you need to annotate which field/property is going to be the "key" for the object. In JAXB this is done with the #XmlID annotation.
#XmlAccessorType(XmlAccessType.FIELD)
public class Employee {
#XmlAttribute
#XmlID
private String id;
}
Company
In the Company class we will indicate that we want to marshal instances of Employee as a reference to the real object. This is done using the #XmlIDREF annotation.
#XmlAccesorType(XmlAccessType.FIELD)
public class Company {
#XmlElementWrapper
#XmlElement(name="elementref")
#XmlIDREF
private List<Employee> employees;
}
Root
In order for #XmlIDREF to work the object must mapped somewhere else with an #XmlElement annotation. In this example this happes in the Root class.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Root {
private Company company;
#XmlElement(name="employee")
private List<Employee> employees;
}
For More Information
You can read more about #XmlID and #XmlIDREF on my blog:
http://blog.bdoughan.com/2010/10/jaxb-and-shared-references-xmlid-and.html
I think you need following class, here is sample, you can do it with other ways
Root One class for Root
| -- Company Company class
| |
| | employess(List) one more class for employess collection
|
|
employee (collection) one class for employee
EmployeeData
#XmlAccessorType(XmlAccessType.FIELD)
#XmlRootElement(name = "root")
public class EmployeeData {
#XmlElement
private Company company;
private List<Employee> employee;
// getter/setter
}
Company
#XmlAccessorType(XmlAccessType.FIELD)
public class Company {
#XmlElement(required = true)
private String name;
#XmlElement(required = true)
private Employees employees;
//...// getter/setter
}
Employee
#XmlAccessorType(XmlAccessType.FIELD)
public class Employee {
#XmlElement
private String name;
private int age;
#XmlAttribute(name = "id")
private String id;
///// getter/setter
}
Employees
#XmlAccessorType(XmlAccessType.FIELD)
public class Employees {
private List<String> employeeref;
// getter/setter
}
Java classes can be structured in such a way that they form a tree hierarchy as described in the XML file. Annotations are used in the Java classes to describe this structure.
Here is a list of some annotations used:
#XmlRootElement : Maps a class or an enum type to an XML element.
#XmlAttribute : Maps a JavaBean property to a XML attribute.
#XmlElement : Maps a JavaBean property to a XML element derived from property name
The Employee class can be like that:
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Employee {
private String id;
private String name;
private String age;
public String getId() {
return id;
}
#XmlAttribute
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
#XmlElement
public void setName(String name) {
this.name = name;
}
public String getAge() {
return age;
}
#XmlElement
public void setAge(String age) {
this.age = age;
}
}