HTML кодирование в T-SQL? - PullRequest
       32

HTML кодирование в T-SQL?

16 голосов
/ 12 марта 2009

Есть ли функция для кодирования HTML-строк в T-SQL? У меня есть устаревшая база данных, которая содержит хитрые символы, такие как «<», «>» и т. Д. Я могу написать функцию для замены символов, но есть ли лучший способ?

У меня есть приложение ASP.Net, и когда оно возвращает строку, оно содержит символы, которые вызывают ошибку. Приложение ASP.Net считывает данные из таблицы базы данных. Он не записывает в саму таблицу.

Ответы [ 10 ]

25 голосов
/ 25 сентября 2009

У нас есть устаревшая система, которая использует триггер и dbmail для отправки электронной почты в кодировке HTML при вводе таблицы, поэтому нам требуется кодирование при создании электронной почты. Я заметил, что в версии Лео есть небольшая ошибка, которая кодирует & в &lt; и &gt; Я использую эту версию:

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
21 голосов
/ 09 января 2013

Уже немного поздно, но в любом случае, вот правильные пути:

HTML-кодировка (HTML-кодировка = XML-кодировка):

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

HTML-кодирование в запросе:

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)');

Если вы хотите сделать это правильно, вы можете использовать хранимую в CLR процедуру.
Однако это становится немного сложнее, потому что вы не можете использовать System.Web-Assembly в CLR-хранимых процедурах (поэтому вы не можете сделать System.Web.HttpUtility.HtmlDecode (htmlEncodedStr);). Поэтому вы должны написать свой собственный класс HttpUtility, который я бы не рекомендовал, особенно для декодирования.

К счастью, вы можете извлечь System.Web.HttpUtility из моно исходного кода (.NET для Linux). Тогда вы можете использовать HttpUtility без ссылки на system.web.

Затем вы пишете эту хранимую процедуру CLR:

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

И зарегистрируйте его:

GO

/*
--/49536/fileloadexception-msg-10314-oshibka-pri-zapuske-hranimoi-protsedury-clr
-- 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;
*/

После этого вы можете использовать его как обычные функции:

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

Любой, кто просто копирует-вставляет, пожалуйста, обратите внимание, что из соображений эффективности вы должны использовать

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

если вы будете использовать эту функцию в производстве.

Смотрите отредактированные моно классы здесь:
http://pastebin.com/pXi57iZ3
http://pastebin.com/2bfGKBte

Вам нужно определить NET_2_0 в опциях сборки Build options

15 голосов
/ 12 марта 2009

Вы не должны исправлять строку в SQL. Лучше использовать функцию в ASP.net с именем HtmlEncode, которая будет готовить специальные символы, которые вызывают проблемы, которые вы видите, см. Пример ниже. Надеюсь, это поможет.

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

Edit: Так как вы привязываете данные к данным. Используйте встроенное выражение для вызова HTMLEncode в разметке GridView или любого другого элемента управления, который вы используете, и это все равно будет соответствовать вашему требованию связывания данных. Смотрите пример ниже. В качестве альтернативы вы можете зациклить каждую запись в объекте таблицы данных и обновить каждую ячейку строкой в ​​кодировке html до привязки данных.

<%# System.Web.HttpUtility.HtmlEncode(Eval("YourColumnNameHere")) %>
8 голосов
/ 12 марта 2009

Я не думаю, что данные в базе данных должны знать или заботиться о пользовательском интерфейсе. Проблемы с отображением должны решаться на уровне представления. Я не хотел бы видеть какой-либо HTML, смешанный с базой данных.

2 голосов
/ 16 декабря 2016

Вы можете просто использовать «XML PATH в своем запросе». Например;

DECLARE @encodedString VARCHAR(MAX)

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

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

Теперь по вашему желанию вы можете сделать это в своей собственной функции sql. Надеюсь, это поможет.

2 голосов
/ 12 марта 2009

Если вы отображаете строку в Интернете, вы можете закодировать ее с помощью Server.HTMLEncode ().

Если вы храните строку в базе данных, убедитесь, что в поле базы данных указано «nchar», а не «char». Это позволит хранить строки Unicode.

