注意:我属于NDA所以我必须使用不合理的变量名称。遗憾
您好! 我有一个抽象类:
public abstract class A {
public abstract List<String> someMethod();
}
和两个扩展该抽象类的类:
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@XmlRootElement(name = "BField")
@XmlAccessorType(XmlAccessType.FIELD)
public class B extends A {
...
}
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@XmlRootElement(name = "CField")
@XmlAccessorType(XmlAccessType.FIELD)
public class C extends A {
...
}
然后在代码中的某个地方有一个类,它列出了这两个类。几乎看起来像这样:
@XmlElementWrapper(name = "MyStuffData")
@XmlAnyElement(lax = true)
@XmlElementRefs({
@XmlElementRef(name = "B", type = B.class),
@XmlElementRef(name = "C", type = C.class),
})
private List<A> myStuff;
myStuff
的内容可以是B还是C对吗?如何遍历该列表?我从肥皂请求中获取数据,所以我真的很困惑如何做到这一点。我试过了:
for(A a: myStuff){
...some code here...
}
但是我得到了这个例外:
Caused by: java.lang.ClassCastException: org.apache.xerces.dom.ElementNSImpl cannot be cast to some.package.here.A
我听说lax = true可以解决问题,但我仍然得到同样的错误。令人费解的是,我可以获得非常准确的列表大小,但后来我无法迭代它。任何帮助,将不胜感激。 抱歉,我不太擅长解释,所以在Google上找到这种东西有点痛苦。
答案 0 :(得分:0)
看起来myStuff
实际上不是List<A>
(或List<B>
),而是List<ElementNSImpl>
,其中org.apache.xerces.dom.ElementNSImpl
实例似乎是某种对B
或C
的实际实例的包装器。
您可以调试该列表并尝试查看是否可以从B
获取C
/ org.apache.xerces.dom.ElementNSImpl
答案 1 :(得分:0)
对于此用例,您不应使用@XmlAnyElement(lax=true)
。
使用案例#1 - @XmlElementRef
使用@XmlElementRef
时,您需要确保@XmlElementRef
注释上的元素名称与@XmlRootElement
(或@XmlElementDecl
)注释完全匹配。
<强> input.xml中强>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<MyStuffData>
<BField/>
<CField/>
<BField/>
</MyStuffData>
</root>
<强>根强>
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlElementWrapper(name = "MyStuffData")
@XmlElementRefs({
@XmlElementRef(name = "BField", type = B.class),
@XmlElementRef(name = "CField", type = C.class),
})
private List<A> myStuff;
public List<A> getMyStuff() {
return myStuff;
}
}
使用案例#2 - @XmlElements
如果您不希望元素名称与引用类型的根元素名称相同,则可以使用@XmlElements
注释。
<强> input.xml中强>
<?xml version="1.0" encoding="UTF-8"?>
<root>
<MyStuffData>
<B/>
<C/>
<B/>
</MyStuffData>
</root>
<强>根强>
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlElementWrapper(name = "MyStuffData")
@XmlElements({
@XmlElement(name = "B", type = B.class),
@XmlElement(name = "C", type = C.class),
})
private List<A> myStuff;
public List<A> getMyStuff() {
return myStuff;
}
}
<强> COMMON 强>
以下两种用例都是相同的。
<强> A 强>
public abstract class A {
}
<强>乙强>
import javax.xml.bind.annotation.*;
@XmlRootElement(name = "BField")
public class B extends A {
}
<强> C 强>
import javax.xml.bind.annotation.*;
@XmlRootElement(name = "CField")
public class C extends A {
}
<强>演示强>
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum17061559/input.xml");
Root root = (Root) unmarshaller.unmarshal(xml);
for(A a : root.getMyStuff()) {
System.out.println(a);
}
}
}
<强>输出强>
forum17061559.B@6998e5d9
forum17061559.C@351a3fb8
forum17061559.B@4e4d6