JAXB from Java to XML - java

My target is to get this xml marshalling Java objects.
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<ns2:cedolini xmlns:ns2="" data_produzione=""
codice_sistema_emittente="">
<cedolino>
<testata lingua="I">
<info>
<infoSoggetto></infoSoggetto>
<infoIndirizzo></infoIndirizzo>
<email></email>
</info>
<anagrafica cod="xxxxxxyyxyyxyyyx">
<cognome></cognome>
<nome></nome>
<dataNascita></dataNascita>
<via></via>
<civico></civico>
<cap></cap>
<citta_residenza></citta_residenza>
<provincia_residenza></provincia_residenza>
</anagrafica>
</testata>
</cedolino>
.
.
</ns2:cedolini>
My trouble is how to represent the list of object Cedolino.
<ns2:cedolini xmlns:ns2="" data_produzione=""
codice_sistema_emittente="">
<cedolino>
....
</cedolino>
<cedolino>
....
</cedolino>
</ns2:cedolini>
In my mind the solution to represent each Cedolino object is something like that.
#XmlRootElement()
public class Cedolino{
private Testata testata;
private Info info;
private Anagrafica anagrafica;
public get and set methods...
}

Convert your xml to Xsd ,
follow below link :
https://www.freeformatter.com/xsd-generator.html
Once you get the generated xsd, save that in your project,
now generate POJO using xsd.
GENERATING POJO USING xsd:
1.in eclipse goto file -> new-> Other-> JAXB classes from schema.
provide package name, where you want your pojo to be generated.

SimpleXml can do it. First some POJOs:
#XmlName("ns2:cedolini")
public class Cedolini {
#XmlName("cedolino")
public List<Cedolino> cedolinos;
}
public class Cedolino {
public Testata testata;
}
public class Testata {
#XmlAttribute
public String lingua;
public Info info;
public Anagrafica anagrafica;
}
public class Info {}
public class Anagrafica {
#XmlAttribute
public String cod;
}
Then serialize and print:
final SimpleXml simple = new SimpleXml();
final Cedolini i = simple.fromXml(xml, Cedolini.class);
System.out.println(i.cedolinos.get(0).testata.lingua + " : " + i.cedolinos.get(0).testata.anagrafica.cod);
This will print:
I : xxxxxxyyxyyxyyyx
SimpleXml is in maven central:
<dependency>
<groupId>com.github.codemonstur</groupId>
<artifactId>simplexml</artifactId>
<version>1.5.5</version>
</dependency>

Related

MOXy JAXB breaks on XmlIDREF to type that has an enum attribute

