xml representation in java class? - java

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.

Related

JAXB from Java to XML

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>

JAXB Unmarshal a list of objects

I have the following XML that I am trying to unmarshal:
<ListOfYear>
<Requests/>
<Payload>
<Year>
<Value>2013</Value>
</Year>
<Year>
<Value>2012</Value>
</Year>
<Year>
<Value>2011</Value>
</Year>
<Year>
<Value>2010</Value>
</Year>
<Year>
<Value>2009</Value>
</Year>
<Year>
<Value>2008</Value>
</Year>
</Payload>
</ListOfYear>
My java class looks like this:
#XmlRootElement(name = "ListOfYear")
public class YearOutput {
#XmlElementWrapper(name = "Payload")
#XmlElement(name = "Year")
private ArrayList<Year> Payload;
public ArrayList<Year> getPayload() {
return Payload;
}
public void setPayload(ArrayList<Year> payload) {
Payload = payload;
}
}
Payload should contain a list of year objects:
#XmlRootElement(name = "Year")
#XmlAccessorType(XmlAccessType.FIELD).
public class Year {
#XmlElement(name = "Value")
int Value;
public int getValue() {
return Value;
}
public void setValue(int value) {
Value = value;
}
}
I am unmarshaling the XML with the following code:
String r = response.getEntity(String.class);
JAXBContext jaxbContext = JAXBContext.newInstance(YearOutput.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
YearOutput output = (YearOutput) unmarshaller.unmarshal(new StringReader(r));
I get an output object back just fine, the payload object is always null. I have tried several different approaches with my XML annotation and have not been able to get anything to work. Any help would be much appreciated.
EDIT
I thought the name space was inconsequential so I didn't post that part of the code. But #Blaise Doughan suggested I marshal my model and it appears my namespace may be causing an issue...
Here is the full XML that I need:
<ListOfYear xmlns="http://something.com/">
<Requests/>
<Payload>
<Year>
<Value>2013</Value>
</Year>
<Year>
<Value>2012</Value>
</Year>
<Year>
<Value>2011</Value>
</Year>
<Year>
<Value>2010</Value>
</Year>
<Year>
<Value>2009</Value>
</Year>
<Year>
<Value>2008</Value>
</Year>
</Payload>
</ListOfYear>
Here is my full model:
#XmlRootElement(name = "ListOfYear", namespace = "http://something.com/")
public class YearOutput {
#XmlElementWrapper(name = "Payload")
#XmlElement(name = "Year")
private ArrayList<Year> Payload;
public ArrayList<Year> getPayload() {
return Payload;
}
public void setPayload(ArrayList<Year> payload) {
Payload = payload;
}
}
Now when I marshal my model I am getting:
<?xml version="1.0" encoding="UTF-8"?>
<ns2:ListOfYear xmlns:ns2="https://something.com/">
<Payload>
<Year>
<Value>2008</Value>
</Year>
</Payload>
</ns2:ListOfYear>
So what am I doing wrong with my namespace?
EDIT
After adding package-info.java everything works perfect!
#XmlSchema(
namespace = "https://something.com/",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Your annotations need to go on the property (get or set method) instead of the field. If you wish to have them on the field (instance variable), the you need to annotate your class with #XmlAccessorType(XmlAccessType.FIELD), like you have on your Year class.
http://blog.bdoughan.com/2011/06/using-jaxbs-xmlaccessortype-to.html
UPDATE
Instead of specifying the namespace on #XmlRootElement you will need to leverage a package level #XmlSchema annotation (on a class called package-info) to match the namespace qualification.
http://blog.bdoughan.com/2010/08/jaxb-namespaces.html
Try adding a / to the ending Payload tag.
A it's already mentioned, the XML file should contain
</Payload>
instead of
<Payload>
in the last but one line
#XmlElement should be above attribute but not getter in Year class:
#XmlElement int Value;
The element name in XmlElement annotation on getValue is missing. JAXB default behavior is that getValue means 'value' element, not 'Value'. Add the annotation #XmlElement(name="Value")
Fix it as in your other code
#XmlRootElement(name = "Year")
public static Year {
...
#XmlElement(name="Value")
public int getValue() {
return Value;
}
...
}
If you also marshal I recommend to add #XmlAccessorType(XmlAccessType.NONE) to the classes to prevent adding both 'value' and 'Value' elements.
See full working code at package 'wicketstuff/enteam/wicket/examples14/mixed' on
https://repo.twinstone.org/projects/WISTF/repos/wicket-examples-1.4/browse/
Also a test that log into console your XML and parse it back is provided in 'YearOutputTest'

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.

Jaxb generated xml - problem with root element prefix

I am trying to generate xml using jaxb. I created xsd and generated java classes.
But when I generate xml, I am geeting prefix ns2 to the root tag, which I don't want.
ex: I want root tag to be
<report>
<id>rep 1</id>
</report>
, But getting as
<ns2:report>
....
</ns2:report>
In the generated java class, I gave annotation as #XmlRootElement(name="report",namespace="urn:report")
Can some one pls help
If this is your class:
package example;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="report",namespace="urn:report")
public class Root {
private String id;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Then it makes sense that there is a prefix on the root element, because you have specified that the "root" element is namespace qualified and the "id" element is not.
<ns2:report xmlns:ns2="urn:report">
<id>123</id>
</ns2:report>
If you add a package-info class to your model, you can leverate the #XmlSchema annotation:
#XmlSchema(
namespace = "urn:report",
elementFormDefault = XmlNsForm.QUALIFIED)
package example;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Then the JAXB implementation may choose to leverage the default namespace, but note now all of the elements are namespace qualified which may or may not match your XML schema:
<report xmlns="urn:report">
<id>123</id>
</report>
For more information on JAXB and namespaces see:
http://bdoughan.blogspot.com/2010/08/jaxb-namespaces.html
Take a look at this answer. It describes how to use a SAX Filter to remove any namespace.
The blog entry Customizing JAXB shows the alternatives provided by implementing a PreferredMapper . Unfortunately it explains, that is not possible to fully suppress namespaces.
Use this attribute in your root element of your schema: elementFormDefault="qualified"
So for instance:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
Somehow the accepted answer did not work for me. I got success when I found solutions in some related stockOverflow questions involving DelegatingXMLStreamWriter from cxf and a filter, NoNamesWriter. The implementation I used with NoNamesWriter:
public class NoNamesWriter extends DelegatingXMLStreamWriter
{
#Override
public void writeStartElement(String prefix, String local, String uri) throws XMLStreamException {
delegate.writeStartElement("", local, uri);
}
public static XMLStreamWriter filter(FileOutputStream fileOutputStream) throws XMLStreamException {
return new NoNamesWriter(XMLOutputFactory.newInstance().createXMLStreamWriter(fileOutputStream));
}
public NoNamesWriter(XMLStreamWriter writer) {
super(writer);
}
}
Invoke the same as described here, like:
xmlmarshaller.marshal(xc, NoNamesWriter.filter(new FileOutputStream(outfile, false));

Why are names returned with # in JSON using Jersey

I am using the JAXB that is part of the Jersey JAX-RS. When I request JSON for my output type, all my attribute names start with an asterisk like this,
This object;
package com.ups.crd.data.objects;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlType;
#XmlType
public class ResponseDetails {
#XmlAttribute public String ReturnCode = "";
#XmlAttribute public String StatusMessage = "";
#XmlAttribute public String TransactionDate ="";
}
becomes this,
{"ResponseDetails":{"#transactionDate":"07-12-2010",
"#statusMessage":"Successful","#returnCode":"0"}
So, why are there # in the name?
Any properties mapped with #XmlAttribute will be prefixed with '#' in JSON. If you want to remove it simply annotated your property with #XmlElement.
Presumably this is to avoid potential name conflicts:
#XmlAttribute(name="foo") public String prop1; // maps to #foo in JSON
#XmlElement(name="foo") public String prop2; // maps to foo in JSON
If you are marshalling to both XML and JSON, and you don't need it as an attribute in the XML version then suggestion to use #XmlElement is the best way to go.
However, if it needs to be an attribute (rather than an element) in the XML version, you do have a fairly easy alternative.
You can easily setup a JSONConfiguration that turns off the insertion of the "#".
It would look something like this:
#Provider
public class JAXBContextResolver implements ContextResolver<JAXBContext> {
private JAXBContext context;
public JAXBContextResolver() throws Exception {
this.context= new JSONJAXBContext(
JSONConfiguration
.mapped()
.attributeAsElement("StatusMessage",...)
.build(),
ResponseDetails.class);
}
#Override
public JAXBContext getContext(Class<?> objectType) {
return context;
}
}
There are also some other alternatives document here:
http://jersey.java.net/nonav/documentation/latest/json.html
You have to set JSON_ATTRIBUTE_PREFIX in your JAXBContext configuration to "" which by default is "#":
properties.put(JAXBContextProperties.JSON_ATTRIBUTE_PREFIX, "");

Categories