I am working on a Scala project, and we want to use XML to initialize our objects with JAXB (not Spring). I have a hierarchy where more data members get added in the subclasses. A simple example would look something like this:
class Animal
{
string name
}
class Cat extends Animal
{
int numLives
}
class Dog extends Animal
{
bool hasSpots
}
I would like to be able to initialize a list of animals from an XML block that looks something like this:
<Animals>
<Cat>
<name>Garfield</name>
<numLives>9</numLives>
</Cat>
<Dog>
<name>Odie</name>
<hasSpots>false</hasSpots>
</Dog>
</Animals>
How would we setup the annotations in the classes to be able to handle this?
For this example you will want to make use of the @XmlElementRef
and @XmlRootElement
annotations. This corresponds to the XML schema concept of substitution groups. This will allow you to have a list of objects from an inheritance hierarchy differentiated by element.
Animals
This will serve as the root object for the domain model. It has a List
property annotated with @XmlElementRef
. This means it will match values based on the value of their @XmlRootElement
annotations.
package forum8356849;
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Animals")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Cat.class, Dog.class})
public class Animals {
@XmlElementRef
private List<Animal> animals;
}
Animal
package forum8356849;
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
class Animal
{
String name;
}
Cat
We will annotate the Cat
class with an @XmlRootElement
annotation. This is used in tandem with the @XmlElementRef
annotation on Animals
.
package forum8356849;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Cat")
class Cat extends Animal
{
int numLives;
}
Dog
We will also add an @XmlRootElement
annotation to the Dog
class.
package forum8356849;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="Dog")
class Dog extends Animal
{
boolean hasSpots;
}
Demo
You can use the following class to see that everything works as expected. input.xml
corresponds to the XML provided in your question.
package forum8356849;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Animals.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum8356849/input.xml");
Animals animals = (Animals) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(animals, System.out);
}
}
For More Inforation
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With