2010-06-03 32 views
23

Tôi đã có một báo cáo có nghĩa vụ phải kiểm soát lưới và tạo ra đầu ra HTML. Một trong các cột trong lưới có thể hiển thị bất kỳ số lượng giá trị nào hoặc <Any>. Khi điều này được đầu ra cho HTML, tất nhiên, nó kết thúc lên trống.Có chức năng chuẩn Delphi nào để thoát HTML không?

Tôi có thể viết một số thường lệ để sử dụng StringReplace để biến thành &lt;Any&gt; để nó hiển thị đúng trường hợp cụ thể này, nhưng tôi có lẽ có một trong RTL ở đâu đó đã được kiểm tra và làm đúng. Bất cứ ai biết nơi tôi có thể tìm thấy nó?

+1

Cách Delphi để thoát HTML ... Intraweb! ;-) – LachlanG

Trả lời

16

Tôi chắc chắn 99% rằng chức năng như vậy không tồn tại trong RTL (như của Delphi 2009). Tất nhiên - tuy nhiên - nó là tầm thường để viết một hàm như vậy.

Cập nhật

HTTPUtil.HTMLEscape là những gì bạn đang tìm kiếm:

function HTMLEscape(const Str: string): string; 

Tôi không dám công bố mã ở đây (vi phạm bản quyền, có lẽ), nhưng thói quen rất đơn giản. Nó mã hóa "<", ">", "&", và """ để &lt;, &gt;, &amp;&quot;. Nó cũng thay thế ký tự # 92, # 160 .. # 255 vào thập phân mã, ví dụ như &#92;.

bước sau này là không cần thiết nếu các tập tin là UTF-8, và cũng vô lý, bởi vì ký tự đặc biệt cao hơn, chẳng hạn như ∮ được trái như họ đang có, trong khi ký tự đặc biệt thấp hơn, chẳng hạn như ×, được mã hóa.

Cập nhật 2

Để trả lời câu trả lời của Stijn Sanders, tôi đã thực hiện một bài kiểm tra hiệu năng đơn giản.

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. 

Đầu ra là

532031 
801969 
2

Tôi thường chỉ cần sử dụng mã này:

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; 

(bản quyền nó open source?)

+0

Điều này có vẻ * nhiều * chậm hơn một vòng lặp đơn giản: cho i: = 1 đến độ dài (Dữ liệu) làm trường hợp thứ tự (Dữ liệu [i]) của ... –

+0

Tôi vừa thử nghiệm điều này: Nested StringReplace: 801259 ticks. Một vòng lặp đơn: 532037 bọ ve. –

+0

Nhưng tất nhiên, cách tiếp cận vòng lặp * rất đơn giản * sẽ không thành công với # 13 # 10 ... –

12

Có vẻ như đây là một cuộc thi nhỏ :) Dưới đây là một triển khai khác:

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; 

Cập nhật 1: Cập nhật ban đầu đã cung cấp mã không chính xác.

Cập nhật 2: Và lần:

HTMLEncode : 2286508597 
HTMLEncode2: 3577001647 
HTMLEncode3: 361039770 
+0

Đây là một giải pháp rất tốt đẹp! (Có lẽ một chút quá mức cần thiết! :)) Lợi ích chính có lẽ không phải là Di chuyển, nhưng thực tế là bạn không cần phải liên tục để phân bổ nhiều không gian hơn cho kết quả. Tôi sẽ cung cấp cho bạn một +1 trừ khi nó đã được cho một thực tế rằng nó không phải là một câu trả lời cho câu hỏi thực tế! :) –

+0

Vâng, tôi cung cấp cho bạn +1 chỉ vì đó là một ví dụ tuyệt vời về tối ưu hóa. –

+0

(Nhân tiện: bạn có biết có sự khác biệt nhỏ giữa "nội dung" và "cuộc thi" không? :)) –

2

Unit HTTPApp có một chức năng gọi là HTMLEncode. Nó cũng có các chức năng liên quan đến HTML/HTTP khác.

+0

Như đã được chỉ ra từ lâu trước đây ... –

+0

HTTPApp.HTMLEncode không mã hóa chính xác một chuỗi trong Delphi 2009 và 2010 - http://qc.embarcadero.com /wc/qcmain.aspx?d=78903 – mjn

0

thế nào về cách mà thay thế ký tự đặc biệt:

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

Chức năng tiêu chuẩn được hỏi cụ thể trong câu hỏi này nên câu trả lời của bạn không trả lời, bất kể nó có đúng hay không. – lukelazarovic

0

chức năng của tôi kết hợp cho vòng lặp với việc tái phân bổ tối thiểu của chuỗi:

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

Tôi không biết trong đó delphi phiên bản nó đã được giới thiệu nhưng, có đơn vị System.NetEncoding có:

TNetEncoding.HTML.Encode 
TNetEncoding.HTML.Decode 

f unctions. Đọc lên here. Bạn không cần thư viện bên ngoài nữa.

Các vấn đề liên quan