尝试通过此处的类型转换异常:
FooClass fooClass = (FooClass ) unmarshaller.unmarshal(inputStream);
抛出此异常:
java.lang.ClassCastException: javax.xml.bind.JAXBElement
我不明白这一点 - 因为这个类是由xjc.bat工具生成的 - 它生成的类我根本没有改变 - 所以这里应该没有施法问题 - unmarshaller应该真的给我了支持一个可以投射到FooClass的类。
关于我做错了什么的想法?
答案 0 :(得分:103)
FooClass
是否有XmlRootElement
注释?如果没有,请尝试:
Source source = new StreamSource(inputStream);
JAXBElement<FooClass> root = unmarshaller.unmarshal(source, FooClass.class);
FooClass foo = root.getValue();
答案 1 :(得分:15)
在JAXBElement上使用JAXBIntrospector来获取类似&gt;&gt;
的schemaObjectJAXBContext jaxbContext = JAXBContext.newInstance(Class.forName(className));
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object schemaObject = JAXBIntrospector.getValue(unmarshaller.unmarshal(new ByteArrayInputStream(xmlString.getBytes())));
参考:when does JAXB unmarshaller.unmarshal returns a JAXBElement<MySchemaObject> or a MySchemaObject?
答案 2 :(得分:14)
我今天遇到了同样的问题,在这里看到了答案,做了一些研究,并向我看,最通用的解决方案是使用 JAXBIntrospector 。因此 -
FooClass fooClass = (FooClass ) unmarshaller.unmarshal(inputStream);
应该写成
FooClass fooClass = (FooClass) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));
甚至更好,使它更通用 -
T t = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));
答案 3 :(得分:9)
如需更全面的解释,请阅读this article。事实证明你的XSD必须正确设置,即必须有一些根元素包含所有其他元素。
XJC确实尝试将
@XmlRootElement
注释放在我们从复杂类型生成的类上。确切的条件有点难看,但基本的想法是,如果我们可以静态地保证复杂类型不会被多个不同的标签名称使用,我们就放@XmlRootElement
。
答案 4 :(得分:3)
我会查看XML文件并确保它大致与您期望的相同。
我还会暂时将代码更改为:
Object o = unmarshaller.unmarshal(inputStream);
System.out.println(o.getClass());
如果第一个失败然后在unmarshal方法中发生了类强制转换,如果它成功,那么你可以看到你正在返回的实际类,然后弄清楚为什么它不是你期望的那样。
答案 5 :(得分:3)
我们花了太多时间来安装JAXB工厂类来满足unmarshaller。我们已经了解到使用unmarshaller 而不用调用JAXB生成的对象工厂可以正常工作。希望示例代码能够挽回某人的挫败感:
System.out.println("Processing generic-type unmarshaller: ");
MessageClass mcObject = unmarshalXml(MessageClass.class, msgQryStreamSource,
NAMESPACE + "." + "MessageClass");
public static <T> T unmarshalXml(Class<T> clazz, StreamSource queryResults,
String contextNamespace)
{
T resultObject = null;
try {
//Create instance of the JAXBContext from the class-name
JAXBContext jc;
jc = JAXBContext.newInstance(Class.forName(clazz.getName()));
Unmarshaller u = jc.createUnmarshaller();
resultObject = clazz.cast(u.unmarshal(queryResults));
}
//Put your own error-handling here.
catch(JAXBException e)
{
e.printStackTrace();
}
catch (ClassCastException e)
{
e.printStackTrace();
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
return clazz.cast(resultObject);
}
答案 6 :(得分:2)
根据同事的预览答案,以防任何人仍在寻找答案。
我遇到了将我的方案的根元素定义为:
的问题<schema>
<element name="foo" type="bar" />
<complexType name="bar" />
</schema>
因此我得到了一个Cast Exception:
try {
javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(mobilityConfigType.getClass().getPackage().getName());
javax.xml.bind.Unmarshaller unmarshaller = jaxbCtx.createUnmarshaller();
File f = FileUtil.toFile(this.getPrimaryFile());
mobilityConfigType = (MobilityModelConfigType)unmarshaller.unmarshal(FileUtil.toFile(this.getPrimaryFile()));
} catch (javax.xml.bind.JAXBException ex) {
java.util.logging.Logger.getLogger("global").log(java.util.logging.Level.SEVERE, null, ex); //NOI18N
}
我所做的是将try块的第一行更改为:
javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(mobilityConfigType.getClass().getName());
这解决了我的问题。
答案 7 :(得分:1)
你绝对相信FooClass是你传递的xml输入源的根元素吗? Unmarshall将返回由xjc创建的根元素的对象。
答案 8 :(得分:1)
有时你有一个带有多个不同根元素的XSD定义(例如在WSDL中定义的XSD),在这种情况下,生成的类缺少@XmlRootElement。因此,正如用户mbrauh已经写过的那样,你必须得到JAXBElement的值。就我而言,我用过:
FooClass request = ((JAXBElement< FooClass >) marshaller.unmarshal(new StreamSource(classPathResource.getInputStream()))).getValue();
因此,使用泛型可以轻松避免双重类型转换。
答案 9 :(得分:0)
指定@XmlRootElement(name =“specifyName”,namespace =“namespace”)来转换对象。
答案 10 :(得分:0)
我还遇到了“Javax.xml.bind.JAXBElement无法转换为”错误,发现这个非常简单的解决方案:
FooClass fooClass = (FooClass) ((JAXBElement) u.unmarshal(new File("xml/foo.xml")) ).getValue();
由于显然返回了JAXBElement类型的对象,因此需要对其值进行类型转换。
答案 11 :(得分:0)
试试这个:
JAXBContext jc = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement element = (JAXBElement) unmarshaller.unmarshal( new StringReader(xmlString));
Foo foo = (Foo)element;
答案 12 :(得分:0)
在我的情况下,尝试从SOAPUI应用程序发送肥皂请求时出现错误。我需要将“ strip whitespaces”属性设置为true才能跳过此错误。
当调试收到的内容时,是包含下一个内容的列表:
[0] = "\n"
[1] = JAXBElement
[2] = "\n"
希望可以帮助某人。
答案 13 :(得分:0)
如果具有访问权限,则可以修改XSD。 对我来说,当我使用IDEA从XML生成XSD时,这个问题会出现。
使用此xml:
<?xml version="1.0"?>
<schema>
<element name="foo" type="bar" />
<complexType name="bar" />
</schema>
IDEA会生成类似的XSD,而JAXB不会生成根元素:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="schema" type="schemaType"/>
<xs:complexType name="schemaType">
<xs:sequence>
<xs:element type="elementType" name="element"/>
<xs:element type="complexTypeType" name="complexType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="elementType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="name"/>
<xs:attribute type="xs:string" name="type"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="complexTypeType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="name"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
但是,如果您以这种方式修改XSD(请修改您的根元素“模式”以获取 标记xs:element内的xs:complexType):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="schema">
<xs:complexType>
<xs:sequence>
<xs:element type="elementType" name="element"/>
<xs:element type="complexTypeType" name="complexType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="schemaType">
<xs:sequence>
<xs:element type="elementType" name="element"/>
<xs:element type="complexTypeType" name="complexType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="elementType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="name"/>
<xs:attribute type="xs:string" name="type"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="complexTypeType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="name"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:schema>
JAXB将生成根元素!