假设我想使用XML表示算术表达式,那么我会有以下内容:
@XmlRootElement
@XmlTransient
@XmlSeeAlso({Num.class, Add.class})
public abstract class Evaluable
{
public abstract int eval();
}
@XmlRootElement
@XmlType(name = "num")
public class Num extends Evaluable
{
@XmlValue
private int val;
@Override
public int eval()
{
return val;
}
}
@XmlRootElement
@XmlType
public class Add extends Evaluable
{
@XmlAnyElement
private ArrayList<Evaluable> elems;
@Override
public int eval()
{
int sum = 0;
for (Evaluable elem : elems)
{
sum += elem.eval();
}
return sum;
}
}
并且我的测试用例:
public class RecursiveUnmarshalTest
{
@Test
public void testAdd() throws Exception
{
String xml = "<add><num>10</num><num>20</num></add>";
assertEquals(30,
((Evaluable) JAXBContext.newInstance(Evaluable.class).createUnmarshaller().unmarshal(new StringReader(
xml))).eval());
}
}
这里的问题在于在
Add
中存储了非Evaluable
对象到ArrayList
中,原因是类型擦除导致JAXB不知道元素应该反映成哪种类型,所以在Add
的eval中会出现转换错误。
我通过以下方式进行测试:
public class Add extends Evaluable
{
@XmlElements({
@XmlElement(name = "num", type = Num.class),
@XmlElement(name = "add", type = Add.class)
})
private ArrayList<Evaluable> elems;
...
这个问题将会被解决。
但我不想把这个表格传遍全世界。如果我想添加一些子类型,事情会变得很混乱。
所以我的问题是哪种注释适合我的情况?或者有没有系统可以输入到非编组解码器中?
我正在使用Glassfish的JAXB,但我无法选择要使用的实现。
num
中有text
。我搜索了一下,在我的特定的JAXB实现中,允许这样做的唯一方法是使用XmlTransient
,对吗? - Jason Hu