2010-06-03 88 views
23

我有一個報告,應該採取網格控制並生成HTML輸出。網格中的一列可以顯示任意數量的值,或<Any>。當它輸出到HTML時,當然它最終會變成空白。是否有用於轉義HTML的Delphi標準函數?

我可能會寫一些例程來使用StringReplace將其轉換爲&lt;Any&gt;,以便它能夠正確顯示此特定情況,但是我認爲RTL中可能有一個已經過測試並且正確的RTL。任何人都知道我在哪裏可以找到它?

+1

德爾福方式逃脫HTML ... intraweb! ;-) – LachlanG 2010-06-04 04:07:51

回答

16

我99%確定這樣的函數在RTL中不存在(截至Delphi 2009)。當然 - 然而,編寫這樣一個函數是微不足道的。

更新

HTTPUtil.HTMLEscape是你正在尋找:

function HTMLEscape(const Str: string): string; 

我不敢在這裏發佈的代碼(侵犯版權,可能),但例程非常簡單。它編碼 ​​「<」, 「>」, 「&」,和 「」」來&lt;&gt;&amp;,和&quot;,還替換字符#92,#160 ..#255爲十進制碼,例如&#92;

後者步驟是不必要的,如果該文件是UTF-8,和還不合邏輯,因爲較高的特殊字符,如∮被原樣保留,而較低的特殊字符,如×,進行編碼。

更新2

爲了迴應Stijn Sanders的回答,我做了一個簡單的性能測試。

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. 

輸出是

532031 
801969 
2

我通常只使用此代碼:

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; 

(?版權是open source

+0

這看起來* *比一個簡單的循環慢:對於I:= 1到長度(Data)do case ord(Data [i])... – 2010-06-03 19:06:59

+0

我剛剛測試了這個:嵌套StringReplace:801259滴答。單循環:532037滴答。 – 2010-06-03 19:14:55

+0

但是,當然,最簡單的循環方法將會失敗,#13#10 ... – 2010-06-03 19:21:00

12

看來這裏是一個小比賽:)這裏是一個更多的實現:

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; 

更新1:更新最初提供了不正確的代碼。

更新2:與時代:

HTMLEncode : 2286508597 
HTMLEncode2: 3577001647 
HTMLEncode3: 361039770 
+0

這是一個非常好的解決方案! (雖然也許有點矯枉過正!:)) 主要的收益可能不是移動,但事實上,你不需要不斷地爲結果分配更多的空間。我會給你一個+1,除非它是因爲它不是對實際問題的回答! :) – 2010-06-04 11:55:06

+0

那麼,我給你+1,只是因爲它是一個優化的例子。 – 2010-06-04 13:00:58

+0

(順便說一下:你知道「內容」和「比賽」之間有細微差別嗎?:)) – 2010-06-04 13:26:24

2

單位HTTPApp有一個稱爲的HTMLEncode功能。它還有其他HTML/HTTP相關功能。

+0

正如前面已經指出的那樣... – 2010-06-04 11:54:39

+0

HTTPApp.HTMLEncode在Delphi 2009和2010中沒有正確編碼字符串 - http://qc.embarcadero.com /wc/qcmain.aspx?d=78903 – mjn 2013-04-11 05:50:00

0

怎麼樣的替代特殊字符的方式:

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; 
+0

在這個問題中特別詢問標準函數,以便您的答案不會回答它,而不管它是否正確。 – lukelazarovic 2015-09-09 13:34:17

0

我的功能相結合的for循環用字符串的最小再分配:

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

我不知道在哪個德爾福版本,它但有,System.NetEncoding單位有:

TNetEncoding.HTML.Encode 
TNetEncoding.HTML.Decode 

f unctions。閱讀here。你不需要外部庫了。

相關問題