如何重构XSD以便解组不返回JAXBElement

dma*_*a_k 9 java xsd jaxb unmarshalling

我有以下架构:

<xsd:schema xmlns:bar="http://www.foo.org/bar"
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:annox="http://annox.dev.java.net"
        xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
        targetNamespace="http://www.foo.org/bar"
        jaxb:extensionBindingPrefixes="annox" jaxb:version="2.1" elementFormDefault="qualified">

    <xsd:element name="unit" type="bar:unit" />

    <xsd:complexType name="unit">
        <xsd:annotation>
            <xsd:appinfo>
                <annox:annotate>@javax.xml.bind.annotation.XmlRootElement(name="unit")</annox:annotate>
            </xsd:appinfo>
        </xsd:annotation>
            <xsd:sequence>
            <xsd:any processContents="skip" />
        </xsd:sequence>
    </xsd:complexType>

</xsd:schema>
Run Code Online (Sandbox Code Playgroud)

当我解组这个XML时

<unit xmlns="http://www.foo.org/bar">
    <text>Name</text>
</unit>
Run Code Online (Sandbox Code Playgroud)

返回的对象是javax.xml.bind.JAXBElement<Unit>,但我想org.foo.bar.Unit回来.我需要这个,因为在我的情况下解组是由JAX-RS提供者或SpringWeb隐式发生的.

观察:

  • 如果我删除/替换<xsd:any processContents="skip" />声明,JAXB开始返回org.foo.bar.Unit.
  • 如果我删除<xsd:element name="unit" type="bar:unit" />声明,JAXB开始返回org.foo.bar.Unit(虽然需要在解组时禁用验证).

因此,我会说,鉴于XSD是证明问题的最小XSD.

问题:为什么JAXB包装org.foo.bar.UnitJAXBElement以上的组合?从我看到的情况来看,XSD类型unit无法使标签名称unit与之不同,为什么JAXB需要这种工厂方法呢?

@XmlElementDecl(namespace = "http://www.foo.org/bar", name = "unit")
public JAXBElement<Unit> createUnit(Unit value) { ... }
Run Code Online (Sandbox Code Playgroud)

展示JAXB 2.2.7问题的项目就在这里.运行时输出以下内容:

Running org.foo.bar.UnitTest
>>> Class is: javax.xml.bind.JAXBElement
>>> XML is: <?xml version="1.0" encoding="UTF-8" standalone="yes"?><unit xmlns="http://www.foo.org/bar"><text>Name</text></unit>
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.318 sec <<< FAILURE!
Run Code Online (Sandbox Code Playgroud)

Laz*_*rov 1

如果你正在做这样的事情:

JAXBContext jaxbContext = JAXBContext.newInstance(Unit.class);
Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

JAXBElement<Unit> root = jaxbUnmarshaller.unmarshal(new StreamSource(
        file), Unit.class);
Unit unit = root.getValue();
Run Code Online (Sandbox Code Playgroud)

尝试也许:

Unit unit = JAXBIntrospector.getValue(jaxbUnmarshaller.unmarshal(new StreamSource(
        file), Unit.class);
Run Code Online (Sandbox Code Playgroud)