java JAXB 2.x:如何在不知道目标类的情况下解组 XML?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5513250/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:29:18  来源:igfitidea点击:

JAXB 2.x: How to unmarshal an XML without knowing the target class?

javajaxbjaxb2moxy

提问by basZero

If there is a way, how to do this, I'd like to know the most elegant one. Here is the question: - Let's assume you have an abstract class Z - You have two classes inherited from Z: named A and B.

如果有办法,如何做到这一点,我想知道最优雅的。这是问题: - 假设您有一个抽象类 Z - 您有两个从 Z 继承的类:名为 A 和 B。

You marshal any instance (A or B) like this:

您可以像这样编组任何实例(A 或 B):

JAXBContext context = JAXBContext.newInstance(Z.class);
Marshaller m = context.createMarshaller();
m.marshal(jaxbObject, ...an outputstream...);

In the resulting XML you see what kind of instance it was (A or B).

在生成的 XML 中,您可以看到它是哪种实例(A 或 B)。

Now, how do you unmarshall like

现在,你如何解组

JAXBContext jc = JAXBContext.newInstance(Z.class);
Unmarshaller u = jc.createUnmarshaller();
u.unmarshal(...an inputstream...)

I get an UnmarshalException saying

我收到一个 UnmarshalException 说

"Exception Description: A descriptor with default root element {<my namespace>}<the root tag, e.g. A or B> was not found in the project]

javax.xml.bind.UnmarshalException"

"Exception Description: A descriptor with default root element {<my namespace>}<the root tag, e.g. A or B> was not found in the project]

javax.xml.bind.UnmarshalException"

So how do you do unmarshalling so that you get an instance of Z and then you can test AFTER unmarshalling, what it is? e.g. z instanceof A then... z instanceof B then something else... etc.

那么如何进行解组,以便获得 Z 的实例,然后可以在解组后进行测试,它是什么?例如 z instanceof A then... z instanceof B then something else... 等等。

Thanks for any ideas or solutions.

感谢您提供任何想法或解决方案。

I am using JRE1.6 with MOXy as JAXB Impl.

我使用 JRE1.6 和 MOXy 作为 JAXB Impl。

采纳答案by basZero

THERE IS NO SOLUTION TO MY QUESTION!

我的问题没有解决方案!

Under any circumstances you have to tell the unmarshaller exactly what object it should unmarshall to.

在任何情况下,您都必须准确地告诉解组器它应该解组到什么对象。

回答by basZero

There is a similar question here.

还有一个类似的问题在这里

Is it possible, to just unmarshall by providing Person.classand the unmarshaller finds out itself, whether it has to unmarshall to ReceiverPerson.classor SenderPerson.class?

是否有可能通过提供来解组Person.class并且解组器发现自己,是否必须解组到ReceiverPerson.classSenderPerson.class

@XmlRootElement(name="person")
public class ReceiverPerson extends Person {
  // receiver specific code
}

@XmlRootElement(name="person")
public class SenderPerson extends Person {
  // sender specific code (if any)
}

// note: no @XmlRootElement here
public class Person {
  // data model + jaxb annotations here
}

回答by Alex

So how do you do unmarshalling so that you get an instance of Z and then you can test >AFTER unmarshalling, what it is? e.g. z instanceof A then... z instanceof B then >something else...etc.

那么如何进行解组,以便获得 Z 的实例,然后可以测试 >AFTER 解组后,它是什么?例如 z instanceof A then... z instanceof B then >something else...等。

This should work...

这应该工作...

Unmarshaller u = jc.createUnmarshaller();
Object ooo = u.unmarshal( xmlStream );
if ( ooo instanceof A )
{
    A myAclass = (A)ooo;
}
else if ( ooo instanceof B )
{
    B myBclass = (B)ooo;
}

I have tested this myself and it works.

我自己测试过这个并且它有效。

回答by Fabian Tschachtli

Every XML Documents Must Have a Root Elementand if you want to use the same UnMarshaller for both instances your only possibility is to have a common root element such as:

每个XML 文档都必须有一个根元素,如果您想对这两个实例使用相同的 UnMarshaller,您唯一的可能性就是拥有一个公共根元素,例如:

<root>
  <A></A>
</root>

and your xsd File would look like this

你的 xsd 文件看起来像这样

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:annotation>
        <xs:documentation>
        example for stackoverflow
    </xs:documentation>
    </xs:annotation>
    <xs:element name="root" type="rootType"/>
    <xs:complexType name="rootType">
            <xs:choice>
                <xs:element name="A" type="AType"/>
                <xs:element name="B" type="BType"/>
            </xs:choice>
    </xs:complexType>

    ... your AType and BType definitions here

</xs:schema>