任务:我们正在通过HttpWebRequest(大约6,000次调用)抓取内容的HTML。修剪此字符串并将其存储在SQL Server 2014数据库中,以便以XML格式进行处理。
问题:在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中尝试过无数的Regex组合,而且我似乎弊大于利。任何指导或指示都将不胜感激。
此致,
约翰
答案 0 :(得分:2)
我建议您使用HTML解析器并以比字符串更好的方式存储数据。但是,如果您正在使用正则表达式来寻找快速而肮脏的解决方案,这可能会对您有所帮助:
寻找这个正则表达式:
(<img[^>]*?[^\/]\s*)(>)
并将其替换为:
$1/$2
[^>]*?
查找除>
之外的任何字符,但尽可能少[^\/]\s*
确保>
之前的最后一个字符不是斜杠/
或者不是斜杠后跟空格$1
和$2
。它只会匹配,如果还没有斜杠,并且它是img
标记。>
标记之间有<img ...>
个字符作为字符串,或者标记未在<img title=""
完全关闭,那么它就无法工作。以下是一个实例:https://regex101.com/r/HIxIIR/1
答案 1 :(得分:1)
首先尝试将你的html转换为xhtml,那里有一些转换器。正则表达式和HTML也不适合我...
答案 2 :(得分:1)
不幸的是,HTML不一定是有效的XML(XHTML除外)。所以你期待未封闭的标签。 HTML明确地允许某些标签像<br >
一样未被封闭,并且即使存在实际缺失甚至重叠的标签,也可以构建为健壮,即使在HTML中也是如此。
根据您期望的HTML,您可以尝试将其中一些错误更正为XML。例如,您知道在具有不同属性值和内容的所有结构上它总是相同的。如果你得到的HTML可以是任何东西,我恐怕你运气不好。也许您可以将其存储为NVARCHAR(MAX),如果您需要在数据库中查询它,请使用LIKE
。
答案 3 :(得分: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