Como cortar uma parte de um córrego na Delphi7
Pergunta
Eu tenho uma mensagem SOAP de entrada wich forma é TStream (Delphi7), servidor que envia este sabão é no modo de desenvolvimento e adiciona um html cabeçalho para a mensagem para fins de depuração. Agora eu preciso para cortar a parte do cabeçalho html dele antes que eu possa passá-lo ao conversor de sabão. Ele começa desde o início com 'pré' tag e termina com '/ pre' tag. Im que pensam que deve ser bastante fácil, mas eu não fiz isso antes em Delphi7, então alguém pode me ajudar?
Solução
Eu acho que o código a seguir fazer o que quiser, desde que você só tem uma
bloco no documento.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;
Outra opção Acredito que seria a utilização de um xml transformar para remover as tags indesejadas, mas eu não faço muito na forma de transformações por isso, se ninguém quer que a tocha ...
EDIT: código corrigido para que ele funcione. ensina-me para a codificação diretamente no SO em vez de para o IDE em primeiro lugar.
Outras dicas
Outra solução, mais em linha com a sugestão de Lars e de alguma forma mais elaborada.
É mais rápido, especialmente quando o tamanho do fluxo está acima de 100, e mais ainda em realmente grandes. Ele evita a cópia de uma cadeia intermediária.
FilterBeginStream é mais simples e segue as "especificações" na remoção de tudo até o fim do cabeçalho.
FilterMiddleStream faz o mesmo que DepreStream, deixando o que é antes e depois do cabeçalho.
Aviso : este código é para Delphi até D2007, D2009 não.
// 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;
Faça um novo TStream (uso TMemoryStream) e mover qualquer coisa que você deseja manter ao longo de um fluxo para o outro com TStream.CopyFrom ou os métodos TStream.ReadBuffer / WriteBuffer.
Uma expressão XPath de "//pre[1][1]
" vai transportar para fora o primeiro nó da primeira
tag na mensagem XML:. A partir de sua descrição, que deve conter a mensagem SOAP que você desejaTem sido muitos anos desde a última vez usei, mas eu acho OpenXML oferece suporte biblioteca de Dieter Koehler XPath.