2010-06-03 4 views
23

J'ai un rapport censé prendre un contrôle de grille et produire une sortie HTML. Une des colonnes de la grille peut afficher un nombre de valeurs, ou <Any>. Quand ceci est sorti en HTML, bien sûr, il finit vide.Existe-t-il une fonction standard Delphi pour échapper le HTML?

Je pourrais probablement écrire une routine pour utiliser StringReplace pour le transformer en &lt;Any&gt; afin qu'il affiche correctement ce cas particulier, mais je pense qu'il y en a probablement un dans la RTL qui a déjà été testé et qui fonctionne correctement. Quelqu'un sait où je pourrais le trouver?

+1

Un moyen Delphi pour échapper HTML ... Intraweb! ;-) – LachlanG

Répondre

16

Je suis sûr à 99% qu'une telle fonction n'existe pas dans le RTL (à partir de Delphi 2009). Bien sûr, cependant, il est trivial d'écrire une telle fonction.

Mise à jour

HTTPUtil.HTMLEscape est ce que vous recherchez:

function HTMLEscape(const Str: string): string; 

Je n'ose pas publier le code ici (violation du droit d'auteur, sans doute), mais la routine est très simple. Il code "<", ">", "&" et "" » à &lt;, &gt;, &amp; et &quot;. Il remplace également les caractères # 92, # 160 .. # 255 en décimal codes, par exemple &#92;.

Cette dernière étape est inutile si le fichier est UTF-8, et également illogique, parce que les caractères spéciaux plus élevés, tels que ∮ sont laissées telles quelles, tandis que des caractères spéciaux inférieurs, tels que x, sont codés.

Mise à jour 2

En réponse à la réponse de Stijn Sanders, j'ai fait un simple test de performance.

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. 

La sortie est

532031 
801969 
2

J'utilise généralement ce 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; 

(? Le droit d'auteur, il est open source)

+0

Cela semble * beaucoup * plus lent qu'une simple boucle: pour i: = 1 à longueur (Data) do cas ord (Data [i]) de ... –

+0

Je viens de tester ceci: Nested StringReplace: 801259 ticks. Une seule boucle: 532037 ticks. –

+0

Mais bien sûr, l'approche en boucle * la plus simple * échouera avec le # 13 # 10 ... –

12

Il semble ici est un petit concours :) Voici une implémentation supplémentaire:

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; 

Mise à jour 1: Mis à jour initialement fourni un code incorrect.

Mise à jour 2: Et les temps:

HTMLEncode : 2286508597 
HTMLEncode2: 3577001647 
HTMLEncode3: 361039770 
+0

C'est une très belle solution! (Peut-être un peu exagéré, cependant! :)) Le gain principal n'est probablement pas le Move, mais le fait que vous n'avez pas besoin d'allouer constamment plus d'espace pour le résultat. Je vous donnerais un +1 sauf si c'était pour le fait que ce n'est pas une réponse à la question réelle! :) –

+0

Eh bien, je vous donne +1 juste parce que c'est un bel exemple d'optimisation. –

+0

(Au fait: vous savez qu'il y a une différence subtile entre un "contenu" et un "concours"? :)) –

2

HTTPApp de l'unité a une fonction appelée HTMLEncode. Il a aussi d'autres fonctions liées au HTML/HTTP.

+0

Comme cela a été souligné depuis longtemps ... –

+0

HTTPApp.HTMLEncode ne code pas correctement une chaîne dans Delphi 2009 et 2010 - http://qc.embarcadero.com /wc/qcmain.aspx?d=78903 – mjn

0

que diriez-vous de cette façon de remplacer les caractères spéciaux:

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

La fonction standard est spécifiquement posée dans cette question afin que votre réponse n'y réponde pas, qu'elle soit correcte ou non. – lukelazarovic

0

Ma fonction combine la boucle for avec une nouvelle répartition minimale de la chaîne:

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

Je ne sais pas dans quelle version delphi il a été introduit, mais il y a l'unité System.NetEncoding qui présente:

TNetEncoding.HTML.Encode 
TNetEncoding.HTML.Decode 

f onctions. Lire here. Vous n'avez plus besoin de bibliothèques externes pour cela.

Questions connexes