我的 Java 应用程序试图从网络服务获取信息。 XML 请求需要在 XML 根元素(类名)中指定命名空间,但标签(类字段)的命名空间需要为空(null),否则 webservice 将拒绝请求。
我必须将 Spring 3.0 和 Spring WS 2.0 与 CastorMarshaller(目前使用 Castor 1.3.1 版)结合使用,以便将我的 Java 对象编码到 XML 中/从 XML 中解码。
请注意以下代码片段中的 __PREFIX__
和 __NAMESPACE__
位置。
所需的编码输出 (即所需的生成的 SOAP 请求)
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" />
<soap-env:Body xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<__PREFIX__:className xmlns:__PREFIX__="__NAMESPACE__">
<fieldName>fieldValue</fieldName>
</__PREFIX__:className>
</soap-env:Body>
</soap-env:Envelope>
当前编码输出(即生成的 SOAP 请求)
不添加命名空间
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" />
<soap-env:Body xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<className>
<fieldName>fieldValue</fieldName>
</className>
</soap-env:Body>
</soap-env:Envelope>
或者给所有元素添加命名空间
<?xml version="1.0" encoding="UTF-8"?>
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/" />
<soap-env:Body xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<__PREFIX__:className xmlns:__PREFIX__="__NAMESPACE__">
<__PREFIX__:fieldName xmlns:__PREFIX__="__NAMESPACE__">fieldValue</__PREFIX__:fieldName>
</__PREFIX__:className>
</soap-env:Body>
</soap-env:Envelope>
都被网络服务拒绝了。
我的配置
applicationContext.xml
中的CastorMarshaller bean
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller">
<property name="mappingLocation" value="classpath:castor-mapping.xml" />
<property name="ignoreExtraAttributes" value="true" />
<property name="ignoreExtraElements" value="true" />
<property name="namespaceMappings">
<map>
<entry key="__PREFIX__" value="__NAMESPACE__" />
</map>
</property>
</bean>
Castor 映射文件 castor-mapping.xml
不添加命名空间(在 castorMarshaller
bean 中通过 namespaceMappings
指定的命名空间应该添加到根)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.org/mapping.dtd">
<mapping>
<class name="some.package.ClassName">
<map-to xml="className">
<field name="fieldName" type="string">
<bind-xml name="fieldName" node="element" />
</field>
</class>
</mapping>
或者给所有元素添加命名空间
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapping PUBLIC "-//EXOLAB/Castor Mapping DTD Version 1.0//EN"
"http://castor.org/mapping.dtd">
<mapping>
<class name="some.package.ClassName">
<map-to xml="className" ns-uri="__NAMESPACE__" ns-prefix="__PREFIX__">
<field name="fieldName" type="string">
<bind-xml name="fieldName" node="element" />
</field>
</class>
</mapping>
最佳答案
由于我面临着同样的问题,我正在考虑的解决方案如下:
- 创建一个扩展 EndpointInterceptorAdapter 的拦截器
- 覆盖 handleResponse 方法
- 通过直接访问或使用转换器修改为 soap 消息
public class MyEndpointInterceptorAdapter extends EndpointInterceptorAdapter{
@Override public boolean handleResponse(MessageContext msgContext, Object endpoint) throws IOException { WebServiceMessage responseMsg = msgContext.getResponse(); SoapMessage soapMsg = (SoapMessage) responseMsg; if(soapMsg!=null){ SoapEnvelope soapEnvelope=soapMsg.getEnvelope(); if(soapEnvelope!=null){ SoapBody soapbody=soapEnvelope.getBody(); if(soapbody!=null){ Source bodySource=soapbody.getSource(); if(bodySource instanceof DOMSource){ DOMSource bodyDomSource=(DOMSource)bodySource; Node bodyNode=bodyDomSource.getNode(); if(bodyNode!=null){ NodeList bodyNodeList=bodyNode.getChildNodes(); if(bodyNodeList.getLength()!=0){ Element root=(Element)bodyNodeList.item(0); root.setAttribute("xmlns:ns", "YourURI"); root.setPrefix("ns"); } } } } } } return true; } }
关于java - Spring 和 CastorMarshaller : add namespace to XML root,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9054959/