2009-03-12 11 views
14

Esiste una funzione per codificare stringhe HTML in T-SQL? Ho un database precedente che contiene personaggi di scherma come '<', '>' ecc. Posso scrivere una funzione per sostituire i caratteri ma c'è un modo migliore?Codifica HTML in T-SQL?

Ho un'applicazione ASP.Net e quando restituisce una stringa contiene caratteri che causano un errore. L'applicazione ASP.Net sta leggendo i dati da una tabella di database. Non scrive sul tavolo stesso.

+0

Le risposte seguenti sono buone, ma se questi caratteri non dovessero essere nei dati, suggerirei di pulire i dati. Altrimenti James è perfetto. – Lazarus

+0

I caratteri sono corretti nei dati e se modifico i dati potrei interrompere l'app legacy. Quindi questa non è un'opzione. –

+1

Se il tuo problema è nel tuo codice ASP.NET, il modo migliore per gestirlo è utilizzare la funzione Server.HtmlEncode() nel livello ASP.NET. Tecnicamente, non è necessario memorizzare i dati "elaborati" nel DB, si desidera che i dati semplici e reali non siano personalizzati per un particolare sistema di presentazione (HTML).Se a un certo punto hai avuto bisogno solo del testo normale senza entità HTML, ne hai ancora una versione pulita nel tuo DB. – Steve

risposta

20

Abbiamo un sistema legacy che utilizza un trigger e dbmail per inviare email codificate in HTML quando viene inserita una tabella, quindi è necessaria la codifica all'interno della generazione della posta elettronica. Ho notato che la versione di Leo ha un leggero bug che codifica il & in &lt; e &gt; io uso questa versione:

CREATE FUNCTION HtmlEncode 
(
    @UnEncoded as varchar(500) 
) 
RETURNS varchar(500) 
AS 
BEGIN 
    DECLARE @Encoded as varchar(500) 

    --order is important here. Replace the amp first, then the lt and gt. 
    --otherwise the &lt will become &amp;lt; 
    SELECT @Encoded = 
    Replace(
    Replace(
     Replace(@UnEncoded,'&','&amp;'), 
    '<', '&lt;'), 
    '>', '&gt;') 

    RETURN @Encoded 
END 
GO 
+0

Grazie, sei corretto. L'ho fatto in produzione ma ho dimenticato di aggiornare il post precedente. –

+1

@ Beniamino: Mentre elimina i più pericolosi caratteri XML, in realtà è lontano da "Html-Encoded", ma immagino tu sappia che sei tu :) –

14

Non è necessario correggere la stringa in SQL. Un modo migliore è utilizzare una funzione in ASP.net denominata HtmlEncode, in questo modo verranno cuciti i caratteri speciali che causano i problemi che stai vedendo vedere l'esempio di seguito. Spero che aiuti.

string htmlEncodedStr = System.Web.HttpUtility.HtmlEncode(yourRawStringVariableHere); 
string decodedRawStr = System.Web.HttpUtility.HtmlDecode(htmlEncodedStr); 

Edit: Dal momento che sei l'associazione di dati questo da un DataTable. Utilizzare un'espressione incorporata per chiamare HTMLEncode nel markup di GridView o qualsiasi altra cosa controlli l'utilizzo e questo soddisferà comunque i requisiti di associazione dei dati. Vedi l'esempio qui sotto. In alternativa è possibile eseguire il ciclo di ogni record nell'oggetto tabella di dati e aggiornare ogni cella con la stringa codificata in html prima dell'associazione dati.

<%# System.Web.HttpUtility.HtmlEncode(Eval("YourColumnNameHere")) %> 
+0

È inoltre possibile utilizzare un BoundField. http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.boundfield.aspx – bobince

+0

Sì, è vero. – James

2

Se si sta visualizzando una stringa sul web, è possibile codificare con Server.HTMLEncode().

Se si sta memorizzando una stringa nel database, assicurarsi che il campo del database sia "nchar", anziché "char". Ciò gli consentirà di memorizzare stringhe unicode.

Se non è possibile controllare il database, è possibile "appiattire" la stringa in ASCII con Encoding.ASCII.GetString.

8

Non penso che i dati in un database debbano conoscere o preoccuparsi dell'interfaccia utente. I problemi di visualizzazione dovrebbero essere gestiti dal livello di presentazione. Non vorrei vedere alcun HTML mischiato nel database.

+0

Sono completamente d'accordo, ma non è la mia scelta. È un'app legacy con caratteri di tipo HTML nel Guid (o ciò che passa come Guid). –

+1

Presentazione nella chiave primaria? OH MIO DIO. Lo rifatterò il prima possibile. – duffymo

+0

