2017-02-26 74 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