@XmlElements标有@XmlJavaTypeAdapters?

时间:2011-05-21 22:40:27

标签: java xml xml-serialization jaxb jaxb2

我有这种情况

@XmlType(name ="", propOrder={"value"})
@XmlRootElement(name = "compound")
public class Compound extends Value {
  @XmlElements({
  @XmlElement(name="simple", type=Simple.class),
  @XmlElement(name="compound", type=Compound.class)
  })
  protected List<Value> value;
  // ...
}

因此,化合物是简单和/或化合物的列表。两者都从定义为

的Value扩展
public abstract class Value implements Serializable {}

Simple是一个标有适配器的类,用于编组/解组简单字符串

@XmlJavaTypeAdapter(SimpleAdapter.class)
public class Simple extends Value {
  private java.lang.String simple;
  // ...
}

化合物不需要适配器。

问题在于,如果我使用简单'原样',它正确编组/解组

<simple>my.text.here</simple>

但如果我在化合物中使用它,它会输出类似

的内容
<compound>
  //...
  <simple>
    <value>my.text.here</value>
  </simple>
  //...
</compound>

我只是想知道为什么......我会错过什么吗?我怎样才能删除那个“价值”? 在我看来,根本没有使用适配器,是否可以在@XmlElements内标记的类型中使用适配器?

修改

经过几次测试后,我发现问题可能在于我如何处理Simple实例。所以我简化了我的初步问题:

给出像

这样的简单类
@XmlRootElement("simple")
public class Simple {
  private java.lang.String innerText;
  // getters/setters
}

如何获得像

这样的编组输出
<simple>
  my.inner.text.here
</simple>

而不是

<simple>
  <value>my.inner.text.here</value>
</simple>

2 个答案:

答案 0 :(得分:2)

听起来你希望private java.lang.String innerText;成为Simple类的@XmlValue。尝试使用@XmlValue标记在Simple中注释String:

@XmlRootElement("simple")
public class Simple {
  @XmlValue
  private java.lang.String innerText;
  //getters/setters
}

或者如果您在getter方法上使用注释(我假设根据您在问题中的XML输出将@XmlElement标记更改为@XmlValue标记:

@XmlValue
public java.lang.String getInnerText() {
  return innerText;
}

当我这样做时,我会在您编辑的问题中获得您正在寻找的输出。

答案 1 :(得分:0)

answer given by bamana是正确的,但您看到的异常是由于JAXB参考实现中的错误。此错误也存在于EclipseLink JAXB (MOXy)中,但已在2.3.0流中修复,可以在此处获得一个夜间下载:

作为一种解决方法,您可以使用原始问题中的XmlAdapter方法:

<强> SimpleAdapter

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class SimpleAdapter extends XmlAdapter<String, Simple> {

    @Override
    public Simple unmarshal(String v) throws Exception {
        Simple simple = new Simple();
        simple.setSimple(v);
        return simple;
    }

    @Override
    public String marshal(Simple v) throws Exception {
        return v.getSimple();
    }

}

<强>简单

import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;

@XmlJavaTypeAdapter(SimpleAdapter.class)
public class Simple extends Value {
    private java.lang.String simple;

    public java.lang.String getSimple() {
        return simple;
    }

    public void setSimple(java.lang.String simple) {
        this.simple = simple;
    }

}

<强>化合物

import java.util.List;

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "compound")
@XmlAccessorType(XmlAccessType.FIELD)
public class Compound extends Value {
    @XmlElements({ @XmlElement(name = "simple", type = Simple.class),
            @XmlElement(name = "compound", type = Compound.class) })
    protected List<Value> value;

    public List<Value> getValue() {
        return value;
    }

    public void setValue(List<Value> value) {
        this.value = value;
    }

}

<强>值

import java.io.Serializable;

public abstract class Value implements Serializable {}

<强>演示

import java.io.File;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Compound.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Compound compound = (Compound) unmarshaller.unmarshal(new File("input.xml"));
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(compound, System.out);
    }

}

<强> input.xml中

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<compound>
    <simple>
        <simple>FOO</simple>
    </simple>
    <compound/>
</compound>