@duffymo: Perché no? Potrebbe essere un sito occupato. Salvataggio del contenuto HtmlEncoded salva la codifica su ogni richiesta. Per esempio. HTML reso creato dal markup Wiki - che salverà un rendering lungo su ogni richiesta - puoi pre-renderlo quando il markup è cambiato e salvato. –

0

OK, ecco quello che ho fatto. Ho creato una semplice funzione per gestirlo. È lontano dal completo ma almeno gestisce i caratteri standard <>&. Mi limiterò ad aggiungerlo mentre vado avanti.

CREATE FUNCTION HtmlEncode 
(
    @UnEncoded as varchar(500) 
) 
RETURNS varchar(500) 
AS 
BEGIN 
    DECLARE @Encoded as varchar(500) 
    SELECT @Encoded = Replace(@UnEncoded,'<','&lt;') 
    SELECT @Encoded = Replace(@Encoded,'>','&gt;') 
    SELECT @Encoded = Replace(@Encoded,'&','&amp;') 
    RETURN @Encoded  
END 

posso quindi utilizzare:

Select Ref,dbo.HtmlEncode(RecID) from Customers 

Questo mi dà un HTML sicura ID Record. Probabilmente esiste una funzione incorporata ma non riesco a trovarla.

0

assegnarlo a testo della proprietà del marchio, sarà automaticamente codificata dal .NET

+0

Benvenuto in Stack Overflow! Per favore espandi la tua risposta, includendo altre informazioni: questo è troppo breve. –

0

I non ho provato questa soluzione da solo, ma quello che vorrei provare è utilizzare l'integrazione SQL CLR server/.NET e in realtà chiamare la funzione C# HTMLEncode dal T-SQL. Questo potrebbe essere inefficiente ma sospetto che ti darebbe il risultato più accurato.

mio punto di partenza per lavorare fuori come fare questo sarebbe http://msdn.microsoft.com/en-us/library/ms254498%28VS.80%29.aspx

20

E 'un po' tardi, ma in ogni caso, qui i modi adeguati:

HTML-Encode (encoding = codifica XML HTML):

DECLARE @s NVARCHAR(100) 
SET @s = '<html>unsafe & safe Utf8CharsDon''tGetEncoded ÄöÜ - "Conex"<html>' 
SELECT (SELECT @s FOR XML PATH('')) 

HTML-codificare in una query:

SELECT 
    FIELD_NAME 
    ,(SELECT FIELD_NAME AS [text()] FOR XML PATH('')) AS FIELD_NAME_HtmlENcoded 
FROM TABLE_NAME 

HTML-Decode:

SELECT CAST('<root>' + '&lt;root&gt;Test&amp;123' + '</root>' AS XML).value(N'(root)[1]', N'varchar(max)'); 

Se si vuole fare in modo corretto, è possibile utilizzare una procedura CLR-memorizzato.
Tuttavia, diventa un po 'complicato, perché non è possibile utilizzare l'assembly System.Web in stored procedure CLR (quindi non è possibile eseguire System.Web.HttpUtility.HtmlDecode (htmlEncodedStr);). Quindi devi scrivere la tua classe HttpUtility, che non consiglierei, specialmente per la decodifica.

Fortunatamente, è possibile strappare System.Web.HttpUtility dal codice sorgente mono (.NET per Linux). Quindi è possibile utilizzare HttpUtility senza fare riferimento a system.web.

Poi si scrive questo CLR-stored-procedure:

using System; 
using System.Collections.Generic; 
using System.Text; 

using Microsoft.SqlServer.Server; 
using System.Data.SqlTypes; 
//using Microsoft.SqlServer.Types; 


namespace ClrFunctionsLibrary 
{ 


    public class Test 
    { 


     [Microsoft.SqlServer.Server.SqlFunction] 
     public static SqlString HtmlEncode(SqlString sqlstrTextThatNeedsEncoding) 
     { 
      string strHtmlEncoded = System.Web.HttpUtility.HtmlEncode(sqlstrTextThatNeedsEncoding.Value); 
      SqlString sqlstrReturnValue = new SqlString(strHtmlEncoded); 

      return sqlstrReturnValue; 
     } 


     [Microsoft.SqlServer.Server.SqlFunction] 
     public static SqlString HtmlDecode(SqlString sqlstrHtmlEncodedText) 
     { 
      string strHtmlDecoded = System.Web.HttpUtility.HtmlDecode(sqlstrHtmlEncodedText.Value); 
      SqlString sqlstrReturnValue = new SqlString(strHtmlDecoded); 

      return sqlstrReturnValue; 
     } 


     // ClrFunctionsLibrary.Test.GetPassword 
     //[Microsoft.SqlServer.Server.SqlFunction] 
     //public static SqlString GetPassword(SqlString sqlstrEncryptedPassword) 
     //{ 
     // string strDecryptedPassword = libPortalSecurity.AperturePortal.DecryptPassword(sqlstrEncryptedPassword.Value); 
     // SqlString sqlstrReturnValue = new SqlString(sqlstrEncryptedPassword.Value + "hello"); 

