使用默认命名空间时无法解组编组文档
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
元素缺少名称空间声明(在您的示例中,Document
和 Export
元素是不同名称空间的一部分)
- 缺少
export
包裹中的 elementFormDefault = XmlNsForm.QUALIFIED
- 您的主包
@XmlSchema
注释的命名空间值错误(urn:Whosebug:exportnamespace
而不是 urn:Whosebug:documentnamespace
,Document
元素应该在其中)
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
我设置了一个显示我的问题的存储库: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
元素缺少名称空间声明(在您的示例中,Document
和Export
元素是不同名称空间的一部分)- 缺少
export
包裹中的elementFormDefault = XmlNsForm.QUALIFIED
- 您的主包
@XmlSchema
注释的命名空间值错误(urn:Whosebug:exportnamespace
而不是urn:Whosebug:documentnamespace
,Document
元素应该在其中) 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