指定名称空间 JAXB 的前缀
Specifying prefix to namespace JAXB
面临使用 JAXB 解组的问题。我需要使用多个名称空间。
Java classes 是为第三方提供的 XSD 生成的。所以我不想在 Java classes 中的 XMLRootElement 指定名称空间,也不想手动更改多个 classes.
编组逻辑如下:
private <R extends BasicResponseType, T extends BasicRequestType> R doPost(T request, String requestname) throws Exception {
if (jaxbContext == null)
jaxbContext = JAXBContext.newInstance(TokenRequest.class, TokenResponse.class,
BasicResponseType.class, GeneralErrorResponse.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
logXML(marshaller, request);
// POST to baseURL/requestname and show response
HttpURLConnection conn = openConnection("/" + requestname);
OutputStream os = conn.getOutputStream();
marshaller.marshal(request, os);
os.flush();
// Normaler Output oder Error liefern, je nach HTTP Response
InputStream is = null;
boolean ok = true;
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
is = conn.getErrorStream();
ok = false;
} else {
is = conn.getInputStream();
}
R response = (R) unmarshaller.unmarshal(new StreamSource(is));
is.close();
conn.disconnect();
logXML(marshaller, response);
if (ok) {
return response;
} else {
throw new Exception(getMessages((GeneralErrorResponse) response));
}
}
xml元素classTokenRequest.java
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
@XmlRootElement(name = "TokenRequest")
public class TokenRequest
extends BasicInRequestType{ }
BasicInRequestType.java
package exp._3_0.api;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BasicInRequestType", propOrder = {
"software"
})
@XmlSeeAlso({
TokenRequest.class
})
public class BasicInRequestType
extends BasicRequestType {
@XmlElement(required = true)
protected SoftwareType software;
/**
* Gets the value of the software property.
*
* @return
* possible object is
* {@link SoftwareType }
*
*/
public SoftwareType getSoftware() {
return software;
}
/**
* Sets the value of the software property.
*
* @param value
* allowed object is
* {@link SoftwareType }
*
*/
public void setSoftware(SoftwareType value) {
this.software = value;
}}
BasicRequestType.java
package exp._3_0.api;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
propOrder = {
"header",
"user"
})
@XmlSeeAlso({
BasicInRequestType.class
})
public class BasicRequestType {
@XmlElement(required = true)
protected BasicHeaderType header;
@XmlElement(required = true)
protected UserHeaderType user;
@XmlType(name = "BasicRequestType", namespace = "http://foo/1.0/common",
/**
* Gets the value of the header property.
*
* @return
* possible object is
* {@link BasicHeaderType }
*
*/
public BasicHeaderType getHeader() {
return header;
}
/**
* Sets the value of the header property.
*
* @param value
* allowed object is
* {@link BasicHeaderType }
*
*/
public void setHeader(BasicHeaderType value) {
this.header = value;
}
/**
* Gets the value of the user property.
*
* @return
* possible object is
* {@link UserHeaderType }
*
*/
public UserHeaderType getUser() {
return user;
}
/**
* Sets the value of the user property.
*
* @param value
* allowed object is
* {@link UserHeaderType }
*
*/
public void setUser(UserHeaderType value) {
this.user = value;
}}
XML 输出:
<TokenRequest xmlns:common="http://foo/1.0/common" xmlns:ns4="http://foo/3.0/api" xmlns:base="http://foo/3.0/base">
<common:header>
<common:requestId></common:requestId>
<common:timestamp></common:timestamp>
</common:header>
<common:user>
<common:login></common:login>
<common:passwordHash></common:passwordHash>
</common:user>
<software>
<softwareId></softwareId>
<softwareName></softwareName>
</software>
</TokenRequest>
我在包中指定了前缀-info.java
@javax.xml.bind.annotation.XmlSchema(elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = {
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://foo/3.0/api", prefix = ""),
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://foo/3.0/base", prefix = "base"),
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://foo/1.0/common", prefix = "common") })
package exp._3_0.api;
TokenRequest 元素实际上指的是命名空间=“http://foo/3.0/api”。在 xml 输出中,TokenRequest 没有任何正确的前缀,但 xmlns 设置为 ns4,这导致了以下错误。
Request body contains on line: [1] and column: [182] error:
[unexpected element (uri:"", local:"TokenRequest"). Expected elements
are <{http://foo/3.0/api}TokenRequest>]
即使在 package-info 中为命名空间“http://foo/3.0/api”指定了前缀 =“”,在输出中它仍然附加为 ns4。请帮助如何修复删除ns4。
如评论中所述,您的 @XmlSchema
缺少 namespace
属性,因此所有 @XmlRootElement
和 @XmlType
都被认为没有命名空间,除非 明确合格。您的 java-package.info
应如下所示:
@XmlSchema(elementFormDefault = XmlNsForm.QUALIFIED, namespace = "http://foo/3.0/api", xmlns = {
@XmlNs(namespaceURI = "http://foo/3.0/api", prefix = ""),
@XmlNs(namespaceURI = "http://foo/3.0/base", prefix = "base"),
@XmlNs(namespaceURI = "http://foo/1.0/common", prefix = "common")})
package exp._3_0.api;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
@XmlNs
注释 没有 指定 Java 包中使用的默认命名空间。他们仅向 JAXB 实现提供 建议 以分配给那些名称空间的前缀。在您的示例中,标签 <TokenRequest>
、<software>
、<softwareId>
和 <softwareName>
不属于任何命名空间,因此 JAXB 对这些元素使用空前缀并且必须使用另一个前缀( ns4
) 对于 http://foo/3.0/api
命名空间中的元素(没有)。
面临使用 JAXB 解组的问题。我需要使用多个名称空间。 Java classes 是为第三方提供的 XSD 生成的。所以我不想在 Java classes 中的 XMLRootElement 指定名称空间,也不想手动更改多个 classes.
编组逻辑如下:
private <R extends BasicResponseType, T extends BasicRequestType> R doPost(T request, String requestname) throws Exception {
if (jaxbContext == null)
jaxbContext = JAXBContext.newInstance(TokenRequest.class, TokenResponse.class,
BasicResponseType.class, GeneralErrorResponse.class);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
logXML(marshaller, request);
// POST to baseURL/requestname and show response
HttpURLConnection conn = openConnection("/" + requestname);
OutputStream os = conn.getOutputStream();
marshaller.marshal(request, os);
os.flush();
// Normaler Output oder Error liefern, je nach HTTP Response
InputStream is = null;
boolean ok = true;
if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
is = conn.getErrorStream();
ok = false;
} else {
is = conn.getInputStream();
}
R response = (R) unmarshaller.unmarshal(new StreamSource(is));
is.close();
conn.disconnect();
logXML(marshaller, response);
if (ok) {
return response;
} else {
throw new Exception(getMessages((GeneralErrorResponse) response));
}
}
xml元素classTokenRequest.java
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "")
@XmlRootElement(name = "TokenRequest")
public class TokenRequest
extends BasicInRequestType{ }
BasicInRequestType.java
package exp._3_0.api;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "BasicInRequestType", propOrder = {
"software"
})
@XmlSeeAlso({
TokenRequest.class
})
public class BasicInRequestType
extends BasicRequestType {
@XmlElement(required = true)
protected SoftwareType software;
/**
* Gets the value of the software property.
*
* @return
* possible object is
* {@link SoftwareType }
*
*/
public SoftwareType getSoftware() {
return software;
}
/**
* Sets the value of the software property.
*
* @param value
* allowed object is
* {@link SoftwareType }
*
*/
public void setSoftware(SoftwareType value) {
this.software = value;
}}
BasicRequestType.java
package exp._3_0.api;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlType;
@XmlAccessorType(XmlAccessType.FIELD)
propOrder = {
"header",
"user"
})
@XmlSeeAlso({
BasicInRequestType.class
})
public class BasicRequestType {
@XmlElement(required = true)
protected BasicHeaderType header;
@XmlElement(required = true)
protected UserHeaderType user;
@XmlType(name = "BasicRequestType", namespace = "http://foo/1.0/common",
/**
* Gets the value of the header property.
*
* @return
* possible object is
* {@link BasicHeaderType }
*
*/
public BasicHeaderType getHeader() {
return header;
}
/**
* Sets the value of the header property.
*
* @param value
* allowed object is
* {@link BasicHeaderType }
*
*/
public void setHeader(BasicHeaderType value) {
this.header = value;
}
/**
* Gets the value of the user property.
*
* @return
* possible object is
* {@link UserHeaderType }
*
*/
public UserHeaderType getUser() {
return user;
}
/**
* Sets the value of the user property.
*
* @param value
* allowed object is
* {@link UserHeaderType }
*
*/
public void setUser(UserHeaderType value) {
this.user = value;
}}
XML 输出:
<TokenRequest xmlns:common="http://foo/1.0/common" xmlns:ns4="http://foo/3.0/api" xmlns:base="http://foo/3.0/base">
<common:header>
<common:requestId></common:requestId>
<common:timestamp></common:timestamp>
</common:header>
<common:user>
<common:login></common:login>
<common:passwordHash></common:passwordHash>
</common:user>
<software>
<softwareId></softwareId>
<softwareName></softwareName>
</software>
</TokenRequest>
我在包中指定了前缀-info.java
@javax.xml.bind.annotation.XmlSchema(elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED, xmlns = {
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://foo/3.0/api", prefix = ""),
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://foo/3.0/base", prefix = "base"),
@javax.xml.bind.annotation.XmlNs(namespaceURI = "http://foo/1.0/common", prefix = "common") })
package exp._3_0.api;
TokenRequest 元素实际上指的是命名空间=“http://foo/3.0/api”。在 xml 输出中,TokenRequest 没有任何正确的前缀,但 xmlns 设置为 ns4,这导致了以下错误。
Request body contains on line: [1] and column: [182] error: [unexpected element (uri:"", local:"TokenRequest"). Expected elements are <{http://foo/3.0/api}TokenRequest>]
即使在 package-info 中为命名空间“http://foo/3.0/api”指定了前缀 =“”,在输出中它仍然附加为 ns4。请帮助如何修复删除ns4。
如评论中所述,您的 @XmlSchema
缺少 namespace
属性,因此所有 @XmlRootElement
和 @XmlType
都被认为没有命名空间,除非 明确合格。您的 java-package.info
应如下所示:
@XmlSchema(elementFormDefault = XmlNsForm.QUALIFIED, namespace = "http://foo/3.0/api", xmlns = {
@XmlNs(namespaceURI = "http://foo/3.0/api", prefix = ""),
@XmlNs(namespaceURI = "http://foo/3.0/base", prefix = "base"),
@XmlNs(namespaceURI = "http://foo/1.0/common", prefix = "common")})
package exp._3_0.api;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
@XmlNs
注释 没有 指定 Java 包中使用的默认命名空间。他们仅向 JAXB 实现提供 建议 以分配给那些名称空间的前缀。在您的示例中,标签 <TokenRequest>
、<software>
、<softwareId>
和 <softwareName>
不属于任何命名空间,因此 JAXB 对这些元素使用空前缀并且必须使用另一个前缀( ns4
) 对于 http://foo/3.0/api
命名空间中的元素(没有)。