Если вы не можете управлять базой данных, вы можете "сгладить" строку в ASCII с Encoding.ASCII.GetString.

0 голосов
/ 04 июля 2018

Я пытался сделать это сегодня в T-SQL, в основном для забавы, поскольку мои требования изменились, но я нашел выход. Вы можете использовать таблицу символов Юникода, построенную из функции NCHAR (), или просто импортировать ее, повторяя от 0 до 65535 (или меньше, если вам просто нужны первые 512 или что-то еще). Затем перестройте строку. Возможно, есть лучшие способы перестроить строку, но это работает в крайнем случае.

---store unicode chars into a table so you can replace those characters withthe decimal value

`

CREATE TABLE #UnicodeCharacters ( DecimalValue INT, UnicodeCharacter NCHAR ) ;

--loop from 0 to highest unicode value you want and dump to the table you created
DECLARE @x INT = 0;
WHILE @x <= 65535
    BEGIN
        BEGIN
            INSERT INTO #UnicodeCharacters(DecimalValue, UnicodeCharacter)
            SELECT  @x,NCHAR(@x)
        END
        ;

        SET @x = @x + 1
        ;
    END
;

--index for fast retrieval
CREATE CLUSTERED INDEX CX_UnicodeCharacter_DecimalValue ON #UnicodeCharacters(UnicodeCharacter, DecimalValue);

--this is the string that you want to html-encode...
DECLARE @String NVARCHAR(100) = N'人This is a test - Ñ';

--other vars
DECLARE @NewString NVARCHAR(100) = '';
DECLARE @Word TABLE(Character NCHAR(1));
DECLARE @Pos INT = 1;

--run through the string and check each character to see if it is outside the regex expression
WHILE @Pos <= LEN(@String)
BEGIN
    DECLARE @Letter NCHAR(1) = SUBSTRING(@String,@Pos,1);
    PRINT @Letter;
    --rebuild the string replacing each unicode character outside the regex with &#[unicode value];
    SELECT  @NewString = @NewString + 
                CASE 
                    WHEN @Letter LIKE N'%[0-9abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-!@#$%^&*()_+-= ]%' THEN @Letter
                    ELSE '&#' + CAST(uc.DecimalValue AS VARCHAR(10)) + ';'
                END
    FROM    #UnicodeCharacters uc
    WHERE   @Letter = uc.UnicodeCharacter COLLATE JAPANESE_UNICODE_BIN

    SET @Pos += 1
END

--end result
SELECT @NewString
;

` Я знаю, что обычно вы бы использовали [0-9A-Za-z], но по какой-то причине, когда я это сделал, он рассматривал акцентированные символы в пределах этого выражения. Поэтому я явно использовал каждый символ, который не хотел преобразовывать в Unicode в выражении.

Последнее замечание: мне пришлось использовать другое сопоставление для сопоставления символов Unicode, потому что сопоставление LATIN по умолчанию (CI или другое), казалось, неправильно совпадало с символами с акцентом, во многом как регулярное выражение в LIKE.

0 голосов
/ 29 июля 2011

Я сам не пробовал это решение, но я попробовал бы использовать интеграцию sql server / .NET CLR и фактически вызвать функцию C # HTMLEncode из T-SQL. Это может быть неэффективно, но я подозреваю, что это даст вам наиболее точный результат.

Моя отправная точка для разработки, как это сделать, будет http://msdn.microsoft.com/en-us/library/ms254498%28VS.80%29.aspx

0 голосов
/ 08 ноября 2010

присвойте его свойству Text Property of label, оно будет автоматически закодировано .NET

0 голосов
/ 15 марта 2009

ОК, вот что я сделал. Я создал простую функцию, чтобы справиться с этим. Это далеко от завершения, но, по крайней мере, обрабатывает стандартные символы <>&. Я просто добавлю к этому, как я иду вперед.

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

Затем я могу использовать:

Select Ref,dbo.HtmlEncode(RecID) from Customers

Это дает мне безопасный идентификатор записи HTML. Вероятно, есть встроенная функция, но я не могу ее найти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...