SQL - 删除字符串中的所有HTML标记

dkm*_*ann 12 html xml sql t-sql sql-server

在我的数据集中,我有一个字段,用于存储用HTML标记的文本.一般格式如下:

<html><head></head><body><p>My text.</p></body></html>

我可以尝试通过执行以下操作来解决问题:

REPLACE(REPLACE(Table.HtmlData, '<html><head></head><body><p>', ''), '</p></body></html>')
Run Code Online (Sandbox Code Playgroud)

但是,这不是一个严格的规则,因为某些条目违反W3C标准并且不包括<head>标签.更糟糕的是,可能会缺少结束标签.所以我需要REPLACE为每个可能存在的开始和结束标记包含该函数.

REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
    Table.HtmlData,
    '<html>', ''),
    '</html>', ''),
    '<head>', ''),
    '</head>', ''),
    '<body>', ''),
    '</body>', ''),
    '<p>', ''),
    '</p>', '')
Run Code Online (Sandbox Code Playgroud)

我想知道是否有比使用多个嵌套REPLACE函数更好的方法来实现这一点.不幸的是,我在这种环境中可用的唯一语言是SQL和Visual Basic(不是.NET).

Dev*_*art 9

DECLARE @x XML = '<html><head></head><body><p>My text.</p></body></html>'

SELECT t.c.value('.', 'NVARCHAR(MAX)')
FROM @x.nodes('*') t(c)
Run Code Online (Sandbox Code Playgroud)

更新 - 对于包含未关闭标记的字符串:

DECLARE @x NVARCHAR(MAX) = '<html><head></head><body><p>My text.<br>More text.</p></body></html>'

SELECT x.value('.', 'NVARCHAR(MAX)')
FROM (
    SELECT x = CAST(REPLACE(REPLACE(@x, '>', '/>'), '</', '<') AS XML)
) r
Run Code Online (Sandbox Code Playgroud)


Luk*_*rms 8

如果HTML格式正确,那么就不需要使用replace来解析XML.
只需将其转换或转换为XML类型并获取值.

这是从所有标签输出文本的示例:

declare @htmlData nvarchar(100) = '<html>
<head>
</head>
<body>
   <p>My text.</p>
   <p>My other text.</p>
</body>
</html>';

select convert(XML,@htmlData,1).value('.', 'nvarchar(max)');

select cast(@htmlData as XML).value('.', 'nvarchar(max)');
Run Code Online (Sandbox Code Playgroud)

请注意,强制转换和转换之间的空白输出存在差异.

要仅从特定节点获取内容,请使用XQuery语法.(XQuery基于XPath语法)

例如:

select cast(@htmlData as XML).value('(//body/p/node())[1]', 'nvarchar(max)');

select convert(XML,@htmlData,1).value('(//body/p/node())[1]', 'nvarchar(max)');
Run Code Online (Sandbox Code Playgroud)

结果: My text.

当然,这仍然假定有效的XML.
例如,如果缺少结束标记,则会引发XML parsing错误.

如果HTML没有很好地形成为XML,那么可以使用PATINDEX和SUBSTRING来获取第一个p标记.然后将其转换为XML类型以获取值.

select cast(SUBSTRING(@htmlData,patindex('%<p>%',@htmlData),patindex('%</p>%',@htmlData) - patindex('%<p>%',@htmlData)+4) as xml).value('.','nvarchar(max)');
Run Code Online (Sandbox Code Playgroud)

或者通过一种时髦的递归方式:

declare @xmlData nvarchar(100);
WITH Lines(n, x, y) AS (
  SELECT 1, 1, CHARINDEX(char(13), @htmlData)
  UNION ALL
  SELECT n+1, y+1, CHARINDEX(char(13), @htmlData, y+1) FROM Lines
  WHERE y > 0
)
SELECT @xmlData = concat(@xmlData,SUBSTRING(@htmlData,x,IIF(y>0,y-x,8)))
FROM Lines
where PATINDEX('%<p>%</p>%', SUBSTRING(@htmlData,x,IIF(y>0,y-x,10))) > 0
order by n;

select 
@xmlData as xmlData, 
convert(XML,@xmlData,1).value('(/p/node())[1]', 'nvarchar(max)') as FirstP;
Run Code Online (Sandbox Code Playgroud)


小智 6

首先创建一个用户定义的函数,像这样去除 HTML:

CREATE FUNCTION [dbo].[udf_StripHTML] (@HTMLText VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
     BEGIN
         DECLARE @Start INT;
         DECLARE @End INT;
         DECLARE @Length INT;
         SET @Start = CHARINDEX('<', @HTMLText);
         SET @End = CHARINDEX('>', @HTMLText, CHARINDEX('<', @HTMLText));
         SET @Length = (@End - @Start) + 1;
         WHILE @Start > 0
               AND @End > 0
               AND @Length > 0
             BEGIN
                 SET @HTMLText = STUFF(@HTMLText, @Start, @Length, '');
                 SET @Start = CHARINDEX('<', @HTMLText);
                 SET @End = CHARINDEX('>', @HTMLText, CHARINDEX('<', @HTMLText));
                 SET @Length = (@End - @Start) + 1;
             END;
         RETURN LTRIM(RTRIM(@HTMLText));
     END;
GO
Run Code Online (Sandbox Code Playgroud)

当您尝试选择它时:

SELECT dbo.udf_StripHTML([column]) FROM SOMETABLE
Run Code Online (Sandbox Code Playgroud)

这应该会导致您避免使用多个嵌套的替换语句。

信用和更多信息:http : //blog.sqlauthority.com/2007/06/16/sql-server-udf-user-defined-function-to-strip-html-parse-html-no-regular-expression/