2012-06-05 48 views
1

我有一些HTML內容需要使用C#修改。這在概念上很簡單,但我不確定如何有效地做到這一點。內容包含幾個分隔符號碼後面跟着一個空的錨點標記。我需要獲取分隔號碼並將其插入到錨標記中的JavaScript函數調用中。例如。使用正則表達式轉換字符串

源字符串將包含這樣的事情:

%%1%%<a href="#"></a> 
<p>A bunch of HTML markup</p> 

%%2%%<a href="#"></a> 
<p>Some more HTML markup</p> 

我需要把它轉換成這樣:

<a href="#" onclick="DoSomething('1')></a> 
<p>A bunch of HTML markup</p> 

<a href="#" onclick="DoSomething('2')></a> 
<p>Some more HTML markup</p> 

沒有限制%% \ d + %%出現的次數。我在寫一個正則表達式時希望能夠使用Replace方法,但我不確定這是否甚至可以用於每個組的多個實例。這是我有:

%%(?<LinkID>\d+)%%(?<LinkStart><a[\s\S]*?)(?:(?<LinkEnd>>[\s\S]*?)(?=%%\d+|$)) 

// %%(?<LinkID>\d+)%%  Match a number surrounded by %% and put the number in a group named LinkID 
// (?<LinkStart><a[\s\S]*?) Match <a followed by any characters until next match (non greedy), in a group named LinkStart 
// (?:      Logical grouping that does not get captured 
// (?<LinkEnd>>[\s\S]*?)  Match > followed by any characters until next match, in a group named LinkEnd 
// (?=%%\d+%%|$)    Where the former LinkEnd group is followed by another instance of a delimited number or the end of the string. (I don't think this is working as I intended.) 

也許可以使用幾個正則表達式操作和String.Format的組合。我在正則表達式方面並不擅長,所以請稍微貶低你的答案。

回答

0

原來,Regex.Replace已經足夠智能處理多個匹配。我只是修改了我的正則表達式,不使用前瞻。我的想法是,我找到%%定界符內的數字並將其添加到一個組中,找到下一個定位標記中的內容並將其添加到一個組,然後用一個新版本替換整個匹配,插入它的兩個組。替換方法似乎會自動處理後續匹配,無需任何其他幫助。

string originalText = "<h3>%%1%%<a href=\"#\">First Spot</a></h3><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>" + 
          "<h3>%%2%%<a href=\"#\">Second Spot</a></h3><p>Ut vulputate lobortis feugiat.</p>" + 
          "<p>Ut nunc diam, malesuada iaculis viverra nec, auctor eget velit.</p>"; 

Regex regex = new Regex(@"%%(\d+)%%[\s]*<a[\s\S]*?>([\s\S]*?)</a>"); 
string result = regex.Replace(originalText, "<a href=\"#\" onclick=\"DoSomething($1)\">$2</a>"); 
Debug.WriteLine("Original Text: \"" + originalText + "\""); 
Debug.WriteLine("Result Text: \"" + result + "\""); 

輸出:

Original Text: "<h3>%%1%%<a href="#">First Spot</a></h3><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p><h3>%%2%%<a href="#">Second Spot</a></h3><p>Ut vulputate lobortis feugiat.</p><p>Ut nunc diam, malesuada iaculis viverra nec, auctor eget velit.</p>" 

Result Text: "<h3><a href="#" onclick="DoSomething(1)">First Spot</a></h3><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p><h3><a href="#" onclick="DoSomething(2)">Second Spot</a></h3><p>Ut vulputate lobortis feugiat.</p><p>Ut nunc diam, malesuada iaculis viverra nec, auctor eget velit.</p>" 
1

正則表達式使用正則表達式來解析HTML已經被廣泛覆蓋。 The consensus is that it should not be done

如果你需要解析你的HTML,我會推薦使用類似HTML Agility Pack的東西。這允許你使用類似於xPath的東西來標識你想要處理的HTML。

+1

我從一些是不讀的問題的upvotes越來越感。我不解析HTML。字符串包含HTML的事實是微不足道的。我可以編輯OP並刪除HTML的所有痕跡,並以相同的問題結束。你是不是更想說一個正則表達式不應該被用來解析一個字符串?那可能。我列出了正則表達式的原因,這是我嘗試過的路線,但我願意接受它可能不是正確的方法。話雖如此,我仍在尋找解決這個問題的方法,而不是不該做什麼。我沒有處理有效的XML字符串,所以XML解析器不起作用。 – xr280xr

+0

我從標題中刪除了「正則表達式」,以免扼殺創意。感謝您的輸入。 – xr280xr

+0

我想說的正則表達式不應該用來解析一個字符串?不,這就是它的目的。爲了清楚起見,我不只是告訴你不要這麼做,我還向您指出了HTML Agility Pack,它旨在幫助您解析HTML(甚至格式錯誤的HTML)和NOT XML,正如您似乎在暗示的那樣。如果這不適合你,那麼我會推薦標準的字符串方法。無論如何,正則表達式是我試圖解決這個問題的最後一種方法。 –

0

我會使用string.split這個。

string emptyAnchor = "<a href=""#""></a>"; 
string src = GetData(); 
string[] splits = src.split(new string[]{"%%"}, StringSplitOptions.None); 
StringBuilder sb = new StringBuilder(); 

//first entry is blank, set to 1 
int i = 1; 
while(i < splits.length) 
{ 
    string id = splits[i]; 
    //increment for data string 
    i++; 
    //prehaps use a StringReplaceFirstOccurrence function instead 
    sb.Append(splits[i].Replace(emptyAnchor, GetDataFromID(id))); 
    i++; 
} 
string output = sb.ToString(); 
+0

我認爲這是使用字符串方法的正確軌道。這讓我想,也許我可以將它分割在分隔符上,並從那裏使用Regex.Replace,因爲每個集合中只有1次發生修改。但在我嘗試之前,我決定嘗試使用Regex.Replace和基本表達式來查看它是否可以處理它並且它可以處理它。所以你給了我一些啓發和替代。謝謝! – xr280xr

1

我會說你的正則表達式幾乎是你想要的 - 我已經稍微改變了它。這隻會在字符串的結尾工作,如果$比賽:

%%(\d+)%%(<a[^>]*)(></a>)(.*?)(?=%%\d|$) 

如果你決定使用這一點,那麼每場比賽,你可以訪問組,這樣就可以構建新的字符串 - 這將可能比替換現有字符串中的東西更容易。