I'm working with a xml file that is generated and used in a .NET application.
I need to deserialize this file in Java and chose to use JAXB.
However, after trying to create the matching class I figured out one major difference.
When having a
#XmlRootElement
public class SomeClass{
List<NestedClass> classes;
}
I get the following structure:
<SomeClass>
...
<NestedClasses>
...
</NestedClasses>
<NestedClasses>
...
</NestedClasses>
</SomeClass>
As oppesed to the required existing structure:
<SomeClass>
...
<NestedClasses>
<NestedClass>
...
</NestedClass>
<NestedClass>
...
</NestedClass>
</NestedClasses>
</SomeClass>
Is there is a way to get my required structure without adding a class that will only contain the list of the nested class?
You will need to have a class that wraps the collection. To get the desired mapping, you can use the #XmlElementWrapper annotation to specify that a grouping element should be used. Then you can use the #XmlElement annotation to specify the name of the element that represents the items in the collection:
#XmlRootElement
public class SomeClass{
#XmlElementWrapper
#XmlElement(name="NestedClass")
List<NestedClass> classes;
}
For More Information
http://blog.bdoughan.com/2010/09/jaxb-collection-properties.html
Related
In my project, I would like to achieve specific order of properties in XML. In java object is represented as:
public class Plan {
private List<Act> act;
private List<Leg> leg;
...
An output object should look similar to this one:
<plan>
<act x="-25000" y="0"/>
<leg mode="car">
...
</leg>
<act x="10000" y="0"/>
<leg mode="car">
...
</leg>
</plan>
Is JAXB able to set up specific order for such case where I need to put items in order:
act.get(0)
leg.get(0)
act.get(1)
leg.get(1)
...
..
.
I know JAXB is able to save specific order of parameters like firstly act, then all legs, using #XmlType (propOrder={"prop1","prop2",..."propN"}) but it is not the case of this project as the 3rd party application which reads this xml's read them in pairs and propOrder would print them one by another.
Ok, I approach the problem from a different side and I solved it... Previously I thought it was a sorting problem - in fact, it is a problem with Java POJO class construction and JAXB annotations.
The solution for that is to use
#XmlElements({
#XmlElement(name="leg", type=Leg.class),
#XmlElement(name="act", type=Act.class)
})
#XmlElementWrapper(name="plan")
public List<Plan> getPlan() {
return plan;
}
and then items must be put one by another.
more details can be found in this answer:
Marshalling a List of objects implementing a common interface, with JaxB
I'm trying to figure out the best way to unmarshal some data from a public API (meaning I have no control over how it is serialized into XML).
<Show>
<name>Buffy the Vampire Slayer</name>
<totalseasons>7</totalseasons>
<Episodelist>
<Season no="1">
<episode>...</episode>
<episode>...</episode>
<episode>...</episode>
<episode>...</episode>
</Season>
<Season no="2">...</Season>
<Season no="3">...</Season>
</Episodelist>
</Show>
Above is a sample of the XML returned from a ReSTful query. Ideally, I'd like to figure out how to do two things; 1) merge all the season lists into one list of episodes and 2) is it possible to access only child elements and ignore parent elements when unmarshalling XML (ex. Access EpisodeList only, ignoring Show)?
Thank you for any help! This is my first SO post (still fairly new to programming).
I ended up creating some "helper" classes to extract the data I needed. I wrote a getEpisodeList method in EpisodeListHelper which rolls all the episodes up into a single list.
EpisodeListHelper class
#XmlRootElement(name="Show")
#XmlAccessorType(XmlAccessType.FIELD)
public class EpisodeListHelper {
#XmlElementWrapper(name="Episodelist")
#XmlElement(name="Season")
private List<SeasonHelper> seasonList;
...
}
SeasonHelper class
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class SeasonHelper {
#XmlElement(name="episode")
private List<Episode> list;
...
}
I have a class like this:
public class revision{
long number;
String comment;
... getters and setters
}
and I want the xstream result to give be like this:
<revision comment="value of comment">
121556
</revision>
However, since number is field it forces me to write it in a <number> tag.
I used this to build the xml:
XStream xstream = new XStream(new DomDriver("UTF-8"));
xstream.useAttributeFor(Revision.class, "comment");
is there a possibility to not show the tag?
You need to register a ToAttributedValueConverter for the revision class. This converter lets you specify a single property of the class that should be mapped to the character content of the element, and all other properties are mapped to attributes on the element. The simplest way to do this is with annotations:
#XStreamConverter(value=ToAttributedValueConverter.class, strings={"number"})
public class revision {
// class body as before
}
and tell the XStream instance to read the annotations with
xstream.processAnnotations(revision.class);
With this converter in place you don't need the useAttributeFor call, as the converter will automatically use attributes for everything except the number.
If you don't want to use annotations then you can configure the converter with a method call on the XStream instance instead, you just have to extract the various helpers from xstream and pass them to the constructor explicitly (the annotation processor passes these things to the converter automatically if it requires them)
xstream.registerConverter(new ToAttributedValueConverter(
revision.class, xstream.getMapper(), xstream.getReflectionProvider(),
xstream.getConverterLookup(), "number"));
Say, I have two classes:
#XmlRootElement
class A {
#XmlElement
String propertyOfA;
#XmlElement
B b;
}
class B {
#XmlElement
String propertyOfB;
}
JAXB returns an XML formatted in the according way:
<a>
<propertyOfA>valueA</propertyOfA>
<b>
<propertyOfB>valueB</propertyOfB>
</b>
</a>
My question is how to flatten the hierarchy in the XML? So that I have:
<a>
<propertyOfA>valueA</propertyOfA>
<propertyOfB>valueB</propertyOfB>
</a>
Can this be done with annotations?
At the moment I am thinking to create a kind of wrapper class for A, that would have fields built the way I want to see them in the XML. Is there a better way?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
You could use MOXy's #XmlPath extension to map this use case:
import java.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
#XmlRootElement
class A {
#XmlElement
String propertyOfA;
#XmlPath(".")
B b;
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2010/09/xpath-based-mapping-geocode-example.html
http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
It's been a while for me, but let me give it a crack:
#XmlRootElement
class A {
#XmlElement
String propertyOfA;
#XmlElement(name="propertyOfB")
B b;
}
#XmlType(name="")
class B {
#XmlValue
String propertyOfB;
}
Edit: disclaimer- I havn't compiled or tried this. But I believe it's how you do it.
Take a look to that question and the solution proposed: Spring RESTful client: root tag exception
Very helpful to solve this kind of problem.
An alternative approach (with standard JAXB) would be using #XmlJavaTypeAdapter. This way you could adapt the object hierarchy with the drawback of having to write the code that translates the object hierarchy into the adapted new class.
In your example however it wouldn't work as you would have to adapt class A which is your root. If however the hierarchy was deeper and you needed to make the adaptation one level lower than the root, then there wouldn't be a problem. A suggestion that might be useful is to write the code in the adapted entity, making it like a delegate to the object hierarchy, rather than the adapter, which would then be very thin.
I am wondering if it is possible to have JAXB not to create Java object for XML elements that serve as wrappers. For example, for XML of the following structure
<root>
<wrapper>
<entity/>
</wrapper>
</root>
I do not want an object for <wrapper> to be created at all. So for a class like
class Root {
private Entity entity;
}
the <entity> element should be unmarshalled directly into the entity field.
Is it possible to achieve with JAXB?
Although it requires extra coding, the desired unmarshalling is accomplished in the following way using a transient wrapper object:
#XmlRootElement(name = "root")
public class Root {
private Entity entity;
static class Entity {
}
static class EntityWrapper {
#XmlElement(name = "entity")
private Entity entity;
public Entity getEntity() {
return entity;
}
}
#XmlElement(name = "wrapper")
private void setEntity(EntityWrapper entityWrapper) {
entity = entityWrapper.getEntity();
}
}
EclipseLink MOXy offers a JAXB 2.2 implementation with extensions. One of the extended capabilities is to use XPath to navigate through layers of the XML you don't want in you domain model.
If you look at:
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/MOXyExtensions
you will notice that the Customer's name is stored within but that the name is a String attribute of Customer. This is accomplished using:
#XmlPath("personal-info/name/text()")
public String getName() {
return name;
}
I hope this helps,
Doug
Worth mentioning, if the content is a list of <entity/> instead of a single instance:
<root>
<wrapper>
<entity/>
<entity/>
...
</wrapper>
</root>
then you can use the #XmlElementWrapper annotation:
#XmlRootElement(name = "root")
public class Root {
#XmlElementWrapper(name = "wrapper")
#XmlElement(name = "entity")
private List<Entity> entity;
static class Entity { }
}
The whole point of JAXB or other mapping systems is to map the elements and their hierarchy to classes. In your example, you seem to want JAXB to somehow know that it can marshal entity into wrapper/entity and vice-versa without actually creating the class used for the wrapper mapping and the connection between root and entity. Which, as presented, is roughly equivalent to asking how to connect a car engine to the wheels without a driveshaft.
So, unless I am missing the point, the answer is no - neither JAXB or any other mapping program can do this. You can avoid creating classes by using something that does mapping purely dynamically (see Groovy, GPath for an example), but that avoids creating all classes, not just skipping one intermediate level in a hierarchy.