代码之家  ›  专栏  ›  技术社区  ›  Wim ten Brink

从SOAP请求中删除命名空间

  •  10
  • Wim ten Brink  · 技术社区  · 14 年前

    我已经导入了一个WSDL并使用它发送一个SOAP请求。看起来是这样的:

    <?xml version="1.0"?>
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <SOAP-ENV:Body>
            <Calculate xmlns="urn:xx.WSDL.xxxxxWebService">
                <ContractdocumentIn>
                    <AL>
                    ...More XML...
    

    xmlns="urn:xx.WSDL.xxxxxWebService" 计算元素的一部分。web服务无法接受此操作。web服务不喜欢这样的名称空间。。。
    SoapUI 我觉得这个请求很好:

    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope" xmlns:col="http://example.com.service.xxx/">
        <SOAP-ENV:Body>
            <col:Calculate>
                <ContractdocumentIn>
                    <AL>
                        ...More XML...
    

    那么,如何将请求从第一个版本更改为第二个版本?(不使用肮脏的伎俩!)




    再次声明:不允许使用肮脏的伎俩,比如入侵请求流来修改它!


    虽然我还没有完全测试过它,但似乎C/VS2010和Delphi2010也无法使用我试图调用的web服务。似乎是用Java编写的web服务。 索皮
    无论如何,是时候再添加两个标记了:“Java”,因为它是一个Java服务,而“vs2010”因为.NET也不喜欢这个服务。
    我正准备在.NET中为这个服务编写一个包装器,希望它能起作用。。。它没有。所以这是一个非常严重的缺陷,可能是一个Java缺陷。。。

    2 回复  |  直到 14 年前
        1
  •  14
  •   BruneauB    14 年前

    如果服务需要:

      <col:Calculate>
         <ContractdocumentIn>
             <AL>
    

    德尔菲索普正在发送。。。

        <Calculate xmlns="urn:xx.WSDL.xxxxxWebService">
            <ContractdocumentIn>
                <AL>
    

    ... 问题是ContractdocumentIn是一个不合格的元素,并且(直到Delphi XE)Delphi SOAP不支持作为操作顶级元素的不合格元素。顶层元素是函数的参数,没有地方存储底层元素必须是非限定的这一事实;对于映射到属性的元素,我们使用属性的索引来存储is-UNQL标志。

    顺便说一下,不必使用前缀。服务还应接受:

        <Calculate xmlns="urn:xx.WSDL.xxxxxWebService">
            <ContractdocumentIn xmlns="">
                <AL>
    

    在Delphi XE中,导入程序存储了这样一个事实:一个特定的参数映射到一个不合格的元素,而运行时对这个信息进行操作。我已经在新闻组发布了基于D2010和D2007的XE实现的补丁,当它最近出现在一个线程中时:

    https://forums.embarcadero.com/thread.jspa?threadID=43057

    如果有人需要访问他们(他们在附件区,但可能已经滚动了),请给我发电子邮件,我会让他们可用。[在embarcadero.com上的标签]

    文莱

        2
  •  8
  •   Wim ten Brink    14 年前


    首先,我导入WSDL,正如预期的那样。这将生成几个可震动类。然后,对于每个需要不同名称空间的TRemotable,我重写ObjectToSOAP()方法!(并将XMLIntf包含到WSDL源中。)在我的例子中,对于几种可远程类型的代码是这样的:

    function AL2.ObjectToSOAP( RootNode, ParentNode: IXMLNode; const ObjConverter: IObjConverter; const NodeName, NodeNamespace, ChildNamespace: InvString; ObjConvOpts: TObjectConvertOptions; out RefID: InvString ): IXMLNode;
    begin
      Result := inherited ObjectToSOAP( RootNode, ParentNode, ObjConverter, NodeName, '', '', ObjConvOpts, RefID );
    end;
    

    function ContractdocumentInType.ObjectToSOAP(RootNode, ParentNode: IXMLNode; const ObjConverter: IObjConverter; const Name, URI: InvString; ObjConvOpts: TObjectConvertOptions; out RefID: InvString): IXMLNode;
    
      procedure AlterChildren(Child: IXMLNode);
      var
        I: Integer;
      begin
        if (Child.NodeType = ntElement) then Child.SetAttributeNS('xmlns', '', '');
        for I := 0 to Pred(Child.ChildNodes.Count) do
          AlterChildren(Child.ChildNodes[I]);
      end;
    
    begin
      Result := inherited ObjectToSOAP(RootNode, ParentNode, ObjConverter, Name, '', ObjConvOpts, RefID);
      AlterChildren(Result);
    end;
    

    在我看来,这是一种黑客行为。但不是很脏。这是一点尝试,捕获SOAP请求和响应来检查它们的内容并查看它是否使用了正确的名称空间。不幸的是,DelphiXE在这方面做得比Delphi2007好得多。

    尽管如此,我还是对这个问题持开放态度,以寻求更好的解决方案。。。


    顺便说一下,添加 col: 对于输出,我还必须更改WSDL中的这一行 RemClassRegistry.RegisterXSClass(Calculate, 'http://colan.ogconnect.service.wzp/', 'Calculate'); 对此: RemClassRegistry.RegisterXSClass(Calculate, 'http://colan.ogconnect.service.wzp/', 'cal:Calculate'); . 结果就变成 <cal:Calculate xmlns:cal="http://example.webservice/"> xmlns:cal 到xml头。但现在,它对我很管用。


    另一个注意:对于WSDL,我使用了以下设置:“一个Outparam是return”、“展开文字参数”、“生成析构函数”、“警告注释” 发出文本类型 '将字符串映射到widestring'。其他选项包括:“生成有关类型和接口的详细信息”、“忽略具有HTTP绑定的端口类型”、“验证枚举成员”、“导入错误类型”、“导入头类型”、“包含的进程和导入的架构”、“将类别名生成为类类型”、“允许输出参数”和“进程nillable和可选元素”。这个 发出文本类型
    信封本身的创建在SOAPEnv单元中,并在optosapdomconv单元中使用。不幸的是,我还没有找到一个简单的方法来访问信封本身来更改头以添加这个额外的名称空间。然后,我可以用自己的版本重写TSOAPDomConv类,该版本添加了额外的名称空间。但是代码现在对我有用,正如我父亲告诉我的,当他学会我编程时:永远不要修复任何没有损坏的东西。