如何在Delphi 7中更改TXSDateTime SOAP序列化?

时间:2010-05-31 21:48:54

标签: delphi datetime soap xsd delphi-7

我正在尝试使用基于Java的webservice并有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" 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>

它不起作用,因为webservice不会将日期识别为参数。当我改变

      <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转换为<dateFrom,而不是<xsd:dateFrom代码?你遇到了这个问题吗?

2 个答案:

答案 0 :(得分:0)

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

更新:点击此处: HTTPRIO1AfterExecute(const MethodName:string; SOAPResponse:TStream);

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

编辑:OnDfterExecute出现在D2007及更高版本中,您可以使用D2007 SOAP源在D2005中使用它。关于D7不确定!你可能是SOL。

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

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

答案 1 :(得分:0)

我找到了解决方案。我继承自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.