XML을 언마샬링하려고 할 때 클래스 캐스트 예외가 발생합니까?

StackOverflow https://stackoverflow.com/questions/707084

  •  22-08-2019
  •  | 
  •  

문제

여기에서 클래스 캐스트 예외를 극복하려고 합니다.

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

이 예외가 발생합니다.

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

나는 이것을 이해하지 못합니다. 클래스는 xjc.bat 도구에 의해 생성되었으며 생성된 클래스는 전혀 변경되지 않았습니다. 따라서 여기에 캐스팅 문제가 없어야 합니다. 언마샬러가 실제로 나에게 클래스를 돌려주어야 합니다. FooClass로 캐스팅할 수 있습니다.

내가 뭘 잘못하고 있는지에 대한 아이디어가 있습니까?

도움이 되었습니까?

해결책

하다 FooClass 가지고있다 XmlRootElement 주석? 그렇지 않은 경우 시도하십시오.

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

그것은 기반입니다 비공식 JAXB 가이드.

다른 팁

jaxbelement에서 jaxbintroSpector를 사용하여 >>와 같은 스키마브젝트를 얻으십시오.

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

나타내다: Jaxb는 언제 undarshaller.unmarshal이 jaxbelement를 반환합니까?u003CMySchemaObject> 아니면 myschemaobject?

나는 오늘 같은 문제를 일으켰고, 여기서 답을보고, 연구를했고, 가장 일반적인 해결책은 사용하는 것입니다. JaxbintroSpector. 따라서 -

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

작성해야합니다

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

또는 더 잘, 더 일반적인

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

더 자세한 설명을 보려면 읽어보세요. 이 기사.XSD가 올바르게 설정되어야 하는 것으로 나타났습니다.다른 모든 요소를 ​​포함하는 일부 루트 요소가 있어야 합니다.

XJC는 다음을 시도합니다. @XmlRootElement 복합 유형에서 생성하는 클래스에 대한 주석입니다.정확한 조건은 다소 추악하지만 기본 아이디어는 복잡한 유형이 여러 개의 다른 태그 이름에서 사용되지 않는다는 것을 정적으로 보장할 수 있다면 다음을 넣는 것입니다. @XmlRootElement.

XML 파일을보고 그것이 당신이 기대할 것으로 예상되는지 확인합니다.

또한 코드를 일시적으로 변경합니다.

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

첫 번째 것이 실패하면 클래스 캐스트가 Unmarshal 메소드 내에서 일어나고 있습니다. 성공하면 돌아 오는 실제 클래스를보고 그것이 왜 기대하지 않는지 알아낼 수 있습니다.

우리는 unmarshaller를 만족시키기 위해 JaxB Factory 수업과 함께 너무 많은 시간을 보냈습니다. 우리는 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);
    }

미리보기를 기반으로 동료의 답변을 구축하는 경우, 누구나 여전히 답을 찾고있는 경우를 대비하여.

내 체계의 근본 요소가 다음과 같이 정의되는 문제가있었습니다.

<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
    }

내가 한 일은 시도 블록의 첫 번째 줄을 다음으로 변경하는 것이 었습니다.

javax.xml.bind.JAXBContext jaxbCtx = javax.xml.bind.JAXBContext.newInstance(mobilityConfigType.getClass().getName());

그것은 나에게 문제를 해결했다.

FooClass가 통과 한 XML 입력 소스의 루트 요소라고 확신하십니까? UnmarShall은 XJC가 만든 루트 요소의 객체를 반환합니다.

때로는 여러 다른 루트 요소 (예 : WSDL에 정의 된 XSD)가있는 XSD 정의가 있으며이 경우 생성 된 클래스에 @xmlRootElement가 누락됩니다. 따라서 사용자 Mbrauh는 이미 jaxbelement의 가치를 얻어야합니다. 제 경우에는 다음을 사용했습니다.

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

따라서 제네릭을 사용하면 이중 유형 캐스팅을 쉽게 피할 수 있습니다.

변환 객체에 @xmlRootElement (이름 = "specifyname", namespace = "namespace")를 지정하십시오.

또한 "javax.xml.bind.jaxbelement가 캐스트 될 수 없으며이 매우 간단한 솔루션을 발견했습니다.

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

분명히 jaxbelement 유형의 객체가 반환되므로 대신 그 값을 대신 타이핑해야합니다.

원천: https://forums.oracle.com/thread/1625944

이 시도:

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

제 경우에는 SOAPUI 신청서에서 비누 청원을 보내려고 할 때 오류가 발생합니다. 이 오류를 건너 뛰려면 속성 '스트립 공백'을 true로 설정해야합니다.

수신 된 콘텐츠를 디버그하면 다음 컨텐츠가있는 목록입니다.

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

희망은 누군가를 도와줍니다.

액세스 권한이 있고 XSD를 수정할 수 있습니다. 저에게 있어이 문제는 아이디어와 함께 XML에서 XSD를 생성 할 때 추가됩니다.

이 XML로 :

<?xml version="1.0"?>
<schema>
  <element name="foo" type="bar" />
  <complexType name="bar" />
</schema>

아이디어는 이와 같은 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는 루트 요소를 생성합니다!

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top