Spring和CastorMarshaller:将命名空间添加到XML根目录

时间:2012-01-29 17:05:11

标签: java xml spring xml-namespaces castor

我的Java应用程序尝试从Web服务获取信息。 XML请求需要在XML根元素(类名)中指定名称空间,但标记的名称空间(类字段)必须为空(null),否则Web服务会拒绝该请求。

我必须使用Spring 3.0和Spring WS 2.0与CastorMarshaller(目前使用Castor版本1.3.1)来将我的Java对象编组/解组到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 Mapping文件 castor-mapping.xml

不添加命名空间(通过castorMarshallernamespaceMappings bean中指定的命名空间应添加到根目录中)

<?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>

1 个答案:

答案 0 :(得分:2)

由于我遇到同样的问题,我正在考虑的解决方案如下:

  1. 创建一个扩展EndpointInterceptorAdapter的拦截器
  2. 覆盖handleResponse方法
  3. 通过直接访问或使用转换器修改为soap消息
  4.   

    公共类MyEndpointInterceptorAdapter扩展   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;
          }
    
    }