2010-06-03 10 views
23

Mam raport, który ma podjąć kontrolę siatki i produkcji HTML. Jedna z kolumn w siatce może wyświetlać dowolną liczbę wartości lub <Any>. Kiedy to zostanie wyprowadzone do HTML, oczywiście kończy się pusta.Czy istnieje standardowa funkcja Delphi do usuwania kodu HTML?

Mogłabym prawdopodobnie napisać jakąś procedurę, żeby użyć StringReplace, aby zamienić ją w &lt;Any&gt;, aby poprawnie wyświetlić ten konkretny przypadek, ale sądzę, że prawdopodobnie jest gdzieś w RTL gdzieś już testowany i robi to dobrze. Czy ktoś wie, gdzie mogę go znaleźć?

+1

Sposób Delphi na ucieczkę z HTML ... Intraweb! ;-) – LachlanG

Odpowiedz

16

Mam 99% pewności, że taka funkcja nie istnieje w RTL (od Delphi 2009). Oczywiście - napisanie takiej funkcji jest trywialne.

Aktualizacja

HTTPUtil.HTMLEscape jest to, czego szukasz:

function HTMLEscape(const Str: string): string; 

nie odważył się opublikować kod tutaj (naruszenie praw autorskich, chyba), ale rutyna jest bardzo prosty. Koduje "<", ">", "&" i ""”, aby &lt;, &gt;, &amp; i &quot;. Zastępuje ono także znaki # 92, # 160 .. # 255 na dziesiętne kody, np &#92;.

Ten ostatni etap jest konieczne, jeśli plik jest UTF-8, a także nielogicznego, ponieważ wyższe znaków specjalnych, takich jak ∮ pozostały jako takie, podczas gdy niższe znaki specjalne takie jak krotne są kodowane.

Aktualizacja 2

W odpowiedzi na odpowiedź Stijn Sanders wykonałem prosty test wydajności.

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. 

Wyjście jest

532031 
801969 
2

I zazwyczaj wystarczy użyć tego kodu:

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; 

(? Autorskich jest open source)

+0

To wygląda * znacznie * wolniej niż zwykła pętla: dla i: = 1 do długości (dane) do przypadku ord (dane [i]) z ... –

+0

Właśnie przetestowałem to: zagnieżdżony ciągReplace: 801259 tyknięć. Pojedyncza pętla: 532037 znaczników. –

+0

Ale oczywiście * najprostsza * metoda zapętlenia zakończy się niepowodzeniem z # 13 # 10 ... –

12

Wydaje tutaj jest mały konkurs :) Oto jeszcze jedna implementacja:

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; 

Aktualizacja 1: Zaktualizowany początkowo podał nieprawidłowy kod.

Aktualizacja 2: a czasy:

HTMLEncode : 2286508597 
HTMLEncode2: 3577001647 
HTMLEncode3: 361039770 
+0

To bardzo dobre rozwiązanie! (Może trochę przesada!)) Głównym zyskiem prawdopodobnie nie jest ruch, ale fakt, że nie trzeba ciągle przyznawać więcej miejsca na wynik. Dałabym ci +1, chyba że byłaby to odpowiedź na pytanie! :) –

+0

Cóż, daję ci +1 tylko dlatego, że jest to piękny przykład optymalizacji. –

+0

(Przy okazji: wiesz, że istnieje subtelna różnica między "treścią" a "konkursem"? :)) –

2

Jednostka HTTPApp posiada funkcję o nazwie HtmlEncode. Ma również inne funkcje powiązane z HTML/HTTP.

+0

Jak już wskazano na długo przed ... –

+0

HTTPApp.HTMLEncode nie koduje prawidłowo ciągu znaków w Delphi 2009 i 2010 - http://qc.embarcadero.com /wc/qcmain.aspx?d=78903 – mjn

0

jak o tej drodze zastąpienia znaków specjalnych:

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

Funkcja standardowa jest specjalnie zadawana w tym pytaniu, więc twoja odpowiedź na nią nie odpowiada, niezależnie od tego, czy jest poprawna czy nie. – lukelazarovic

0

Moja funkcja łączy w pętli for z minimalną realokacji napisu:

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

nie wiem w której wersji go Delphi został wprowadzony, ale istnieje jednostka System.NetEncoding, która ma:

TNetEncoding.HTML.Encode 
TNetEncoding.HTML.Decode 

f unkcje. Przeczytaj artykuł here. Nie potrzebujesz już do tego zewnętrznych bibliotek.

Powiązane problemy