用HTML实体替换特殊字符

时间:2018-10-16 09:07:39

标签: sql-server tsql sql-server-2012 bcp

我在表TABLE中有以下内容

id    content
-------------------------------------
1     Hellö world, I äm text
2     ènd there äré many more chars
3     that are speçial in my dat£base

我现在需要使用bcp将这些记录导出为HTML文件:

set @command = 'bcp "select [content] from [TABLE] where [id] = ' + 
            @id queryout +' + @filename + '.html" -S ' + @instance +
            ' -c -U ' + @username + ' -P ' + @password"

exec xp_cmdshell @command, no_ouput

要使输出看起来正确,我需要先将所有特殊字符替换为其各自的HTML实体(伪)

insert into [#temp_html] ..
replace(replace([content], 'ö', 'ö'), 'ä', 'ä')

但是到现在为止,我有30个嵌套的replace,并且开始看起来很疯狂。

经过大量搜索,我发现this post which uses a HTML conversion table,但是它太高级了,我无法理解:

  1. 该表未列出特殊字符本身,就象我在文本中一样(ö, à等),而是UnicodeHex。是否需要将它们添加到表中以进行所需的转换?
  2. 我无法理解如何更新脚本以替换所有特殊字符。有人可以给我看一下(伪)代码段吗?

1 个答案:

答案 0 :(得分:1)

使用转换表执行此操作的一种方法是使用递归cte进行替换,再使用cte仅获取每个转换值的最后一行。

首先,创建并填充示例表(在您将来的问题中为我们保存此步骤):

DECLARE @T AS TABLE
(
    id int,
    content nvarchar(100)
)
INSERT INTO @T (id, content) VALUES
(1,     'Hellö world, I äm text'),
(2,     'ènd there äré many more chars'),
(3,     'that are speçial in my dat£base')

然后,创建并填充翻译表(我不知道这些字符的HTML实体,因此我只使用了数字[另外,在结果中更容易看到])。另外,请注意,可以使用链中的另一个cte来完成此操作。

DECLARE @Translations AS TABLE
(
    str nchar(1),
    replacement nvarchar(10)
)

INSERT INTO @Translations (str, replacement) VALUES
('ö', '-1-'),
('ä', '-2-'),
('è', '-3-'),
('ä', '-4-'),
('é', '-5-'),
('ç', '-6-'),
('£', '-7-')

现在,第一个cte将执行替换操作,第二个cte仅添加一个row_number,以便对于每个id,lvl的最后一个值将为1:

;WITH CTETranslations AS
(
    SELECT id, content, 1 As lvl
    FROM @T
    UNION ALL
    SELECT id, CAST(REPLACE(content, str, replacement) as nvarchar(100)), lvl+1
    FROM CTETranslations
    JOIN @Translations 
        ON content LIKE '%' + str + '%' 
), cteNumberedTranslation AS
(
    SELECT id, content, ROW_NUMBER() OVER(PARTITION BY Id ORDER BY lvl DESC) rn
    FROM CTETranslations
)

从rn = 1的第二个cte中选择,我已加入原始表以并排显示源代码和翻译:

SELECT r.id, s.content, r.content
FROM @T s
JOIN cteNumberedTranslation r
    ON s.Id = r.Id
WHERE rn = 1
ORDER BY Id

结果:

id  content                             content
1   Hellö world, I äm text              Hell-1- world, I -4-m text
2   ènd there äré many more chars       -3-nd there -4-r-5- many more chars
3   that are speçial in my dat£base     that are spe-6-ial in my dat-7-base

请注意,如果您的内容包含超过100个特殊字符,则需要在最终选择中添加maxrecursion 0提示:

SELECT r.id, s.content, r.content
FROM @T s
JOIN cteNumberedTranslation r
    ON s.Id = r.Id
WHERE rn = 1
ORDER BY Id
OPTION ( MAXRECURSION 0 );

See a live demo on rextester.