使用默认命名空间时无法解组编组文档

Can't unmarshal marshalled document when default namespace used

我设置了一个显示我的问题的存储库:https://github.com/Waxolunist/Whosebug.34392476

我尝试解组一个简单的 xml 文档:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<for:document xmlns:for="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx">
     <Export xmlns="urn:adcubum:Syrius">
         <ExportInhalt/>
         <ExportKopf>
             <Quelle>lokal</Quelle>
         </ExportKopf>
         <SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</SchemaVersion>
     </Export>
</for:document>

这是我通过以下代码得到的文档:

    Document document = new Document();
    Export export = new Export();
    ExportKopf exportKopf = new ExportKopf();
    exportKopf.setQuelle("lokal");
    export.setExportKopf(exportKopf);
    ExportInhalt exportInhalt = new ExportInhalt();
    export.setExportInhalt(exportInhalt);
    export.setSchemaVersion("bec811a9807a8c8da403d70b9b5e22ad");
    document.setExport(export);

    JAXBContext jaxbContext = JAXBContext.newInstance(Document.class);
    Marshaller marshaller = jaxbContext.createMarshaller();
    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
    marshaller.marshal(document, System.out);

文档如下所示:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "document", namespace = "http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx")
public class Document {

    @XmlElement(name = "Export", namespace = "urn:adcubum:Syrius")
    private vo.dom.common_service.modul_bl.syrius.Export export;

}

包-info.java

@XmlSchema(
namespace = "urn:adcubum:Syrius",
xmlns = {
    @XmlNs(prefix = "for", namespaceURI = "http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx"),
    @XmlNs(prefix = "", namespaceURI = "urn:adcubum:Syrius")
}, 
elementFormDefault = XmlNsForm.UNQUALIFIED)

当我尝试对其进行解组时,我没有映射数据:

    JAXBContext jaxbContext = JAXBContext.newInstance(Document.class);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

    InputStream is = this.getClass().getResourceAsStream("/requests/document_simple3.xml");
    XMLInputFactory factory = XMLInputFactory.newInstance();
    XMLStreamReader xmlsr = factory.createXMLStreamReader(is);

    Document document = unmarshaller.unmarshal(xmlsr, Document.class).getValue();

ExportKopf 和 ExportInhalt 正在返回 null。

而是遵循 xml 的作品。唯一的区别是命名空间前缀:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<for:document xmlns:for="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx">
    <ns3:Export xmlns:ns3="urn:adcubum:Syrius">
        <ExportInhalt/>
        <ExportKopf>
            <Quelle>lokal</Quelle>
        </ExportKopf>
        <SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</SchemaVersion>
    </ns3:Export>
</for:document>

我正在使用 eclipselink moxy。

我必须更改什么才能解组已编组的文档。

我认为每当 JAXB 中发生类似这种奇怪的事情时,查看映射的实际 XSD 模式总是一个好主意。您可以使用以下代码轻松做到这一点。

JAXBContext jaxbContext = JAXBContext.newInstance(Document.class);
jaxbContext.generateSchema(new SchemaOutputResolver() {

    @Override
    public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
        StreamResult streamResult = new StreamResult(new PrintWriter(System.err) {
            @Override
            public void close() {
            }
        });
        streamResult.setSystemId(suggestedFileName);
        return streamResult;
    }
});

这将打印应该反映您的 JAXB 模型的模式(您可以使用其他编写器将它们写入文件)。 XSD 文件通常非常能揭示这类问题。我认为您遇到的问题是 @XmlSchema 映射。您应该尝试使用 elementFormDefault = XmlNsForm.QUALIFIED 代替。每当您在映射中使用多个命名空间时,使用 QUALIFIED 总是一个好主意。

编辑:虽然您的 JAXB 映射的主要问题是错误的 and/or 缺少 elementFormDefault 的值,但还有其他问题已修复,您的代码库中的代码可以正常工作。

  • Document 中的 Export 元素缺少名称空间声明(在您的示例中,DocumentExport 元素是不同名称空间的一部分)
  • 缺少 export 包裹中的 elementFormDefault = XmlNsForm.QUALIFIED
  • 您的主包 @XmlSchema 注释的命名空间值错误(urn:Whosebug:exportnamespace 而不是 urn:Whosebug:documentnamespaceDocument 元素应该在其中)
  • jdk_jaxb/UnmarshallerTest.java 导入错误 - 它导入了 model.eclipselink.Document 而不是 model.sun.Document

编辑:这是更新后的代码 https://github.com/MojoJojo/Whosebug.34392476

好的,这是所有 moxy_jaxb 测试都通过的工作版本。因为你说你正在使用 moxy,所以我省略了 model.sun.* 包的更改。如果您理解下面的概念,您应该能够轻松地自行修复它。

