SQL Server:HTML解码基于String输入中的HTML名称

Sat*_*ish 1 sql sql-server sql-server-2012

我正在尝试使用下面的SQL 将HTML & "等名称转换为等效CHAR值.我在SQL Server 2012中测试了这个.

测试1(这很好):

GO
DECLARE @inputString VARCHAR(MAX)= '&testString&'
DECLARE @codePos INT, @codeEncoded VARCHAR(7), @startIndex INT, @resultString varchar(max)
SET @resultString = LTRIM(RTRIM(@inputString))
SELECT @startIndex = PATINDEX('%&%', @resultString)
WHILE @startIndex > 0 
BEGIN
    SELECT @resultString = REPLACE(@resultString, '&', '&'), @startIndex=PATINDEX('%&%', @resultString)
END

PRINT @resultString
Go
Run Code Online (Sandbox Code Playgroud)

输出:

&testString&
Run Code Online (Sandbox Code Playgroud)

测试2(这不起作用):由于上述工作,我试图扩展它以处理更多字符如下:

DECLARE @htmlNames TABLE (ID INT IDENTITY(1,1), asciiDecimal INT, htmlName varchar(50))
INSERT INTO @htmlNames
VALUES (34,'"'),(38,'&'),(60,'<'),(62,'>'),(160,' '),(161,'¡'),(162,'¢')
-- I would load the full list of HTML names into this TABLE varaible, but removed for testing purposes
DECLARE @inputString VARCHAR(MAX)= '&testString&'
DECLARE @count INT = 0
DECLARE @id INT = 1
DECLARE @charCode INT, @htmlName VARCHAR(30)
DECLARE @codePos INT, @codeEncoded VARCHAR(7), @startIndex INT
        , @resultString varchar(max)
SELECT @count=COUNT(*) FROM @htmlNames

WHILE @id <=@count
BEGIN
    SELECT @charCode = asciiDecimal, @htmlname = htmlName
    FROM @htmlNames
    WHERE ID = @id

        SET @resultString = LTRIM(RTRIM(@inputString))
        SELECT @startIndex = PATINDEX('%' + @htmlName + '%', @resultString)
        While @startIndex > 0 
        BEGIN
            --PRINT @resultString + '|'  + @htmlName + '|' + NCHAR(@charCode)
            SELECT @resultString = REPLACE(@resultString, @htmlName, NCHAR(@charCode))
            SET @startIndex=PATINDEX('%' + @htmlName + '%', @resultString)
        END
        SET @id=@id + 1
END

PRINT @resultString

GO
Run Code Online (Sandbox Code Playgroud)

输出:

&amp;testString&amp;
Run Code Online (Sandbox Code Playgroud)

我无法弄清楚我哪里出错了?任何帮助将非常感激.

我不想将字符串值加载到应用程序层,然后应用HTMLDecode并保存回数据库.

编辑:这条线SET @resultString = LTRIM(RTRIM(@inputString))在里面,WHILE所以我覆盖了结果@inputString.谢谢你,YanireRomero.

我也喜欢@ RichardDeeming的解决方案,但在这种情况下它不符合我的需求.

Ric*_*ing 16

这是一个不需要循环的简单解决方案:

DECLARE @htmlNames TABLE 
(
    ID INT IDENTITY(1,1), 
    asciiDecimal INT, 
    htmlName varchar(50)
);

INSERT INTO @htmlNames 
VALUES 
    (34,'&quot;'),
    (38,'&amp;'),
    (60,'&lt;'),
    (62,'&gt;'),
    (160,'&nbsp;'),
    (161,'&iexcl;'),
    (162,'&cent;')
;

DECLARE @inputString varchar(max)= '&amp;test&amp;quot;&lt;String&gt;&quot;&amp;';
DECLARE @resultString varchar(max) = @inputString;

-- Simple HTML-decode:
SELECT
    @resultString = Replace(@resultString COLLATE Latin1_General_CS_AS, htmlName, NCHAR(asciiDecimal))
FROM
    @htmlNames
;

SELECT @resultString;
-- Output: &test&quot;<String>"&


-- Multiple HTML-decode:
SET @resultString = @inputString;

DECLARE @temp varchar(max) = '';
WHILE @resultString != @temp
BEGIN
    SET @temp = @resultString;

    SELECT
        @resultString = Replace(@resultString COLLATE Latin1_General_CS_AS, htmlName, NCHAR(asciiDecimal))
    FROM
        @htmlNames
    ;
END;

SELECT @resultString;
-- Output: &test"<String>"&
Run Code Online (Sandbox Code Playgroud)

编辑:NCHAR根据@tomasofen的建议更改为,并根据@TechyGypo的建议为函数添加了区分大小写的排序REPLACE规则.


Wit*_*der 5

出于性能考虑,这不应该作为T-SQL语句或SQL标量值函数编写..NET库提供了出色,快速,最重要的可靠 HTML解码.在我看来,你应该将它实现为SQL CLR,如下所示:

using Microsoft.SqlServer.Server;
using System.Data.SqlTypes;
using System.Net;

public partial class UserDefinedFunctions
{
    [Microsoft.SqlServer.Server.SqlFunction(
        IsDeterministic = true,
        IsPrecise = true,
        DataAccess = DataAccessKind.None,
        SystemDataAccess = SystemDataAccessKind.None)]
    [return: SqlFacet(MaxSize = 4000)]
    public static SqlString cfnHtmlDecode([SqlFacet(MaxSize = 4000)] SqlString input)
    {
        if (input.IsNull)
            return null;

        return System.Net.WebUtility.HtmlDecode(input.Value);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后在你的T-SQL中,像这样调用它:

SELECT clr_schema.cfnHtmlDecode(column_name) FROM table_schema.table_name
Run Code Online (Sandbox Code Playgroud)