Как изменить сериализацию TXSDateTime SOAP в Delphi 7? - PullRequest
0 голосов
/ 01 июня 2010

Я пытаюсь использовать веб-сервис на основе Java и запрос на мыло:

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

Это не работает, потому что веб-сервис не распознает даты как параметры. Когда я меняю

      <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 голосов
/ 06 июня 2010

Я нашел решение. Я унаследовал от THttpRIO и, поскольку DoBeforeExecute равен virtual, я изменил его реализацию (DoBeforeExecute взят из Delphi 2007, который позволяет изменять XML в OnBeforeExecute). Затем я изменил свой автоматически сгенерированный из модуля 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.
0 голосов
/ 01 июня 2010

Вы можете перехватить XML перед десериализацией и отредактировать по своему вкусу с помощью stringreplace. Вам нужно подключиться к одному из событий RIO.

Обновление: подключитесь здесь: HTTPRIO1AfterExecute (const MethodName: строка; SOAPResponse: TStream);

SOAPResponse - это поток, с которым не так просто поиграться, как со строкой, но он, безусловно, можно изменить. Я могу опубликовать пример кода завтра днем.

Редактировать: OnAfterExecute присутствует в D2007 и более поздних версиях, и вы можете использовать его в D2005 с помощью источников SOAP D2007. Не уверен насчет D7! Вы можете быть SOL.

Редактировать: В D7 вы, вероятно, могли бы взломать код для предоставления собственного события OnAfterExecute. то есть измените rio.pas, чтобы включить обработчик для вас. Кроме того, распространенной ошибкой при работе с потоковым объектом является сбой при установке позиции на 0, когда вы закончите.

Редактировать: вы также можете редактировать запрос в BeforeExecute, хотя, возможно, не с кодом Delphi7. В D2010 (который я сейчас имею перед собой) SOAPRequest является потоком. В D2007 (с которым я много работал, но на самом деле использую код D2007 на D2005), я считаю, что это строка. В моем проекте D2005 / 2007 мы интенсивно редактируем запрос с помощью ряда операторов StringReplace () в OnBeforeExecute.

...