首先,我清理了您的 mode.* 包中的命名空间声明。大多数时候,package-info.java 中的声明和绑定就足够了。在包、实体、字段上一遍又一遍地声明它们会增加复杂性和不需要的行为。查看 this link 了解详情。没有必要 re-declare 个人 Models/Entities 自己,除非有充分的理由不这样做。接下来,测试 xml 本身有点破。在必要时使用适当的前缀修复了测试 xml:

首先,model.eclipselink.Document.java

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "document")
public class Document {
    @XmlElement(name = "Export", namespace="urn:adcubum:Syrius")
    private Export export;
    public Export getExport() {
        return export;
    }
    public void setExport(Export export) {
        this.export = export;
    }
}

model.eclipselink.package-info.java:

@XmlSchema(namespace = "http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx",
elementFormDefault = XmlNsForm.QUALIFIED)
package model.eclipselink;

import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;

model.eclipselink.export.packageinfo.java 上的类似重构:

@XmlSchema(namespace = "urn:adcubum:Syrius",
elementFormDefault = XmlNsForm.QUALIFIED)
package model.eclipselink.export;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.Xml

在 Export.java 上:

package model.eclipselink.export;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import org.eclipse.persistence.oxm.annotations.XmlElementNillable;

@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "Export")

@XmlType(name = "Export", propOrder = {
        "exportInhalt",
        "exportKopf",
        "schemaVersion"
    })
public class Export {

    @XmlElement(name = "ExportKopf", required = true)
    private ExportKopf exportKopf;

    @XmlElement(name = "ExportInhalt", required = true)
    private ExportInhalt exportInhalt;

    @XmlElement(name = "SchemaVersion", required = true)
    private String schemaVersion;

    public ExportKopf getExportKopf() {
        return exportKopf;
    }

    public void setExportKopf(ExportKopf exportKopf) {
        this.exportKopf = exportKopf;
    }

    public ExportInhalt getExportInhalt() {
        return exportInhalt;
    }

    public void setExportInhalt(ExportInhalt exportInhalt) {
        this.exportInhalt = exportInhalt;
    }

    public String getSchemaVersion() {
        return schemaVersion;
    }

    public void setSchemaVersion(String schemaVersion) {
        this.schemaVersion = schemaVersion;
    }

}

以及对 prefixes.Here 的 document_prefix.xml

的 xml 文件的一些调整
<?xml version="1.0" encoding="UTF-8"?>
<for:document xmlns:for="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx">
    <ns1:Export xmlns:ns1="urn:adcubum:Syrius">
        <ns1:ExportKopf>
            <ns1:Quelle>lokal</ns1:Quelle>
        </ns1:ExportKopf>
        <ns1:ExportInhalt/>
        <ns1:SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</ns1:SchemaVersion>
    </ns1:Export>
</for:document>

document.xml:

<?xml version="1.0" encoding="UTF-8"?>
<for:document
    xmlns:for="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx" xmlns="urn:adcubum:Syrius">
    <Export>
        <ExportKopf>
            <Quelle>lokal</Quelle>
        </ExportKopf>
        <ExportInhalt />
        <SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</SchemaVersion>
    </Export>
</for:document>

和document_realnamespace.xml(不确定这个文件的用途):

<?xml version="1.0" encoding="UTF-8"?>
<for:document xmlns:ns1="urn:adcubum:Syrius" xmlns:for="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrenderer/forwktbx">
    <ns1:Export>
        <ns1:ExportKopf>
            <ns1:Quelle>lokal</ns1:Quelle>
        </ns1:ExportKopf>
        <ns1:ExportInhalt/>
        <ns1:SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</ns1:SchemaVersion>
    </ns1:Export>
</for:document>

而你运行 mvn clean test:

Running moxy_jaxb.MarshallerTest
Context class: class org.eclipse.persistence.jaxb.JAXBContext
<?xml version="1.0" encoding="UTF-8"?>
<document xmlns="http://www.adcubum.com/wsdl/global/callout/syrius/modul_bl/doc/service/documentrend
erer/forwktbx" xmlns:ns0="urn:adcubum:Syrius">
   <ns0:Export>
      <ns0:ExportInhalt/>
      <ns0:ExportKopf>
         <ns0:Quelle>lokal</ns0:Quelle>
      </ns0:ExportKopf>
      <ns0:SchemaVersion>bec811a9807a8c8da403d70b9b5e22ad</ns0:SchemaVersion>
   </ns0:Export>
</document>
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.044 sec
Running moxy_jaxb.UnmarshallerTest
Context class: class org.eclipse.persistence.jaxb.JAXBContext
lokal
Context class: class org.eclipse.persistence.jaxb.JAXBContext
lokal
Context class: class org.eclipse.persistence.jaxb.JAXBContext
lokal
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.033 sec