1

注意:我在 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 可以解决问题,但我仍然得到同样的错误。令人费解的是,我可以获得非常准确的列表大小,但我无法遍历它。任何帮助,将不胜感激。对不起,我不擅长解释,所以在谷歌上找到这种东西有点痛苦。

4

2 回答 2

0

看起来myStuffis 实际上 is not List<A>(or List<B>) 但是,List<ElementNSImpl>其中instance 似乎是对ororg.apache.xerces.dom.ElementNSImpl的实际实例的某种包装。BC

您可以调试该列表并尝试查看是否可以获取B/C来自org.apache.xerces.dom.ElementNSImpl

于 2013-06-12T09:09:03.280 回答
0

对于此用例,您不应使用@XmlAnyElement(lax=true).


用例 #1 - @XmlElementRef

使用@XmlElementRef时需要确保注解上的元素名称与(或)注解完全@XmlElementRef匹配。@XmlRootElement@XmlElementDecl

输入.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注释。

输入.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;
    }

}

常见的

以下是两种用例的共同点。

一种

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
于 2013-06-12T10:00:21.377 回答