Is there a way to map the value of a node when the node also has inner nodes?
I'm currently using JAXB annotations, which work great for most cases. However, I've come across something I can't figure out how to process/create annotations for. I have the following XML:
<animals>
<animal>
cat
<age>5</age>
<color>red</color>
</animal>
</animals>
Is there a way I can just get "cat
" out of that XML without fetching "5
" or "red
"?
Here is what I have so far:
@XmlRootElement(name = "animals")
public class Animal {
@XmlElement(name = "animal")
String type;
}
But when I unmarshall this I just get an empty string.
Any help would be appreciated!
EDIT
Here is a full working example of what I'm trying to do:@XmlRootElement(name = "animals")
private static class Animals {
@XmlElement(name = "animals")
String animalType;
}
// This code is in "main"
final String animalsXml = "<animals><animal>cat<color>red</color><age>5</age></animal></animals>";
JAXBContext context = JAXBContext.newInstance(Animals.class);
Unmarshaller um = context.createUnmarshaller();
ByteArrayInputStream bais = new 开发者_开发知识库ByteArrayInputStream(animalsXml.getBytes("UTF-8"));
Animals animals = (Animals)um.unmarshal(bais);
boolean animalIsCat = animals.animalType == null ? false : animals.animalType.equalsIgnoreCase("cat");
assert animalIsCat;
// end code in main
Try something like this:
@XmlRootElement(name = "animals")
public class Animals {
@XmlElement(name = "animal")
List<Animal> animals;
}
public class Animal {
@XmlMixed
List<Object> content;
}
Now, the content
field of Animal
will contain a mix of String
and JAXBElement
objects. You'll need to examine them at runtime to extract the bits you want.
First of all, the xml structure should be coherent - put the type of the animal into the "type" tag:
<animals>
<animal>
<type>cat</type>
<age>5</age>
<color>red</color>
</animal>
<animal>
<type>dog</type>
<age>7</age>
<color>orange</color>
</animal>
</animals>
Then you have two options. 1. Building on your example, you need two classes: one for animals and one for animal, because by default JAXB maps every tag to a class. While you need a collection for "containing" the objects in java, xml doesn't and that's where the difference comes from. The corresponding annotations:
package sample;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="animals")
public class Animals
{
@XmlElement(name="animal")
public List<Animal> animals;
public static class Animal
{
public String type;
public String color;
public Integer age;
}
}
However, this solution is not the most elegant. If you simply want to skip the container class from the middle, you can use the @XmlElementWrapper annotation:
package sample;
import java.util.List;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name="MyDocument")
public class MyDocument
{
public String comment;
@XmlElementWrapper(name="animals")
@XmlElement(name="animal")
public List<Animal> animals;
public static class Animal
{
public String type;
public String color;
public Integer age;
}
}
The xml would be like that:
<MyDocument>
<animals>
<animal>
<type>cat</type>
<age>5</age>
<color>red</color>
</animal>
<animal>
<type>dog</type>
<age>7</age>
<color>orange</color>
</animal>
</animals>
</MyDocument>
You could use JAXB to unmarshal a StAX input and leverage a StreamFilter to eliminate the unwanted nodes:
- JAXB filtered parsing
精彩评论