我正在使用 JAXB 根据定义的模式编码/解码 xml 文档。我注意到 JAXB 在编码的 xml 中生成不正确的 namespace 。
这里是详细信息-
soap.xsd -->
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope"
xmlns:svc="http://abc.com/ServiceSetupV001"
targetNamespace="http://schemas.xmlsoap.org/soap/envelope"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://abc.com/ServiceSetupV001" schemaLocation="schema1.xsd" />
<xsd:complexType name="Envelope">
<xsd:sequence minOccurs="0" maxOccurs="1">
<xsd:element name="Body" type="soapenv:Body" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="Body">
<xsd:sequence minOccurs="0" maxOccurs="1">
<xsd:element name="detailsRequest" type="svc:DetailsRequest" minOccurs="0" maxOccurs="1"/>
<xsd:element name="detailsResponse" type="svc:DetailsResponse" minOccurs="0" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
schema1.xsd -->
<xsd:schema
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://abc.com/ServiceSetupV001"
xmlns:svc="http://abc.com/ServiceSetupV001"
xmlns:osa="http://abc.com/xmlschema/osa"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:import namespace="http://abc.com/xmlschema/osa" schemaLocation="schema2.xsd"/>
<xsd:complexType name="DetailsRequest">
<xsd:sequence minOccurs="0" maxOccurs="1">
<xsd:element name="requestHeader" type="osa:RequestHeader" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="detailsRequest" type="svc:DetailsRequest" />
<xsd:complexType name="DetailsResponse">
<xsd:sequence minOccurs="0" maxOccurs="1">
<xsd:element name="responseHeader" type="osa:ResponseHeader" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="detailsResponse" type="svc:DetailsResponse" />
</xsd:schema>
schema2.xsd -->
<xsd:schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:osa="http://abc.com/xmlschema/osa"
targetNamespace="http://abc.com/xmlschema/osa"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xsd:complexType name="RequestHeader">
<xsd:sequence>
<xsd:element name="component" type="string" />
<xsd:element name="channel" type="string" />
<xsd:element name="serverInstance" type="string" minOccurs="0" />
<xsd:element name="traceId" type="string" />
<xsd:element name="applicationId" type="string" />
<xsd:element name="userId" type="string" minOccurs="0" />
<xsd:element name="userIdType" type="string" minOccurs="0" />
<xsd:element name="role" type="string" minOccurs="0" />
<xsd:element name="timestamp" type="dateTime" minOccurs="0" />
<xsd:element name="isReplyExpected" type="boolean" minOccurs="0" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ResponseHeader">
<xsd:sequence>
<xsd:element name="component" type="string" />
<xsd:element ref="osa:service" />
<xsd:element name="traceId" type="string" />
<xsd:element name="serverInstance" type="string" />
<xsd:element name="timestamp" type="dateTime" />
</xsd:sequence>
</xsd:complexType>
<xsd:element name="service" type="osa:Service" />
<xsd:complexType name="Service">
<xsd:sequence>
<xsd:element name="name" type="string" />
<xsd:element name="operation" type="string" />
<xsd:element name="version" type="string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
我已经为 jaxbMarshaller 定义了一个 namespacePrefixMapperImpl(在我的 spring 配置中),它将 URI 映射到我定义的前缀名称。
编码的响应 xml 如下所示。请注意,JAXB 在 namespace 前缀上搞砸了。 JAXB 正在使用 soapenv 命名空间 对于 detailsResponse 复杂类型,而不是 svc 前缀。然后它使用 svc 前缀作为 responseHeader 复杂类型而不是 osa 前缀。 一些元素是字符串类型,因此不应该有前缀(即默认命名空间)。等等……
我哪里错了?或者这是 jaxb-impl 的问题。
生成的 XML -->
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope"
xmlns:osa="http://abc.com/xmlschema/osa"
xmlns:svc="http://abc.com/ServiceSetupV001">
<soapenv:Body>
<soapenv:detailsResponse>
<svc:responseHeader>
<osa:component/>
<osa:service/>
<osa:traceId>sadasdas</osa:traceId>
<osa:serverInstance>40d501</osa:serverInstance>
<osa:timestamp>2012-07-01T02:18:00.693Z</osa:timestamp>
</svc:responseHeader>
</soapenv:detailsResponse>
</soapenv:Body>
</soapenv:Envelope>
我用来从模式生成 JAXB 类的插件在我的 pom.xml 中定义如下:
<!-- Plugin to generate jaxb classes from xsd -->
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.2</version>
<executions>
<execution>
<id>process-xsd</id>
<goals>
<goal>generate</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<schemaIncludes>
<include>**/*.xsd</include>
</schemaIncludes>
<bindingIncludes>
<include>**/*.xjb</include>
</bindingIncludes>
<generateDirectory>${src.dir}</generateDirectory>
<verbose>true</verbose>
<extension>true</extension>
<args>
<arg>-Xannotate</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
<version>0.6.4</version>
</plugin>
</plugins>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.6</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>stax</groupId>
<artifactId>stax-api</artifactId>
<version>1.0.1</version>
</dependency>
<dependency>
<groupId>activesoap</groupId>
<artifactId>jaxb-xercesImpl</artifactId>
<version>1.5</version>
</dependency>
</dependencies>
</plugin>
最佳答案
好吧,看起来 Jaxb 正在为导入的子元素保留包含 xsd 的目标 namespace ,即使那些导入的子元素有自己的 namespace 。解决此问题的一种方法是将架构中导入元素的定义从“type”更改为“ref”。
但是,在这种情况下,我不想修改模式,因为它们来自客户端,因此我们不想修改它们以使其工作。
因此,我在 bindings.xjb 文件中添加了以下注释。我现在可以看到生成的模式类中的元素具有正确的命名空间声明。但是,现在的问题是生成的 xml 不会生成子元素,即使命名空间现在是正确的。
所以,我又有点卡住了。没想到这么难。
对我的 bindings.xjb 的更改:
<jaxb:bindings node="//xsd:complexType[@name='Body']//xsd:element[@name='detailsRequest']">
<annox:annotate target="field">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlElement"
name="detailsRequest"
namespace="http://abc.com/ServiceSetupV001"/>
</annox:annotate>
<jaxb:bindings node="//xsd:complexType[@name='Body']//xsd:element[@name='detailsResponse']">
<annox:annotate target="field">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlElement"
name="detailsResponse"
namespace="http://abc.com/ServiceSetupV001"/>
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="//xsd:complexType[@name='DetailsRequest']//xsd:element[@name='requestHeader']">
<annox:annotate target="field">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlElement"
name="requestHeader"
namespace="http://abc.com/xmlschema/osa"/>
</annox:annotate>
<jaxb:bindings node="//xsd:complexType[@name='DetailsResponse']//xsd:element[@name='responseHeader']">
<annox:annotate target="field">
<annox:annotate annox:class="javax.xml.bind.annotation.XmlElement"
name="responseHeader"
namespace="http://abc.com/xmlschema/osa"/>
</annox:annotate>
</jaxb:bindings>
生成的类有适当的命名空间注释
@XmlElement(name = "detailsRequest", namespace = "http://abc.com/ServiceSetupV001")
protected DetailsRequest detailsRequest;
@XmlElement(name = "detailsResponse", namespace = "http://abc.com/ServiceSetupV001")
protected DetailsResponse detailsResponse;
但是现在,编码的 XML 没有值
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope"
xmlns:osa="http://abc.com/xmlschema/osa"
xmlns:svc="http://abc.com/ServiceSetupV001">
<soapenv:Body>
<svc:detailsResponse/>
</soapenv:Body>
</soapenv:Envelope>
关于namespaces - JAXB Impl 在编码的 xml 中生成不正确的命名空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11962835/