【问题标题】:How to change TXSDateTime SOAP serialization in Delphi 7?如何在 Delphi 7 中更改 TXSDateTime SOAP 序列化?
【发布时间】:2010-05-31 21:48:54
【问题描述】:

我正在尝试使用基于 Java 的 web 服务并有肥皂请求:

<?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" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body xmlns:NS1="http://something/">
    <NS1:getRequest id="1">
      <sessionId xsi:type="xsd:string"></sessionId>
      <reportType xsi:type="NS1:reportType">ALL</reportType>
      <xsd:dateFrom xsi:type="xsd:dateTime">2010-05-30T23:29:43.088+02:00</xsd:dateFrom>
      <xsd:dateTo xsi:type="xsd:dateTime">2010-05-31T23:29:43.728+02:00</xsd:dateTo>
    </NS1:getRequest>
    <parameters href="#1" />
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

它不起作用,因为 web 服务不将日期识别为参数。当我改变时

      <xsd:dateFrom xsi:type="xsd:dateTime">2010-05-30T23:29:43.088+02:00</xsd:dateFrom>
      <xsd:dateTo xsi:type="xsd:dateTime">2010-05-31T23:29:43.728+02:00</xsd:dateTo>

      <dateFrom xsi:type="xsd:dateTime">2010-05-30T23:29:43.088+02:00</xsd:dateFrom>
      <dateTo xsi:type="xsd:dateTime">2010-05-31T23:29:43.728+02:00</xsd:dateTo>

一切正常,但 Delphi(无需更改 Delphi 源代码)不允许更改生成的 XML,它只有一些选项。是否可以设置转换选项,使TSXDateTime 转换为&lt;dateFrom,而不是&lt;xsd:dateFrom 标记?你遇到过这个问题吗?

【问题讨论】:

    标签: delphi datetime soap xsd delphi-7


    【解决方案1】:

    您可以在反序列化之前拦截 XML 并使用 stringreplace 编辑您喜欢的内容。您需要挂钩其中一个 RIO 事件。

    更新:在这里挂钩: HTTPRIO1AfterExecute(const MethodName: string; SOAPResponse: TStream);

    SOAPResponse 是一个流,不像字符串那么容易处理,但它绝对是可修改的。明天下午我可以发布一些示例代码。

    编辑:OnAfterExecute 出现在 D2007 及更高版本中,您可以通过使用 D2007 SOAP 源在 D2005 中使用它。不知道D7!你可能是 SOL。

    编辑:在 D7 上,您可能会破解代码以提供您自己的 OnAfterExecute 事件。即修改 rio.pas 以包含您的处理程序。此外,使用流对象时的一个常见错误是完成后无法将位置重置为 0。

    编辑:您也可以在 BeforeExecute 中编辑请求,尽管可能不使用 Delphi7 代码。在 D2010(现在摆在我面前)中,SOAPRequest 是一个流。在 D2007(我已经广泛使用,但实际上在 D2005 上使用 D2007 代码)中,我相信它是一个字符串。在我的 D2005/2007 项目中,我们使用 OnBeforeExecute 中的一系列 StringReplace() 语句对请求进行了广泛的编辑。

    【讨论】:

    • 在哪里?这不可能。我写了关于它的问题。 THTTPRIO 具有 OnBeforeExecute 事件,它甚至具有声明为 var 的 xml 参数,但它仍然不可更改。如果您查看 Delphi 源代码,甚至还有关于它的注释。
    • 对不起,OnAfterExecute 发生在方法执行之后,所以没有什么可以改变的。 OnAfterExecute 包含响应的 xml,我想更改请求。
    • @LukLed - 对此感到抱歉。请参阅我最后添加的内容,以使用 BeforeExecute 编辑 XML。这在 D7 中可能不起作用,但在 D2005 及更高版本中可用。您可以修改源以允许编辑该字符串/流。
    • OnBeforeExecute 不允许更改 D7 中的 xml。我可以更改 Delphi 源代码,但我不想这样做。我正在寻找其他解决方案,可能是 THTTPRIO 的设置。
    【解决方案2】:

    我找到了解决方案。我继承自 THttpRIO 并且因为 DoBeforeExecutevirtual,所以我更改了它的实现(DoBeforeExecute 取自 Delphi 2007,它允许更改 OnBeforeExecute 中的 xml)。然后我将自动生成的 WSDL 单元更改为使用 TMyHttpRIO:

    unit MyHttpRIO;
    
    interface
    
    uses
      RIO, Classes, SOAPHTTPClient;
    
    type
      TMyHttpRIO = class(THttpRIO)
        procedure DoBeforeExecute(const MethodName: string; Request: TStream); override;
      private
      end;
    
    implementation
    
    { TMyHttpRIO }
    
    procedure TMyHttpRIO.DoBeforeExecute(const MethodName: string;
      Request: TStream);
    var
      StrStrm: TStringStream;
      SavedRequest: WideString;
      ReqWideStr: WideString;
    begin
      if Assigned(OnBeforeExecute) then
      begin
        { Ideally we would change the signature of this event to take a Stream.
          The change to stream was necessary for attachment and encoding support.
          And it makes the event consistent.... However, for the sake of
          backward compatibility.... }
        StrStrm := TStringStream.Create('');
        try
          StrStrm.CopyFrom(Request, 0);
          Request.Position := 0;
          ReqWideStr := UTF8Decode(StrStrm.DataString);
          SavedRequest := ReqWideStr;
          OnBeforeExecute(MethodName, ReqWideStr);
        finally
          StrStrm.Free;
        end;
        if (Length(SavedRequest) <> Length(ReqWideStr)) or (SavedRequest <> ReqWideStr) then
        begin
          // Copy changes made to ReqWideStr in the event back to the Request stream
          StrStrm := TStringStream.Create(string(ReqWideStr));
          try
            StrStrm.Position := 0;
            Request.Size := 0;
            Request.CopyFrom(StrStrm, 0);
            Request.Position := 0;
          finally
            StrStrm.Free;
          end;
        end;
      end;
    end;
    
    end.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-02
      • 1970-01-01
      • 2016-03-31
      相关资源
      最近更新 更多