如何避免SOAP请求XML中的特殊字符转义?
Java Axis SOAP客户端CDATA转义问题解决方案
问题核心
你手动拼接的CDATA字符串会被Axis当作普通文本转义特殊字符,最终生成的是<![CDATA[...]]>而非有效的CDATA节点,导致服务器无法解析。以下是针对性解决方案:
1. Axis禁用转义的配置方案
Axis没有直接禁用转义的系统属性,但可以通过自定义序列化器或直接操作DOM树实现CDATA节点的正确输出:
- 自定义序列化器:编写实现Axis
Serializer和SerializerFactory接口的CDATASerializer与CDATASerializerFactory,序列化时直接输出CDATA节点而非转义文本,再在Call对象中注册到目标字段类型:
Call call = service.createCall(); QName fieldQName = new QName("你的命名空间", "目标字段的类型名"); call.registerTypeMapping(String.class, fieldQName, new CDATASerializerFactory(), new CDATADeserializerFactory());
- 直接操作DOM树:绕开Axis自动序列化逻辑,手动构建CDATA节点插入SOAP消息:
SOAPEnvelope env = call.getMessageContext().getEnvelope(); SOAPElement targetField = env.getBody().getChildElements("目标字段元素名").next(); Text cdataNode = env.createCDATASection(你的JSON字符串); targetField.appendChild(cdataNode);
2. 替代SOAP库推荐
Axis已停止维护,换用现代库可更简单解决问题:
- Apache CXF:支持JAX-WS规范,在实体类字段上添加
@XmlCDATA注解即可自动生成CDATA节点,无额外转义。 - Spring Web Services:基于Spring的SOAP框架,通过配置Marshaller或使用
@XmlCDATA实现CDATA输出。 - Metro(JAX-WS RI):Java官方JAX-WS实现,原生支持
@XmlCDATA,配置成本低。
3. 其他包裹CDATA的方式
除上述方法外,还可:
- 直接生成包含正确CDATA节点的完整SOAP XML字符串,再通过Axis发送原始XML内容,绕开Axis的序列化逻辑。
- 使用Dom4j、JDOM等第三方XML工具构建含CDATA的XML片段,再注入到Axis的SOAP消息中。
4. 修改服务器适配的可行性
仅当你完全控制服务器代码时才考虑:需要服务器先对收到的转义文本进行反转义,再解析JSON。但这违背原有的XML约定,若服务器为第三方服务则无法实现,不推荐。
你遗漏的基础要点
手动拼接<![CDATA[...]]>字符串是无效的——Axis会把整个字符串当作普通XML文本处理,自动转义其中的<、>等特殊字符,最终生成的不是XML规范中的CDATA节点,而是转义后的文本,服务器自然无法识别。必须通过XML生成器的API创建CDATA节点,而非手动拼接字符串。
内容的提问来源于stack exchange,提问作者Andy
相关产品推荐
相关产品推荐

