TSQL 从 HTML 中删除带有特定 src 的 img 标签
Posted
技术标签:
【中文标题】TSQL 从 HTML 中删除带有特定 src 的 img 标签【英文标题】:TSQL remove img tag with specific src from HTML 【发布时间】:2016-12-06 14:07:40 【问题描述】:我的数据库中有一个带有许多 img 标签的 html 文本。我的目标是删除带有特定 src 的 img 标签
我的输入是
<div>
<p>some text goes here <img src="/upload/remove-me.png" /></p>
<p>some other text goes here <img src='/upload/remove-me.png' /></p>
<p>some other text goes here <img src="/upload/filename.png" /></p>
</div>
我想删除我的输出结果为 src="/upload/remove-me.png" 的所有图像
<div>
<p>some text goes here</p>
<p>some other text goes here</p>
<p>some other text goes here <img src="/upload/filename.png" /></p>
</div>
有没有办法在 TSQL 中使用正则表达式?
【问题讨论】:
tsql 不支持正则表达式,除了 clr 函数。我建议在 sql server 之外执行此操作。 【参考方案1】:如果img
作为一个整体是不变的(不仅仅是src):
<img src='/upload/remove-me.png' />
那么你可以使用一个简单的REPLACE
,像这样:
UPDATE tablename SET columnname=REPLACE(
columnname,
N' <img src=''/upload/remove-me.png'' />',
N''
)
WHERE columnname LIKE N'% <img src=''/upload/remove-me.png'' />%'
标签前的空格是有意的。
如果标记存储在ntext
列中,请先转换为nvarchar(max)
,否则REPLACE
将失败。
如果这不是一次性数据更正的任务,您应该将其包含在您的业务逻辑层中。
【讨论】:
这不起作用,因为即使问题中给出的示例数据也没有统一的属性。 正确。如果 OP 可以将其限制为一组已知的排列,他可以每个都做一个UPDATE
。否则,您上面的解决方案显然更适合此任务
替换不是一个选项,在我的示例中,我发布了我可能拥有的不同变体。所以需要一些通用的东西【参考方案2】:
从您的示例看来,标签的属性可以按任何顺序排列,因此我们需要遍历文本以一次取出一个 img 标签。显然,您需要在数据的备份版本上尝试此操作,以确保它只删除您想要删除的内容:
declare @HTML table(a nvarchar(max))
insert into @HTML
select
'<div>
<p>some text goes here <img src="/upload/remove-me.png" /></p>
<p>some other text goes here <img src="/upload/remove-me.png" /></p>
<p>some other text goes here <img src="/upload/filename.png" /></p>
</div>'
declare @URL nvarchar(50) = 'src="/upload/remove-me.png"' -- Search for img tags with this text in.
declare @TagStart int = -1
declare @TagEnd int = -1
while @TagStart <> 0
begin
select @TagStart = patindex('%<img%' + @URL + '%/>%',a)-1 -- Find the start of the first img tag in the text.
,@TagEnd = patindex('%/>%'
,substring(a
,patindex('%<img%' + @URL + '%/>%',a)
,999999999
)
)+1 -- Find the end of the first img tag in the text.
from @HTML
update @HTML -- Update the table to remove just this tag
set a = (select left(a,@TagStart) + right(a,len(a)-@TagStart-@TagEnd)
from @HTML
)
select @TagStart = patindex('%<img%' + @URL + '%/>%',a) -- Check if there are any more img tags with the URL to remove. Will return 0 if there are none.
from @HTML
end
select a as CleanHTML
from @HTML
【讨论】:
完全按预期工作。谢谢【参考方案3】:XML DML 提供了更优雅的解决方案。很可能您的主表的 HTML 字段为 (n)varchar(max))
,因此需要一个临时表。
declare @HTML table(id int, a xml)
insert into @HTML
select id, html
from dbo.myTable
/* content of html field
'<div>
<p>some text goes here <img src="/upload/remove-me.png" /></p>
<p>some other text goes here <img src="/upload/remove-me.png" /></p>
<p>some other text goes here <img src="/upload/filename.png" /></p>
</div>'
*/
update @html
set a.modify('delete //img[contains(@src,"remove-me")]') --delete nodes and update
from @HTML cross apply a.nodes('div') t(v)
--select * from @html --just to see what happens
update dbo.myTable
set html = h.a
from dbo.myTable t
inner join @html h on t.id = h.id
【讨论】:
确实非常优雅! 你的解决方案非常优雅,我喜欢它,但唯一的缺点是它需要有效的 xml 结构,不幸的是我的输入文本可能并不总是以 开头,它只能以纯文本开头没有任何标签 这也适用于纯文本。只需使用div
包装该字段即可。像这样insert into @HTML select id, '<div>'+html+'</div>' from dbo.myTable
【参考方案4】:
下面的函数应该可以完成这项工作。它只是找到目标图像名称的图像开始和结束标记,然后删除文本。
ALTER FUNCTION Html_RemoveImageAttributes
(
@sourceImage NVARCHAR(100),
@inputHtml NVARCHAR(MAX)
)
RETURNS NVARCHAR(MAX)
AS
BEGIN
DECLARE @imageTagStart INT = CHARINDEX('<img ' , @inputHtml, 1);
DECLARE @imageIndex INT = CHARINDEX(@sourceImage, @inputHtml, @imageTagStart);
DECLARE @imageTagEnd INT = CHARINDEX('/>' , @inputHtml, @imageTagStart);
DECLARE @outputHtml NVARCHAR(MAX) = @inputHtml;
WHILE (@imageIndex > 0)
BEGIN
IF (@imageIndex > @imageTagStart) AND (@imageIndex < @imageTagEnd)
BEGIN
-- Remove first occurrence of image.
SET @outputHtml = REPLACE(@outputHtml, SUBSTRING(@outputHtml, @imageTagStart, @imageTagEnd - @imageTagStart + 2), '');
SET @imageTagStart = CHARINDEX('<img ' , @outputHtml);
SET @imageIndex = CHARINDEX(@sourceImage, @outputHtml);
SET @imageTagEnd = CHARINDEX('/>' , @outputHtml);
END
ELSE
BEGIN
SET @imageTagStart = CHARINDEX('<img ' , @outputHtml, @imageTagEnd);
SET @imageIndex = CHARINDEX(@sourceImage, @outputHtml, @imageTagEnd);
SET @imageTagEnd = CHARINDEX('/>' , @outputHtml, @imageTagEnd + 1);
END
END
RETURN @outputHtml
END
下面的例子展示了如何使用它:
DECLARE @sourceImage NVARCHAR(50) = 'remove-me.png';
DECLARE @input NVARCHAR(4000) = N'<div>
<p>some text goes here <img src="/upload/remove-me.png" /></p>
<p>some other text goes here <img src=''/upload/remove-me.png'' /></p>
<p>some other text goes here <img src="/upload/filename.png" /></p>
</div>';
PRINT dbo.Html_RemoveImageAttributes(@sourceImage, @input);
【讨论】:
以上是关于TSQL 从 HTML 中删除带有特定 src 的 img 标签的主要内容,如果未能解决你的问题,请参考以下文章
需要从本地 iframe 中的 src url 中删除页眉和页脚
如何在 C# 中执行包含带有“-”、“\”或“;”的字符串的 TSQL 输入命令