我正在尝试使用提供商公开的Web服务。提供者在他的结尾有一个严格的检查,请求xml不应该包含没有值的标签。
我正在使用Jax-WS。如果我没有在特定对象中设置值,则它将作为空标记发送,并且标记存在。 PFB这个例子说明了我的问题。
客户端XML:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:host="http://host.testing.webservice.com/">
<soapenv:Header/>
<soapenv:Body>
<host:testingMathod>
<arg0>
<PInfo>
<IAge>45</IAge>
<strName>Danny</strName>
</PInfo>
<strCorrId>NAGSEK</strCorrId>
<strIpAddress></strIpAddress>
</arg0>
</host:testingMathod>
</soapenv:Body>
</soapenv:Envelope>
在此,未给出IpAddress的值,因此发送了空标记。
因此请让我们知道在删除请求xml中的空标记时需要做些什么。 Handlerchain是同一个解决方案吗?
谢谢, 纳文。
答案 0 :(得分:8)
注意:我是EclipseLink JAXB (MOXy)主管,是JAXB (JSR-222)专家组的成员。
默认情况下,MOXy与其他JAXB实现一样,不会为空值编组元素:
可能出现的问题
我相信strIpAddress
属性不为null,但包含空字符串(“”)的值。这将导致写出空元素。
<强> 根 强>
package forum11215485;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
String nullValue;
String emptyStringValue;
String stringValue;
}
<强> 演示 强>
package forum11215485;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
Root root = new Root();
root.nullValue = null;
root.emptyStringValue = "";
root.stringValue = "Hello World";
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
<强> 输出 强>
请注意,nullValue
字段没有编组元素,并且emptyStringValue
字段被编组为空元素。
<?xml version="1.0" encoding="UTF-8"?>
<root>
<emptyStringValue></emptyStringValue>
<stringValue>Hello World</stringValue>
</root>
解决方案#1 - 确保该属性设置为null而不是“”
解决方案#2 - 编写一个将“”转换为null的XmlAdapter
XmlAdapter
是一种JAXB机制,允许将对象编组为另一个对象。
<强> StringAdapter 强>
以下XmlAdapter
将空字符串封送为null。这将导致它们不出现在XML表示中。
package forum11215485;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class StringAdapter extends XmlAdapter<String, String> {
@Override
public String unmarshal(String v) throws Exception {
return v;
}
@Override
public String marshal(String v) throws Exception {
if(null == v || v.length() == 0) {
return null;
}
return v;
}
}
<强> 包信息 强>
XmlAdapter
使用@XmlJavaTypeAdapter
注释。下面是一个在包级别挂钩的示例,以便它应用于包中String类型的字段/属性。有关详细信息,请参阅:http://blog.bdoughan.com/2012/02/jaxb-and-package-level-xmladapters.html
@XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
package forum11215485;
import javax.xml.bind.annotation.adapters.*;
<强> 输出 强>
现在运行演示代码的输出如下:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<stringValue>Hello World</stringValue>
</root>
答案 1 :(得分:1)
这是您正在使用的XML Serializer的问题(如果您没有做一些特殊的事情,它应该是JAXB)。
序列化程序的“空策略”应该是可配置的,但我认为JAXB是不可能的。如果使用MOXy,则可以使用XmlMarshalNullRepresentation.ABSENT_NODE
在节点为空时不写入节点。实现应该是这样的:
class MyClass {
// ... here are your other attributes
@XmlElement (name = "strIpAddress")
@XmlNullPolicy(nullRepresentationForXml = XmlMarshalNullRepresentation.ABSENT_NODE)
String strIpAddress = null;
}
PS:也许您还需要定义emptyNodeRepresentsNull
的{{1}}参数。
有关此主题的更多信息,请查看this question
答案 2 :(得分:0)
在序列化我无法使用注释(LogRecord
)的课程时,这对我有用:
JAXBContext jc = JAXBContext.newInstance(LogRecord.class);
JAXBElement<LogRecord> je = new JAXBElement<>(new QName("log"), LogRecord.class, record);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setAdapter(new XmlAdapter<String,String>() {
@Override
public String marshal(String v) throws Exception {
if(null == v || v.length() == 0) {
return null;
}
return v;
}
@Override
public String unmarshal(String v) throws Exception {
return v;
}
});
ByteArrayOutputStream xml = new ByteArrayOutputStream();
marshaller.marshal(je, xml);