1

フォームが TStream (Delphi7) の着信 SOAP メッセージがあります。この SOAP を送信するサーバーは開発モードであり、デバッグ目的でメッセージに html ヘッダーを追加します。SOAP コンバーターに渡す前に、html ヘッダー部分を切り取る必要があります。「pre」タグで始まり、「/pre」タグで終わります。かなり簡単だと思いますが、Delphi7でこれまでやったことがないので、誰か助けてもらえますか?

4

4 に答える 4

2

Larsの提案に沿った別の解決策で、どういうわけかうまくいきました。
特に Stream のサイズが 100 を超える場合は高速であり、非常に大きなものではさらに高速です。中間文字列へのコピーを回避します。
FilterBeginStreamはより単純で、ヘッダーの最後まですべてを削除する「仕様」に従います。
FilterMiddleStreamは DepreStream と同じことを行い、ヘッダーの前後にあるものを残します。

警告: このコードは、D2009 ではなく、D2007 までの Delphi 用です。

// returns position of a string token (its 1st char) into a Stream. 0 if not found
function StreamPos(Token: string; AStream: TStream): Int64;
var
  TokenLength: Integer;
  StringToMatch: string;
begin
  Result := 0;
  TokenLength := Length(Token);
  if TokenLength > 0 then
  begin
    SetLength(StringToMatch, TokenLength);
    while AStream.Read(StringToMatch[1], 1) > 0 do
    begin
      if (StringToMatch[1] = Token[1]) and
         ((TokenLength = 1) or
          ((AStream.Read(StringToMatch[2], Length(Token)-1) = Length(Token)-1) and
           (Token = StringToMatch))) then
      begin
        Result := AStream.Seek(0, soCurrent) - (Length(Token) - 1); // i.e. AStream.Position - (Length(Token) - 1);
        Break;
      end;
    end;
  end;
end;

// Returns portion of a stream after the end of a tag delimited header. Works for 1st header.
// Everything preceding the header is removed too. Returns same stream if no valid header detected.
// Result is True if valid header found and stream has been filtered.
function FilterBeginStream(const AStartTag, AEndTag: string; const AStreamIn, AStreamOut: TStream): Boolean;
begin
  AStreamIn.Seek(0, soBeginning); // i.e. AStreamIn.Position := 0;
  Result := (StreamPos(AStartTag, TStream(AStreamIn)) > 0) and (StreamPos(AEndTag, AStreamIn) > 0);
  if Result then
    AStreamOut.CopyFrom(AStreamIn, AStreamIn.Size - AStreamIn.Position)
  else
    AStreamOut.CopyFrom(AStreamIn, 0);
end;

// Returns a stream after removal of a tag delimited portion. Works for 1st encountered tag.
// Returns same stream if no valid tag detected.
// Result is True if valid tag found and stream has been filtered.
function FilterMiddleStream(const AStartTag, AEndTag: string; const AStreamIn, AStreamOut: TStream): Boolean;
var
  StartPos, EndPos: Int64;
begin
  Result := False;
  AStreamIn.Seek(0, soBeginning); // i.e. AStreamIn.Position := 0;
  StartPos := StreamPos(AStartTag, TStream(AStreamIn));
  if StartPos > 0 then
  begin
    EndPos := StreamPos(AEndTag, AStreamIn);
    Result := EndPos > 0;
  end;
  if Result then
  begin
    if StartPos > 1 then
    begin
      AStreamIn.Seek(0, soBeginning); // i.e. AStreamIn.Position := 0;
      AStreamOut.CopyFrom(AStreamIn, StartPos - 1);
      AStreamIn.Seek(EndPos - StartPos + Length(AEndTag), soCurrent);
    end;
    AStreamOut.CopyFrom(AStreamIn, AStreamIn.Size - AStreamIn.Position);
  end
  else
    AStreamOut.CopyFrom(AStreamIn, 0);
end;
于 2008-11-06T00:27:33.707 に答える
1

ドキュメントに <pre> ブロックが 1 つしかないと仮定すると、次のコードで目的が達成されると思います。

function DepreStream(Stm : tStream):tStream;
var
  sTemp : String;
  oStrStm : tStringStream;
  i : integer;
begin
  oStrStm := tStringStream.create('');
  try
    Stm.Seek(0,soFromBeginning);
    oStrStm.copyfrom(Stm,Stm.Size);
    sTemp := oStrStm.DataString;
    if (Pos('<pre>',sTemp) > 0) and (Pos('</pre>',sTemp) > 0) then
      begin
        delete(sTemp,Pos('<pre>',sTemp),(Pos('</pre>',sTemp)-Pos('<pre>',sTemp))+6);
        oStrStm.free;
        oStrStm := tStringStream.Create(sTemp);
      end;
    Result := tMemoryStream.create;
    oStrStm.Seek(0,soFromBeginning);
    Result.CopyFrom(oStrStm,oStrStm.Size);
    Result.Seek(0,soFromBeginning);
  finally
    oStrStm.free;
  end;
end;

私が信じている別のオプションは、不要なタグを削除するためにxml変換を使用することですが、私は変換の方法で多くのことをしないので、他の誰かがそのトーチを望んでいる場合...

編集:動作するようにコードを修正しました。最初に IDE ではなく SO に直接コーディングする方法を教えてくれます。

于 2008-11-03T19:43:19.617 に答える
1

新しい TStream を作成し (TMemoryStream を使用)、TStream.CopyFrom または TStream.ReadBuffer/WriteBuffer メソッドを使用して、1 つのストリームから別のストリームに保持したいものを移動します。

于 2008-11-03T16:41:00.593 に答える
0

" " の XPath 式は//pre[1][1]、XML メッセージ内の最初の <pre> タグの最初のノードを引き出します: 説明から、必要な SOAP メッセージが含まれている必要があります。

最後に使用してから何年も経ちますが、Dieter Koehler のOpenXML ライブラリは XPath をサポートしていると思います。

于 2008-11-04T07:50:04.470 に答える