2017-02-26 45 views
3

任务:我们通过HttpWebRequest(大约6000次调用)为内容刮取HTML。该字符串被修剪并存储在SQL Server 2014数据库中,作为XML进行处理。如何将所有HTML img关闭标记转换为XML兼容? (<img>到<img/>)

问题:在SQL Server中,由于图像标签,我们将得到一个XML解析错误:“...end tag does not match start tag”。

现在,我有一个相当不雅的和潜在 SQL Server有缺陷的解决方案。

样品字符串

<div someattr="aaa"> 
    <div class="bbb">Some Text</div> 
    <img src="image.jpg" width="150">  <-- Notice the lack of /> 
</div> 

预期的效果

<div someattr="aaa"> 
    <div class="bbb">Some Text</div> 
    <img src="image.jpg" width="150"/>  <-- Notice the /> 
</div> 

我在ASP.Net试过无数的正则表达式组合,我似乎做弊大于利。任何指导或方向将不胜感激。

尊敬,

约翰

回答

2

我建议你使用一个HTML解析器UND存储中的数据以更好的方式不仅仅是一个字符串。但是,如果你打算用正则表达式的快速和肮脏的解决方案,这可以帮助你:

查找这个表达式:

(<img[^>]*?[^\/]\s*)(>) 

,取而代之的是:

$1/$2 
  • [^>]*?寻找除>之外的任何字符但尽可能少
  • [^\/]\s*确保最后一个cha在>之前的部分或者不是斜线/或者不是斜线后面是空格
  • 第一部分和第二部分分组在$1$2之间。它只会匹配,如果还没有斜线,并且它是img标记。
  • 如果在<img ...>标签之间存在>字符作为字符串,或者标签根本没有关闭<img title="",它将不起作用。

这是一个活生生的例子:https://regex101.com/r/HIxIIR/1

+0

谢谢,这是我一直在寻找 –

+1

将奖励在2个小时的赏金,当系统允许它 –

1

尝试转换您的HTML先XHTML,也有一些转换器在那里。正则表达式和HTML没有工作对我来说要么...

1

不幸的是HTML不一定是有效的XML(XHTML除外)。所以你有期待未封闭的标签。 HTML显然确实允许一些标签像<br >那样未被封闭,并且即使确实缺少甚至重叠的标签即使在HTML中也是实际的错误,其被构建为健壮的。

根据您期望的HTML,您可以尝试将某些错误更正为XML。例如,您知道在具有不同属性值和内容的所有结构中它总是相同的。如果你得到的HTML可以是任何东西,恐怕你运气不好。也许你可以将它存储为NVARCHAR(MAX),并且如果必须在数据库上使用LIKE来查询它。

1

下面是一个快速和肮脏的解决方案,只使用T-SQL。

Rextester演示:http://rextester.com/TLF34624

CREATE FUNCTION processHtml(@html VARCHAR(MAX)) 
RETURNS VARCHAR(MAX) 
AS 
BEGIN 
    DECLARE @remainingHtml VARCHAR(MAX), 
      @processedHtml VARCHAR(MAX), 
      @imgPos INT, 
      @closingAngleBracketPos INT, 
      @openingAngleBracketPos INT; 
    SET @remainingHtml = @html; 
    SET @imgPos = PATINDEX('%<img%[^</]>%', @remainingHtml); 
    WHILE @imgPos > 0 
    BEGIN 
     SET @processedHtml = CONCAT(@processedHtml, SUBSTRING(@remainingHtml, 1, @imgPos - 1)); 
     SET @remainingHtml = SUBSTRING(@remainingHtml, @imgPos, LEN(@remainingHtml)); 
     SET @closingAngleBracketPos = PATINDEX('%[^/]>%', @remainingHtml); 
     SET @openingAngleBracketPos = CHARINDEX('<', @remainingHtml, 2); 
     IF @closingAngleBracketPos < 0 
      SET @imgPos = -1; 
     ELSE IF @closingAngleBracketPos < @openingAngleBracketPos 
     BEGIN 
      SET @processedHtml = CONCAT(@processedHtml, SUBSTRING(@remainingHtml, 1, @closingAngleBracketPos), '/>'); 
      SET @remainingHtml = SUBSTRING(@remainingHtml, @closingAngleBracketPos + 2, LEN(@remainingHtml)); 
      SET @imgPos = PATINDEX('%<img%[^</]>%', @remainingHtml); 
     END 
     ELSE 
     BEGIN 
      SET @processedHtml = CONCAT(@processedHtml, SUBSTRING(@remainingHtml, 1, @openingAngleBracketPos - 1)); 
      SET @remainingHtml = SUBSTRING(@remainingHtml, @openingAngleBracketPos, LEN(@remainingHtml)); 
      SET @imgPos = PATINDEX('%<img%[^</]>%', @remainingHtml); 
     END 
    END 

    SET @processedHtml = CONCAT(@processedHtml, @remainingHtml); 
    RETURN @processedHtml; 
END