开发者

Is there a Delphi standard function for escaping HTML?

开发者 https://www.devze.com 2023-01-02 17:37 出处:网络
I\'ve got a report that\'s supposed to take a grid control and pro开发者_高级运维duce HTML output.One of the columns in the grid can display any of a number of values, or <Any>.When this gets ou

I've got a report that's supposed to take a grid control and pro开发者_高级运维duce HTML output. One of the columns in the grid can display any of a number of values, or <Any>. When this gets output to HTML, of course, it ends up blank.

I could probably write up some routine to use StringReplace to turn that into &lt;Any&gt; so it would display this particular case correctly, but I figure there's probably one in the RTL somewhere that's already been tested and does it right. Anyone know where I could find it?


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


I usually just use this code:

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

(copyright? it's open source)


Unit HTTPApp has a function called HTMLEncode. It has also other HTML/HTTP related functions.


I dont know in which delphi version it was introduced but, there is the System.NetEncoding unit which has:

TNetEncoding.HTML.Encode
TNetEncoding.HTML.Decode

functions. Read up here. You dont need external libraries anymore for that.


From unit Soap.HTTPUtil or simply HTTPUtil for older delphi versions, you can use

function HTMLEscape(const Str: string): string;
var
  i: Integer;
begin
  Result := '';
  for i := Low(Str) to High(Str) do
  begin
    case Str[i]  of
    '<' : Result := Result + '&lt;';    { Do not localize }
    '>' : Result := Result + '&gt;';    { Do not localize }
    '&' : Result := Result + '&amp;';   { Do not localize }
    '"' : Result := Result + '&quot;';  { Do not localize }
{$IFNDEF UNICODE}
    #92, Char(160) .. #255 : Result := Result + '&#' + IntToStr(Ord(Str[ i ])) +';';  { Do not localize }
{$ELSE}
    // NOTE: Not very efficient
    #$0080..#$FFFF : Result := Result + '&#' + IntToStr(Ord(Str[ i ])) +';'; { Do not localize }
{$ENDIF}
    else
      Result := Result + Str[i];
    end;
  end;
end;


how about that way of replacing special characters:

    function HtmlWeg(sS: String): String;
var
  ix,cc: Integer;
  sC, sR: String;
begin
  result := sS;
  ix := pos('\u00',sS);

  while ix >0 do
  begin
    sc := copy(sS,ix+4,2) ;
    cc := StrtoIntdef('$' +sC,32);
    sR := '' + chr(cc);
    sS := Stringreplace(sS, '\u00'+sC,sR,[rfreplaceall]) ;
    ix := pos('\u00',sS);
  end;
  result := sS;
end;


My function combines the for-loop with a minimal reallocation of the string:

function HtmlEncode(const Value: string): string;
var
  i: Integer;

begin
  Result := Value;
  i := 1;

  while i <= Length(Result) do
  begin
    if Result[i] = '<' then
    begin
      Result[i] := '&';
      Insert('lt;', Result, i + 1);
      Inc(i, 4);
    end
    else if Result[i] = '>' then
    begin
      Result[i] := '&';
      Insert('gt;', Result, i + 1);
      Inc(i, 4);
    end
    else if Result[i] = '"' then
    begin
      Result[i] := '&';
      Insert('quot;', Result, i + 1);
      Inc(i, 6);
    end
    else if Result[i] = '&' then
    begin
      Insert('amp;', Result, i + 1);
      Inc(i, 5);
    end
    else
      Inc(i);
  end;
end;


in delphi You have the function

THTMLEncoding.HTML.Encode
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号