web-dev-qa-db-ja.com

XMLをアンマーシャルしようとするとクラスキャスト例外が発生しますか?

ここでクラスキャスト例外を通過しようとしています:

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

この例外をスローします:

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

クラスはxjc.batツールによって生成されたため、これを理解していません。生成されたクラスはまったく変更していません。したがって、ここでキャストの問題はないはずです-アンマーシャラーは本当にクラスを返しますFooClassにキャストできます。

私が間違っていることに関するアイデアはありますか?

50
Vidar

FooClassにはXmlRootElement注釈がありますか?そうでない場合は、試してください:

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

これは 非公式JAXBガイド に基づいています。

109
Jon Skeet

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を返すのはいつですか?

16
Rahul Thakur

今日、私は同じ問題に遭遇し、ここで答えを見つけ、いくつかの調査を行い、最も一般的な解決策はJAXBIntrospectorを使用することであると考えています。したがって-

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

として書かれるべきである

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

それとも、より一般的にするために-

T t = (T) JAXBIntrospector.getValue(unmarshaller.unmarshal(inputStream));
15
Gaurav B

詳細な説明については、 この記事 をお読みください。 XSDを適切に設定する必要があることがわかります。つまり、他のすべての要素を包含するルート要素が必要です。

XJCは@XmlRootElement複合型から生成するクラスの注釈。正確な条件はややいですが、基本的な考え方は、複合型が複数の異なるタグ名で使用されないことを静的に保証できる場合、@XmlRootElement

9
Vidar

アンマーシャラーを満足させるには、JAXBファクトリクラスをいじるのに時間がかかりすぎました。 unmarshaller withoutを使用して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);
    }
3
MAbraham1

XMLファイルを見て、おおよそ予想どおりのものであることを確認します。

また、一時的にコードを次のように変更します。

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

最初のクラスが失敗した場合、アンマーシャリングメソッド内でクラスキャストが行われます。成功した場合は、戻ってきた実際のクラスを確認し、それが期待どおりではない理由を把握できます。

3
TofuBeer

誰かがまだ回答を探している場合に備えて、同僚からのプレビューの回答に基づいて作成します。

私のスキームのルート要素が次のように定義されているという問題がありました:

<schema>
  <element name="foo" type="bar" />
  <complexType name="bar" />
</schema>

そのため、次のキャスト例外が発生していました。

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());

これで問題は解決しました。

2

FooClassが渡したxml入力ソースのルート要素であると確信していますか? Unmarshallは、xjcによって作成されたルート要素のオブジェクトを返します。

1
Greg Noe

複数の異なるルート要素(たとえば、WSDLで定義されたXSD)を持つXSD定義がある場合があり、その場合、生成されたクラスには@XmlRootElementがありません。そのため、ユーザーmbrauhがすでに書いているように、JAXBElementの値を取得する必要があります。私の場合、私は使用しました:

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

したがって、ジェネリックを使用すると、二重型キャストを簡単に回避できます。

1
Marek Branicky

また、「Javax.xml.bind.JAXBElementにキャストできません」というエラーが発生し、この非常に簡単な解決策が見つかりました。

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

明らかに、JAXBElement型のオブジェクトが返されるため、代わりにその値を型キャストする必要があります。

ソース: https://forums.Oracle.com/thread/1625944

0
mbrauh

私の場合、SOAPUIアプリケーションから石鹸の請願書を送信しようとするとエラーが発生します。このエラーをスキップするには、プロパティ 'strip whitespaces'をtrueに設定する必要があります。

受信したコンテンツをデバッグするとき、次のコンテンツを含むリストです:

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

誰かを助けることを願っています。

@XmlRootElement(name = "specifyName"、namespace = "namespace")を変換オブジェクトに指定します。

0
user752749

これを試して:

JAXBContext jc = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
JAXBElement element = (JAXBElement) unmarshaller.unmarshal( new StringReader(xmlString));
Foo foo = (Foo)element;
0
LazyCoder

アクセス権があり、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はルート要素を生成します!

0
Antho