在使用jaxb2时,如何根据type属性构造xml元素?

时间:2012-05-15 06:16:57

标签: java xml jaxb2

我正在使用java jaxb2.0xml marshallingunmarshalling 我遇到了这样的问题。
示例xml类似于* (fruit.xml) *:

<fruitPacks>
  <fruit name="apple1" type="apple" isApple="true"/>
  <fruit name="banana1" type="banana" isBanana="true"/>
  <fruit name="apple2" type="apple" isApple="true"/>
</fruitPacks>

和这样的java类:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "fruitPacks")
@XmlRootElement
public class FruitPacks
{
   @XmlElement(name = "fruit")
   private List<Fruit> fruits
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "fruit")
@XmlSeeAlso({ Apple.class, Banana.class })
public class Fruit{
 @XmlAttribute
 private String name;
 @XmlAttribute
 private String type;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "apple")
public class Apple extends Fruit{
  @XmlAttribute
  private boolean isApple = true;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "banana")
public class Banana extends Fruit{
  @XmlAttribute
  private boolean isBanana = true;
}

和unmarshal代码是:

public class JAXBTest {

public static void main(String [] args) throws Exception{
    JAXBContext jc = JAXBContext.newInstance(FruitPacks.class,Fruit.class,Apple.class, Banana.class);

    Unmarshaller unmarshaller = jc.createUnmarshaller();
    Object obj = unmarshaller.unmarshal(new File("fruit.xml"));
    System.out.println(obj);
}   
}

所以我想做的是:
当解组xml时,水果的构造将根据类型属性自动完成子类(Apple,Banana)。
我该怎么做?

2 个答案:

答案 0 :(得分:2)

您需要确保JAXBContext知道子类。一种方法是使用@XmlSeeAlso注释,请参阅下面的示例:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "fruit")
@XmlSeeAlso({Apple.class, Banana.class})
public class Fruit{
 @XmlAttribute
 private String name;
 @XmlAttribute
 private String type;
}

了解更多信息


<强>更新

我刚刚意识到您使用的是type属性,而不是标准xsi:type属性。使用任何JAXB实现,您可以利用XmlAdapter

映射此用例

如果您正在使用EclipseLink JAXB(MOXy),那么您可以利用@XmlDescriminatorNode / @XmlDescriminatorValue扩展名:

答案 1 :(得分:0)

@Gang尝试使用递归代码并在标记XML中使用id属性。 :)