java - Spring 和 CastorMarshaller : add namespace to XML root

标签 java xml spring xml-namespaces castor

我的 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>

最佳答案

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

  1. 创建一个扩展 EndpointInterceptorAdapter 的拦截器
  2. 覆盖 handleResponse 方法
  3. 通过直接访问或使用转换器修改为 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/

相关文章:

java - Spring/Hibernate/appfuse 中的事务

java - Spring Boot 外部化属性不起作用

java - 根据时基设置时间选择器

Java while循环不循环

xml - 计算 XSLT 2.0 中变量中的字符数

xml - 解析 QName 失败

java - Spring 的 AspectJ NoSuchMethodError

java - 比较一个 ArrayList 并组合共同的元素

java - 如何比较java中数组中的空元素?

php - PHP无法访问SimpleXMLElement对象的Xpath节点