开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