     // return sqlstrReturnValue; 
     //} 

     public const double SALES_TAX = .086; 

     // http://msdn.microsoft.com/en-us/library/w2kae45k(v=vs.80).aspx 
     [SqlFunction()] 
     public static SqlDouble addTax(SqlDouble originalAmount) 
     { 
      SqlDouble taxAmount = originalAmount * SALES_TAX; 

      return originalAmount + taxAmount; 
     } 


    } // End Class Test 


} // End Namespace ClrFunctionsLibrary 

e registrarlo:

GO 

/* 
--http://stackoverflow.com/questions/72281/error-running-clr-stored-proc 
-- For unsafe permission 
EXEC sp_changedbowner 'sa' 
ALTER DATABASE YOUR_DB_NAME SET TRUSTWORTHY ON 

GO 
*/ 


IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[HtmlEncode]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) 
DROP FUNCTION [dbo].[HtmlEncode] 
GO 


IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[HtmlDecode]') AND type in (N'FN', N'IF', N'TF', N'FS', N'FT')) 
DROP FUNCTION [dbo].[HtmlDecode] 
GO 




IF EXISTS (SELECT * FROM sys.assemblies asms WHERE asms.name = N'ClrFunctionsLibrary' and is_user_defined = 1) 
DROP ASSEMBLY [ClrFunctionsLibrary] 

GO 


--http://msdn.microsoft.com/en-us/library/ms345101.aspx 



CREATE ASSEMBLY [ClrFunctionsLibrary] 
AUTHORIZATION [dbo] 
FROM 'D:\username\documents\visual studio 2010\Projects\ClrFunctionsLibrary\ClrFunctionsLibrary\bin\Debug\ClrFunctionsLibrary.dll' 
WITH PERMISSION_SET = UNSAFE --EXTERNAL_ACCESS --SAFE 
; 

GO 




CREATE FUNCTION [dbo].[HtmlDecode](@value [nvarchar](max)) 
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER 
AS 
-- [AssemblyName].[Namespace.Class].[FunctionName] 
EXTERNAL NAME [ClrFunctionsLibrary].[ClrFunctionsLibrary.Test].[HtmlDecode] 
GO 





CREATE FUNCTION [dbo].[HtmlEncode](@value [nvarchar](max)) 
RETURNS [nvarchar](max) WITH EXECUTE AS CALLER 
AS 
-- [AssemblyName].[Namespace.Class].[FunctionName] 
EXTERNAL NAME [ClrFunctionsLibrary].[ClrFunctionsLibrary.Test].[HtmlEncode] 
GO 



/* 
EXEC sp_CONFIGURE 'show advanced options' , '1'; 
GO 
RECONFIGURE; 
GO 
EXEC sp_CONFIGURE 'clr enabled' , '1' 
GO 
RECONFIGURE; 
GO 

EXEC sp_CONFIGURE 'show advanced options' , '0'; 
GO 
RECONFIGURE; 
*/ 

Successivamente, è possibile utilizzarlo come normali funzioni:

SELECT 
    dbo.HtmlEncode('helloäÖühello123') AS Encoded 
    ,dbo.HtmlDecode('hello&auml;&Ouml;&uuml;hello123') AS Decoded 

Chiunque chi si limita a copiare le incisioni, si prega di notare che per motivi di efficienza si usa

public const double SALES_TAX = 1.086; 

// http://msdn.microsoft.com/en-us/library/w2kae45k(v=vs.80).aspx 
[SqlFunction()] 
public static SqlDouble addTax(SqlDouble originalAmount) 
{ 
    return originalAmount * SALES_TAX; 
} 

se si utilizza questa funzione in produzione.

Vedi qui per le classi mono modificati:
http://pastebin.com/pXi57iZ3
http://pastebin.com/2bfGKBte

è necessario definire NET_2_0 nelle opzioni di generazione Build options

+0

wow non pensava di tornare come xml! nice 1 –

+0

il trucco html-decode è davvero buono, grazie. –

+0

@ Rez.Net: fai attenzione, questo può e verrà lanciato su caratteri html validi che non sono specificati in XML, come ä ö o © o & eacute; â œ & ccedil; Ω ß æ Œ & ntilde; eccetera. –

1

Si può semplicemente utilizzare 'PATH XML nella query'. Per esempio;

 
DECLARE @encodedString VARCHAR(MAX) 

SET @encodedString = 'give your html string you want to encode' 

SELECT @encodedString 
SELECT (SELECT @encodedString FOR XML PATH('')) 

Ora come vostro desiderio potete farlo nella vostra funzione sql. Spero che questo ti sia d'aiuto.