Question

Je reçois un message SOAP entrant sous la forme TStream (Delphi7), le serveur qui envoie ce savon est en mode de développement et ajoute un en-tête HTML au message à des fins de débogage. Maintenant, je dois couper la partie en-tête HTML avant de pouvoir la passer au convertisseur de savon. Il commence par le début avec la balise 'pre' et se termine par la balise '/ pre'. Je pense que cela devrait être assez facile mais je ne l’ai jamais fait auparavant dans Delphi7, alors quelqu'un peut-il m'aider?

Était-ce utile?

La solution

Je pense que le code suivant ferait ce que vous voulez, en supposant que vous n’ayez qu’un < pre > bloquer dans votre document.

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;

Je pense qu'une autre option serait d'utiliser une transformation XML pour supprimer les balises indésirables, mais je ne fais pas beaucoup de transformations, donc si quelqu'un d'autre veut ce flambeau ...

EDIT: corrigé le code pour qu'il fonctionne. M'apprend à coder directement dans SO plutôt que dans l'IDE en premier.

Autres conseils

Une autre solution, plus conforme à la suggestion de Lars et plus élaborée.
C'est plus rapide, surtout lorsque la taille du Stream est supérieure à 100, et encore plus pour les très gros. Cela évite de copier dans une chaîne intermédiaire.
FilterBeginStream est plus simple et respecte les & spécifications; & "; en supprimant tout jusqu'à la fin de l'en-tête.
FilterMiddleStream fait la même chose que DepreStream, laissant ce qui se trouve avant et après l'en-tête.

Avertissement : ce code concerne Delphi jusqu'à D2007 et non D2009.

// 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;

Créez un nouveau TStream (utilisez TMemoryStream) et déplacez tous les éléments que vous souhaitez conserver d'un flux à l'autre avec les méthodes TStream.CopyFrom ou TStream.ReadBuffer / WriteBuffer.

Une expression XPath de " //pre[1][1] " va sortir le premier noeud du premier < pre > balise dans le message XML: à partir de votre description, elle doit contenir le message SOAP souhaité.

Cela fait plusieurs années que je ne l'utilise pas pour la dernière fois, mais je pense que la bibliothèque OpenXML de Dieter Koehler prend en charge XPath.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top