<requests>
<request id="246">
<employee id="40350">Michael Daniels</employee>
<start>2012-10-20</start>
<end>2012-10-25</end>
<created>2012-10-11</created>
<status lastChanged="2012-10-24" lastChangedByUserId="2270">superceded</status>
<type id="4">Vacation</type>
<amount unit="hours">2</amount>
<notes>
<note from="employee">Having wisdom teeth removed.</note>
<note from="manager">Get well soon</note>
</notes>
</request>
<request id="248">
<employee id="40350">Michael Daniels</employee>
<start>2012-11-12</start>
<end>2012-11-15</end>
<created>2012-10-19</created>
<status lastChanged="2012-10-30" lastChangedByUserId="2270">superceded</status>
<type id="4">Vacation</type>
<amount unit="hours">2</amount>
<notes>
<note from="employee">My dog ate my homework so I can't come to work.</note>
</notes>
</request>
I am having a horrible time of figuring out how xstream wants me to set this up.... this is what I am currently doing:
class Holder
{
Requests requests;
#XStreamAlias("requests")
public static class Requests
{
List<Request> requests = new ArrayList<Request>();
}
#XStreamAlias("request")
public static class Request
{
int id;
Employee employee;
String start;
String end;
String created;
Status status;
Type type;
Amount amount;
Notes notes;
}
public static class Employee
{
int id;
String content;
}
public static class Status
{
String content;
String lastChanged;
int lastChangedByUserId;
}
public static class Type
{
int id;
String content;
}
public static class Amount
{
String unit;
int content;
}
public static class Notes
{
List<Note> notes = new ArrayList<Note>();
}
public static class Note
{
String from;
String content;
}
}
Coud someone please help me figure out how to set up the structure so that xstream will fill it in from the bove xml?
I think you need the structure of getter and setter in your static class just as public static class Employee, for "int id" and "String content".
Related
I try to unmarshal a xml file to custom classes via jaxb.
The (not changeable) xml file looks as follow:
<demo>
<customers>
<customer usrid="1" name="jane" />
<customer usrid="2" name="leia" />
<customer usrid="3" name="tobi" />
</customers>
<phonenumbers>
<phonenumber usrid="1">123-456-789</phonenumber>
<phonenumber usrid="2">987-654-321</phonenumber>
<phonenumber usrid="2">111-222-333</phonenumber>
</phonenumbers>
<mobilenumbers>
<mobilenumber usrid="3">666-666-666</mobilenumber>
</mobilenumbers>
</demo>
Java classes look something special:
public class Demo {
public List<Customer> customers;
}
public class Customer {
public String usrid;
public String name;
public List<Number> numbers;
}
public class Number {
public NumberType type;
public String value;
}
public enum NumberType {
phone, mobile
}
Is this possible with jaxb (e.g. adapter) or do i have to do a xslt transform first ?
Btw. using jaxb straightforward works fine (annotations omitted):
public class Demo {
public List<Customer> customers;
public List<Phonenumber> phonenumbers;
public List<Mobilenumbers> mobilenumbers;
}
public class Customer {
public String usrid;
public String name;
}
public class Phonenumber {
public String usrid;
public String value;
}
public class Mobilenumber {
public String usrid;
public String value;
}
I have an XML which looks like below
<Book>
<Name>Book1</Name>
<Cost>20$</Cost>
</Book>
I have used a Bean Class with properties name, cost and successfully unmarshaled the xml file contents to Book bean object.
Now I want to have multiple book objects in the same XML file like below.
<Books>
<Book>
...
</Book>
<Book>
...
</Book>
I know that I can create one more class with Name Books.java and have an arraylist of book objects annotated with #XmlElement tag and unmarshall it.
But, I don't want to waste one more public class for doing that.
Can anyone let me know if there is any other way of parsing that xml file with JaxB.
Thanks in advance.
Found the solution..
I can have a class like below. I can use List list; variable member within the same class Book.java instead of using one more public class Books.java.
#XmlRootElement(name = "Books")
#XmlAccessorType(XmlAccessType.FIELD)
public class BookBean {
private String name;
private String cost;
#XmlElement(name = "Books")
public List<BookBean> books;
public BookBean(){
}
public BookBean(String s1, String s2){
name=s1;
cost=s2;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCost() {
return cost;
}
public void setCost(String cost) {
this.cost = cost;
}
public List<BookBean> getBooks() {
return books;
}
public void setBooks(List<BookBean> books) {
this.books = books;
}
}
Let's say I'm trying to create an XML document out of an object. Is this possible using JAXB annotations on a single Food class, or do I need to create inner classes for Cost and Flavor?
I know I can use #XmlElement or #XmlAttribute to set up immediate children of my root element. However, I'm not sure if/how to create the <cost> and <Flavor> tags as I show here.
<Food>
<cost amt=13.5 unit=USD/>
<Flavor spicy=5>It tastes good</Flavor>
</Food>
#XmlRootElement("Food")
public class Food {
private float amount;
private String units;
private String flavorType;
private STring flavorDescription;
}
Add a new Java class Cost:
public class Cost
{
#XmlAttribute
double amt;
#XmlAttribute
String unit;
}
And exdend class Food
#XmlRootElement
public class Food {
private float amount;
private String units;
private String flavorType;
private String flavorDescription;
private Cost cost;
...
you could also use something like this for Flavor class
public class Flavor {
private long spicy;
private String shortDesc;
#XmlValue
public String getShortDesc() {
return shortDesc;
}
public void setShortDesc(String shortDesc) {
this.shortDesc = shortDesc;
}
#XmlAttribute
public Long getSpicy() {
return spicy;
}
public void setSpicy(long spicy) {
this.spicy= spicy;
}
}
I have the following xml
<MyPojo>
<name>Jason</name>
<age>25</age>
<meta>
<occupation>Engineer</occupation>
</meta>
</MyPojo>
I need to deserialize it to the following POJO:
public class MyPojo {
private String name;
private int age;
private String occupation;
}
The problem here is that occupation is wrapped within meta element
You need one more object:
public class MyPojo {
private String name;
private int age;
private Meta meta;
}
public class Meta{
private String occupation;
}
My idea is to replace occupation with an own class. Something like myMeta or whatever you want to call it(be aware in your case like the xml says: meta). This class should cotain the field occupation:
public class Meta
{
private String occupation;
}
After that you only have to add a new field of your new class e.g. myMeta to myPojo. Something like this:
public class MyPojo
{
private String name;
private int age;
private Meta meta;
}
this should avoid
that occupation is wrapped within meta element
Hope that helps!
In the below sample, the Data block inside A and the Data block inside B should be unmarshalled into different classes. Is this achievable using JAXB?
<Content>
<A>
<Data>
<Name></Name>
<Age></Age>
</Data>
</A>
<B>
<Data>
<MobilePhone></MobilePhone>
<WorkPhone></WorkPhone>
</Data>
</B>
</Content>
The Data inside A and the Data inside B represent different classes.The data inside A should be mapped to AData.class and the Data inside B should be mapped to BData.class.
Note: Marshalling is working fine. Any number of classes can have the same name tag. The generated xml contains the same tag for all those classes. In this case, AData and BData will both be written to XML as <Data> . But even the same marshalled xml cannot be unmarshalled again. I am hoping this can be solved by adding some additional annotations.
You just need to have the following:
#XmlAccessorType(XmlAccessType.FIELD)
public class A {
#XmlElement(name="Data")
private AData data;
}
#XmlAccessorType(XmlAccessType.FIELD)
public class B {
#XmlElement(name="Data")
private BData data;
}
#XmlRootElement(name="Content")
#XmlAccessorType(XmlAccessType.FIELD)
public class Content {
#XmlElement(name="A")
private A a;
#XmlElement(name="B")
private B b;
}
The solution that Blaise has posted will be a good way to tackle this if you know ahead of time the objects that Content will contain, such as here:
public class Content {
#XmlElement(name="A")
private A a;
#XmlElement(name="B")
private B b;
}
But another way you could do this is to have the data that could be contained in content be wrapped in a list of some supertype that A/B extend from, which results in XML that looks like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Content>
<myContent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="a">
<Data>
<Name>Joe Smith</Name>
<Age>25</Age>
</Data>
</myContent>
<myContent xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="b">
<Data>
<MobilePhone>555-234-5678</MobilePhone>
<WorkPhone>555-555-5555</WorkPhone>
</Data>
</myContent>
</Content>
You can get this by annotating your classes like so:
#XmlRootElement(name = "Content")
#XmlAccessorType(XmlAccessType.FIELD)
public class Content {
#XmlElement
List<SomeSuperType> myContent;
public Content() {
}
public List<SomeSuperType> getMyContent() { return this.myContent; }
public void setMyContent(List<SomeSuperType> myContent ) { this.myContent = myContent; }
}
// class for A
#XmlRootElement(name = "A")
#XmlAccessorType(XmlAccessType.FIELD)
public class A extends SomeSuperType {
#XmlElement(name="Data")
AData data;
public A() {
data = new AData();
}
public void setName(String name) {
data.name = name;
}
public void setAge(int age) {
data.age = age;
}
public String getName() { return data.name; }
public int getAge() { return data.age; }
}
class AData {
#XmlElement(name = "Name")
String name;
#XmlElement(name = "Age")
int age;
}
// class for B
#XmlRootElement(name = "B")
#XmlAccessorType(XmlAccessType.FIELD)
public class B extends SomeSuperType {
#XmlElement(name = "Data")
BData data;
public B() {
data = new BData();
}
public void setMobilePhone(String mobilePhone) { data.mobilePhone = mobilePhone; }
public void setWorkPhone(String workPhone) { data.workPhone = workPhone; }
public String getMobilePhone() { return data.mobilePhone; }
public String getWorkPhone() { return data.workPhone; }
}
class BData {
#XmlElement(name="MobilePhone")
String mobilePhone;
#XmlElement(name="WorkPhone")
String workPhone;
public BData() {
}
}