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

发布于 2025-01-01 05:14:44 字数 3952 浏览 0 评论 0原文

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

均被 Web 服务拒绝的所有元素。

我的配置

CastorMarshaller beanapplicationContext.xml

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

不添加命名空间(通过 namespaceMappingscastorMarshaller 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>

My Java application tries to get information from a webservice. The XML request needs to have the namespace specified in the XML root element (class name), but the namespace of the tags (class fields) need to be empty (null), otherwise the webservice rejects the request.

I have to use Spring 3.0 and Spring WS 2.0 with CastorMarshaller (currently using Castor version 1.3.1) to marshall/unmarshall my Java objects into/from XML.

Please note the __PREFIX__ and __NAMESPACE__ locations in following code snippets.

Desired marshalled output
(i.e. the desired generated SOAP request)

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

Currently marshalled output (i.e. the generated SOAP request)

Not adding the namespace

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

or adding the namespace to all elements

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

which are both rejected by the webservice.

My configuration

CastorMarshaller bean in applicationContext.xml

<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 file castor-mapping.xml

Not adding the namespace (namespace specified in the castorMarshaller bean through namespaceMappings should be added to the root)

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

or adding the namespace to all elements

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

明媚如初 2025-01-08 05:14:44

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

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

公共类 MyEndpointInterceptorAdapter 扩展
端点拦截器适配器{

<预><代码> @Override
公共布尔handleResponse(MessageContext msgContext,对象端点)抛出IOException {

WebServiceMessage 响应Msg = msgContext.getResponse();
SoapMessagesoapMsg = (SoapMessage)responseMsg;

if(soapMsg!=null){
SoapEnvelopesoapEnvelope=soapMsg.getEnvelope();

if(soapEnvelope!=null){

SoapBodysoapbody=soapEnvelope.getBody();

if(soapbody!=null){

源 bodySource=soapbody.getSource();
if(DOMSource 的 bodySource 实例){
DOMSource bodyDomSource=(DOMSource)bodySource;
节点bodyNode=bodyDomSource.getNode();

if(bodyNode!=null){
NodeList bodyNodeList=bodyNode.getChildNodes();

if(bodyNodeList.getLength()!=0){
元素根=(Element)bodyNodeList.item(0);
root.setAttribute("xmlns:ns", "YourURI");
root.setPrefix("ns");
}
}
}
}
}
}

返回真;
}

}

Since I am facing the same problem, a solution that I am considering is the following:

  1. Create a interceptor extending EndpointInterceptorAdapter
  2. Override handleResponse method
  3. Modify to soap message by directly access or using a transformer

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;
      }

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文