Is there a Delphi standard function for escaping HTML?

I usually just use this code:

function HTMLEncode(Data:string):string;
begin
  Result:=
    StringReplace(
    StringReplace(
    StringReplace(
    StringReplace(
    StringReplace(
      Data,
      '&','&',[rfReplaceAll]),
      '<','&lt;',[rfReplaceAll]),
      '>','&gt;',[rfReplaceAll]),
      '"','&quot;',[rfReplaceAll]),
      #13#10,'<br />'#13#10,[rfReplaceAll]);
end;

(copyright? it's open source)


I am 99 % sure that such a function does not exist in the RTL (as of Delphi 2009). Of course - however - it is trivial to write such a function.

Update

HTTPUtil.HTMLEscape is what you are looking for:

function HTMLEscape(const Str: string): string;

I don't dare to publish the code here (copyright violation, probably), but the routine is very simple. It encodes "<", ">", "&", and """ to &lt;, &gt;, &amp;, and &quot;. It also replaces characters #92, #160..#255 to decimal codes, e.g. &#92;.

This latter step is unnecessary if the file is UTF-8, and also illogical, because higher special characters, such as ∮ are left as they are, while lower special characters, such as ×, are encoded.

Update 2

In response to the answer by Stijn Sanders, I made a simple performance test.

program Project1;

{$APPTYPE CONSOLE}

uses
  Windows, SysUtils;

var
  t1, t2, t3, t4: Int64;
  i: Integer;
  str: string;
const
  N = 100000;


function HTMLEncode(const Data: string): string;
var
  i: Integer;
begin

  result := '';
  for i := 1 to length(Data) do
    case Data[i] of
      '<': result := result + '&lt;';
      '>': result := result + '&gt;';
      '&': result := result + '&amp;';
      '"': result := result + '&quot;';
    else
      result := result + Data[i];
    end;

end;

function HTMLEncode2(Data: string):string;
begin
  Result:=
    StringReplace(
    StringReplace(
    StringReplace(
    StringReplace(
      Data,
      '&','&amp;',[rfReplaceAll]),
      '<','&lt;',[rfReplaceAll]),
      '>','&gt;',[rfReplaceAll]),
      '"','&quot;',[rfReplaceAll]);
end;

begin

  QueryPerformanceCounter(t1);
  for i := 0 to N - 1 do
    str := HTMLEncode('Testing. Is 3*4<3+4? Do you like "A & B"');
  QueryPerformanceCounter(t2);

  QueryPerformanceCounter(t3);
  for i := 0 to N - 1 do
    str := HTMLEncode2('Testing. Is 3*4<3+4? Do you like "A & B"');
  QueryPerformanceCounter(t4);

  Writeln(IntToStr(t2-t1));
  Writeln(IntToStr(t4-t3));

  Readln;


end.

The output is

532031
801969

It seems here is a small contest :) Here is a one more implementation:

function HTMLEncode3(const Data: string): string;
var
  iPos, i: Integer;

  procedure Encode(const AStr: String);
  begin
    Move(AStr[1], result[iPos], Length(AStr) * SizeOf(Char));
    Inc(iPos, Length(AStr));
  end;

begin
  SetLength(result, Length(Data) * 6);
  iPos := 1;
  for i := 1 to length(Data) do
    case Data[i] of
      '<': Encode('&lt;');
      '>': Encode('&gt;');
      '&': Encode('&amp;');
      '"': Encode('&quot;');
    else
      result[iPos] := Data[i];
      Inc(iPos);
    end;
  SetLength(result, iPos - 1);
end;

Update 1: Updated initially provided incorrect code.

Update 2: And the times:

HTMLEncode :   2286508597
HTMLEncode2:   3577001647
HTMLEncode3:    361039770