I have set up a minimal working example of the problem I have. These are the JAXB classes.
moxytest/A.java
package moxytest;
#XmlRootElement
public class A {
#XmlElement(name = "b")
public List<B> bs;
#XmlElement(name = "c")
public List<C> cs;
}
moxytest/B.java
package moxytest;
public class B {
#XmlAttribute
#XmlID
public String id;
#XmlAttribute
public EnumD md;
}
moxytest/C.java
package moxytest;
public class C {
#XmlAttribute
#XmlIDREF
public B b;
}
moxytest/EnumD.java
package moxytest;
#XmlEnum
public enum EnumD {
VALUE1, VALUE2, VALUE3
}
Example input:
<?xml version="1.0" encoding="UTF-8" ?>
<a>
<b id="b1" md="VALUE1"/>
<b id="b2" md="VALUE2"/>
<b id="b3" md="VALUE3"/>
<c b="b2"/>
<c b="b1"/>
<c b="b3"/>
</a>
So C elements are referencing B elements by id, and B elements have an Enum attribute.
This line of Java code
JAXBContext context = JAXBContext.newInstance(A.class);
Produces an exception with the following message:
The #XmlAttribute property b in type moxytest.C must reference a type that maps to text in XML. moxytest.B cannot be mapped to a text value.
I have been debugging and reading some lines of MOXy source code. That is how I was able to set up this minimal example. The JDK implementation works fine.
EDIT:
I am using EclipseLink 2.6.0 (thanks Santhosh Kumar Tekuri)
I tested your code with following maven dependency:
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>2.5.0</version>
</dependency>
i placed jaxb.properties in same package where model classes exist. this file contains:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
and it works fine. below is my unmarshalling code:
public static void main(String[] args) throws Exception{
JAXBContext context = JAXBContext.newInstance(A.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Object obj = unmarshaller.unmarshal(new File("input.xml"));
System.out.println(obj);
}
make sure you are using same moxy version I am using.

Problems with JAXB marshalling lists of non-annotated objects

I've got a bit of an issue with unmarshalling a list of closed objects using JAXB (closed in the sense that I cannot add JAXB annotation) . Basically, my XML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<document>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<!-- SNIP! -->
</rdf:RDF>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<!-- SNIP! -->
</rdf:RDF>
</document>
And my Document class is:
#XmlRootElement(name = "document", namespace = Namespace.DEFAULT_NAMESPACE)
#XmlAccessorType(XmlAccessType.FIELD)
public class Document {
#XmlJavaTypeAdapter(ModelAdapter.class)
#XmlElement(name = "RDF", namespace = Namespace.RDF_NAMESPACE)
private List<Model> models;
....
Where Model is a class from a framework that I cannot add JAXB annotations to, hence the adaptor.
The implementation of ModelAdapter is as follows:
public class ModelUnmarshalAdapter extends ModelAdapter<Object, Model> {
#Override
public Model unmarshal(final Object v) throws Exception {
// Turn incoming Node into a Model object
Model model = convert(v);
return model;
}
....
}
When I unmarshal the XML I'm finding ModelUnmarshalAdapter.unmarshal() is being called twice as expected (due to the 2 RDF elements in the XML), but the Document instance models property is always null. It's like it doesn't instantiate the necessary list instance.
Any ideas would be greatly appreceiated.
Thanks
Nick
After much trial and error it turns out the solution was to subclass the closed object concrete class (in my case ModelCom, which implements the Model interface) and add the #XmlJavaTypeAdapter to that
#XmlJavaTypeAdapter(ModelAdapter.class)
public class MyModel extends ModelCom {
public Model(Graph base) {
super(base);
}
public Model(Graph base, Personality<RDFNode> personality) {
super(base, personality);
}
}
The Document class is now simply
public class Document {
#XmlElement(name = "RDF", namespace = Namespace.RDF_NAMESPACE)
private List<MyModel> models;

JAXB-RI Marshalling generic list gives incorrect output

We have a complicated structure of classes that we are trying to marshal to an xml file using JAXB-RI. The marshalling seems to work correctly with Spring's jaxb2Marshaller but not with the jaxb-ri, which is what we are trying to use. (We're using Java 6 and jaxb-2.1.13)
This is an example of the output we currently see after marshalling with JAXB-RI:
<?xml version="1.0" encoding="UTF-8"?>
<specificCompanyList>
<org>com.ourcompany.etc.etc.TypeOfCompany#56cb0eed</org>
<org>com.ourcompany.etc.etc.TypeOfCompany#3125a57</org>
....
</specificCompanyList>
This is what we want to see:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<specificCompanyList>
<org id="123456" name=" COMPANY NAME 1"/>
<org id="098765" name=" COMPANY NAME 2"/>
....
</specificCompanyList>
Here is some info about our class structure. Apologies if it's confusing -- I want to lay everything out on the table. Class names and paths have been changed and shortened as well.
Class that becomes the root element:
#XmlRootElement(name="specificCompanyList")
public class SpecificCompanyLookup extends BaseCompanyLookup<TypeOfCompany> {
public SpecificCompanyLookup() {}
....
}
BaseCompanyLookup:
#XmlAccessorType(XmlAccessType.FIELD)
abstract class BaseCompanyLookup<T extends OrgNode> implements Lookup {
#XmlElement(name="org")
final Set<T> companyList = new TreeSet<T>(.....);
}
OrgNode:
#XmlAccessorType(XmlAccessType.FIELD)
classOrgNode extends BaseLookupItem {
}
BaseLookupItem:
#XmlAccessorType(XmlAccessType.FIELD)
public class BaseLookupItem {
#XmlAttribute(required = true)
protected String id;
#XmlAttribute(required = true)
protected String name;
....
}
A class that extends OrgNode:
class TypeOfCompany extends OrgNode {
....
}
So:
BaseLookupItem -> OrgNode -> TypeOfCompany
Does anyone know what is causing this bad output? How do we make the JAXB-RI marshaller generate the output that we need?
EDIT: We found the solution. This happened when we moved to WebLogic 12c, which has switched its JAXB default to the EclipseLink MOXy implementation. That implementation appears to have a bug for the case I described here. Following the instructions to switch to the Glassfish JAXB RI fixed this issue for us. Here are those instructions: http://docs.oracle.com/cd/E24329_01/web.1211/e24964/data_types.htm#CIHBHDGI
I confirmed this is in fact a bug in MOXy and have opened the following bug to track the issue https://bugs.eclipse.org/bugs/show_bug.cgi?id=410001
I also confirmed that adding the #XmlSeeAlso annotation like this would be a workaround for this case.
#XmlSeeAlso(TypeOfCompany.class)
public class SpecificCompanyLookup extends BaseCompanyLookup<TypeOfCompany> {
public SpecificCompanyLookup() {}
}

Marshalling null values with a custom type used with an xml adapter

I'm using a POJO object with XmlType for a custom XML adapter I built for marshaling a map of strings. I'm having issues however, with getting it to allow me to use null values properly. I was able to get it to work, but I'm not happy with the XML it is generating.
This is what I'm currently using that I would like to work, but as you can see in an sample XML result, it is not including the proper xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true" value
#XmlType(name="element")
public class RestMapElements {
#XmlAttribute(name="name")
public String key;
#XmlValue
public String value;
public RestMapElements(String key, String value) {
this.key = key;
this.value = value;
}
}
The resulting XML (slimmed to relevant data).
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
...
<element-list>
<item name="activated_date">2012-03-29 11:34:14.323</item>
<item name="some_null_value"/>
</element-list>
...
However, I was able to get it to work with this, I'm just not happy with the XML having to add an additional "value" tag inside of the item tag to get it to work. (side note, why is it naming it item instead of element like I tried to specify in the XmlType name declaration?)
#XmlType(name="element")
public class RestMapElements {
#XmlAttribute(name="name")
public String key;
#XmlElement(nillable = true)
public String value;
public RestMapElements(String key, String value) {
this.key = key;
this.value = value;
}
}
Again, the resulting XML (slimmed to relevant data).
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
...
<element-list>
<item name="activated_date"><value>2012-03-29 11:34:14.323</value></item>
<item name="some_null_value"><value xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/></item>
</element-list>
...
Really, I can use the second as it works to solve my issue. I'm just wanting to use this as a learning experience to see if JAXB using annotations will allow be to bend this to what I'm looking for without having to add that additional value tag underneath an item tag just so I can support null values. Right now, when it unmarshals in the first example, I end up getting empty strings instead of null. In the second example, I get the null value I was expecting.
FYI: I'm currently using Jersey 1.11
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
You could use MOXy's #XmlNullPolicy extension to map this use case:
RestMapElements
package forum10415075;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
#XmlType(name="element")
public class RestMapElements {
#XmlAttribute(name="name")
public String key;
#XmlValue
#XmlNullPolicy(nullRepresentationForXml=XmlMarshalNullRepresentation.XSI_NIL)
public String value;
}
Root
package forum10415075;
import java.util.*;
import javax.xml.bind.annotation.*;
#XmlRootElement
public class Root {
#XmlElementWrapper(name="element-list")
#XmlElement(name="item")
public List<RestMapElements> items = new ArrayList<RestMapElements>();
}
jaxb.properties
To use MOXy as your JAXB (JSR-222) provider you need to add a file called jaxb.properties in the same package as your domain model with the following content:
javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
package forum10415075;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum10415075/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
input.xml/Output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<element-list>
<item name="activated_date">2012-03-29 11:34:14.323</item>
<item name="some_null_value" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
</element-list>
</root>
Note
If you are using Jersey in GlassFish 3.1.2 MOXy or WebLogic 12.1.1 is already included:
http://blog.bdoughan.com/2012/02/glassfish-312-is-full-of-moxy.html
http://blog.bdoughan.com/2011/12/eclipselink-moxy-is-jaxb-provider-in.html
I see your problem. An item element with xsi:nil="true" will be generated only by setting the corresponding RestMapElements entry in your ArrayList (or whatever) to null, losing the attribute. I think there isn't much of a solution to this.
One option would be to use your marshalling from the beginning of your post and unmarshal using the following:
If you're doing something like this:
#XmlElementWrapper(name="element-list")
#XmlElement(name="item")
public ArrayList<RestMapElements> list;
You can use a XmlAdapter to check if the value is an empty String and set it to null if it is:
#XmlElementWrapper(name="element-list")
#XmlElement(name="item")
#XmlJavaTypeAdapter(ItemAdapter.class)
public ArrayList<RestMapElements> list;
And ItemAdapter:
public class ItemAdapter extends XmlAdapter<RestMapElements, RestMapElements> {
#Override
public RestMapElements unmarshal(RestMapElements v) throws Exception {
if (v.value.equals("")) v.value = null;
return v;
}
}
Although this is still inelegant imho.
If you want to generate the proper xsi:nil="true" item elements, this is obviously not what you want though.
Good luck.

xml representation in java class?

I'm trying to convert this XML to Java object and then updating key and value and then save it to XML.I can convert simple XML but this one has two attribute which is the same.
Can anybody help me to represent this xml in java class as Configuration.java?
XML
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="mode" value="1"/>
<add key="type" value="shs"/>
</appSettings>
</configuration>
Configuration.java
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Configuration {
String appSettings;
String add;
String key;
String value;
public String getAppSettings() { return appSettings; }
#XmlElement
public void setAppSettings(String appSettings) { this.appSettings = appSettings;}
public String getAdd() { return add; }
#XmlElement
public void setAdd(String add) { this.add = add; }
public String getKey() { return key; }
#XmlAttribute
public void setKey(String key) { this.key = key; }
public String getValue() { return value; }
#XmlAttribute
public void setValue(String value) { this.value = value; }
}
I suggest to:
specify the XSD
generate the JAXB classes using the following Maven plugin: http://java.net/projects/maven-jaxb2-plugin/pages/Home
Use JAXB if you want fine control over the XML to POJO creation. But you will have to specify the structure of your XML in an XSD first and let JAXB generate the Java classes for you.
Another way is to use XStream.
XStream xstream = new XStream();
Configuration config= (Configuration)xstream.fromXML(xml);
But you might have to update your Configuration class to use List for the add nodes as Kuldeep Jain said in his answer.
Edit: Take a look at the 2-minute XStream tutorial also - http://x-stream.github.io/tutorial.html
I think you will have to have a List for the follwing add nodes:
<add key="mode" value="1"/>
<add key="type" value="shs"/>
EDIT:
You may have a look at JAXB article for help.

Categories