57

试图在这里克服一个类转换异常:

FooClass fooClass = (FooClass ) unmarshaller.unmarshal(inputStream);

抛出此异常:

java.lang.ClassCastException: javax.xml.bind.JAXBElement

我不明白这一点——因为该类是由 xjc.bat 工具生成的——它生成的类我根本没有改变——所以这里不应该有强制转换问题——解组器真的应该给我一个类可以转换为 FooClass。

关于我做错了什么的任何想法?

4

14 回答 14

124

FooClassXmlRootElement注解吗?如果没有,请尝试:

Source source = new StreamSource(inputStream);
JAXBElement<FooClass> root = unmarshaller.unmarshal(source, FooClass.class);
FooClass foo = root.getValue();

这是基于非官方 JAXB 指南

于 2009-04-01T20:04:11.843 回答
19

在 JAXBElement 上使用 JAXBIntrospector 来获取 schemaObject,如 >>

JAXBContext jaxbContext = JAXBContext.newInstance(Class.forName(className));
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Object schemaObject = JAXBIntrospector.getValue(unmarshaller.unmarshal(new ByteArrayInputStream(xmlString.getBytes())));

参考:JAXB unmarshaller.unmarshal 何时返回 JAXBElement<MySchemaObject> 或 MySchemaObject?

于 2012-05-21T06:02:45.900 回答
17

我今天遇到了同样的问题,在这里看到了答案,做了一些研究,在我看来,最通用的解决方案是使用JAXBIntrospector。因此 -

FooClass fooClass = (FooClass ) unmarshaller.unmarshal(inputStream);

应该写成

FooClass fooClass = (FooClass) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));

甚至更好,使其更通用-

T t = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));
于 2015-01-10T11:09:44.423 回答
9

如需更全面的解释,请阅读这篇文章。事实证明,您的 XSD 必须正确设置,即必须有一些根元素包含所有其他元素。

XJC 确实尝试将@XmlRootElement注释放在我们从复杂类型生成的类上。确切的条件有点难看,但基本思想是,如果我们可以静态保证复杂类型不会被多个不同的标签名称使用,我们将@XmlRootElement.

于 2009-04-29T16:48:06.353 回答
4

我们花了太多时间来处理 JAXB 工厂类来满足解组器。我们已经了解到,使用 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);
    }
于 2011-02-11T15:54:46.670 回答
3

我会查看 XML 文件并确保它大致符合您的预期。

我还会暂时将代码更改为:

Object o = unmarshaller.unmarshal(inputStream);
System.out.println(o.getClass());

如果第一个失败,那么类转换发生在 unmarshal 方法中,如果它成功,那么你可以看到你正在返回的实际类,然后找出为什么它不是你期望的那样。

于 2009-04-01T23:26:39.330 回答
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());

这为我解决了问题。

于 2011-11-02T14:40:05.640 回答
1

您确定 FooClass 是您传递的 xml 输入源的根元素吗?Unmarshall 将返回由 xjc 创建的根元素的对象。

于 2009-04-01T20:03:48.800 回答
1

有时,您的 XSD 定义包含多个不同的根元素(例如,在 WSDL 中定义的 XSD),在这种情况下,生成的类缺少 @XmlRootElement。因此,正如用户 mbrauh 已经写过的那样,您必须获取 JAXBElement 的值。就我而言,我使用了:

FooClass request = ((JAXBElement< FooClass >) marshaller.unmarshal(new StreamSource(classPathResource.getInputStream()))).getValue();

因此,使用泛型可以轻松避免双重类型转换。

于 2014-08-03T12:41:32.253 回答
1

如果您有权访问并且可以修改 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 将生成根元素!

于 2018-11-13T16:18:43.637 回答
0

指定 @XmlRootElement(name="specifyName", namespace="namespace") 来转换对象。

于 2011-09-09T17:19:12.103 回答
0

我还遇到了“Javax.xml.bind.JAXBElement cannot be cast to”错误,找到了这个非常简单的解决方案:

FooClass fooClass = (FooClass) ((JAXBElement) u.unmarshal(new File("xml/foo.xml")) ).getValue();

由于显然返回了一个 JAXBElement 类型的对象,因此您需要改为对它的值进行类型转换。

来源:https ://forums.oracle.com/thread/1625944

于 2013-10-30T16:49:13.117 回答
0

试试这个:

JAXBContext jc = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement element = (JAXBElement) unmarshaller.unmarshal( new StringReader(xmlString));
Foo foo = (Foo)element;
于 2016-07-15T12:46:24.797 回答
0

就我而言,我在尝试从 SOAPUI 应用程序发送肥皂请求时收到错误消息。我需要将属性 'strip whitespaces' 设置为 true 以跳过此错误。

调试收到的内容时,是一个包含下一个内容的列表:

[0] = "\n"
[1] = JAXBElement
[2] = "\n"

希望帮助某人。

于 2018-11-06T10:39:10.793 回答