有人有正則表達式來匹配未封閉的HTML標記嗎?正則表達式用於未封閉的HTML標記
<i><b>test<i>ing</i>
是對正則表達式這樣太複雜:例如,正則表達式將在<b>
和第二<i>
,但不是第一<i>
或第一的收盤</i>
標籤相匹配?可能需要一些遞歸的,程序化的處理?
有人有正則表達式來匹配未封閉的HTML標記嗎?正則表達式用於未封閉的HTML標記
<i><b>test<i>ing</i>
是對正則表達式這樣太複雜:例如,正則表達式將在<b>
和第二<i>
,但不是第一<i>
或第一的收盤</i>
標籤相匹配?可能需要一些遞歸的,程序化的處理?
我敢肯定,一些正則表達式的大師可以拼湊一些近似解決方案的東西,但這是一個壞主意:HTML isn't regular。考慮一個能夠識別這些問題的HTML解析器,或者自己解析它。
是的它需要遞歸處理,並且可能很深(當然是一個奇特的循環),它不會用正則表達式來完成。你可以製作一個深度處理幾個級別的正則表達式,但不能用於任何HTML文件。這是因爲解析器必須記住流中任何給定點處打開了哪些標記,而正則表達式並不擅長。
對某些計數器使用SAX解析器,或者使用彈出/推入的堆棧來保持您的狀態。想想如何編碼這個遊戲來查看我對html標籤深度的意思。 http://en.wikipedia.org/wiki/Tower_of_Hanoi
正如@Pesto說的,HTML不規則,你將不得不建立HTML語法規則,並遞歸應用它們。
如果您希望以編程方式修復HTML,我使用了一個名爲html tidy的組件,取得了相當的成功。對於大多數語言(COM +,Dotnet,PHP等),都有它的構建。
如果你只是需要手動修復它,我會推薦一個好的IDE。 Visual Studio 2008做得很好,最新的Dreamweaver也做得很好。
不,這對於正則表達式來說很複雜。你的問題相當於測試正確使用括號的算術表達式,它至少需要pushdown automaton才能成功。
對於您的情況,您應該在打開標記,關閉標記和文本節點(例如使用正則表達式)中分割HTML代碼。將結果存儲在一個列表中。然後,您可以遍歷節點列表並將每個開始標記推入堆棧。如果在節點列表中遇到結束標記,則必須檢查最上面的堆棧條目是否是同一類型的開始標記。否則,您會發現您查找的html語法錯誤。
我有一個案例,我處理單一自包含行的我am。以下正則表達式適用於我:<[^/]+$
,它與「<
」匹配,然後是不是「/
」的任何內容。
我建議使用Nokogiri:
Nokogiri::HTML::DocumentFragment.parse(html).to_html
您可以使用正則表達式來識別所有的HTML開始/結束元素,然後用棧枚舉,推新的元素,和流行的結束標記。在C#中試試這個 -
public static bool ValidateHtmlTags(string html)
{
string expr = "(<([a-zA-Z]+)\\b[^>]*>)|(</([a-zA-Z]+) *>)";
Regex regex = new Regex(expr, RegexOptions.IgnoreCase);
var stack = new Stack<Tuple<string, string>>();
var result = new StringBuilder();
bool valid = true;
foreach (Match match in regex.Matches(html))
{
string element = match.Value;
string beginTag = match.Groups[2].Value;
string endTag = match.Groups[4].Value;
if (beginTag == "")
{
string previousTag = stack.Peek().Item1;
if (previousTag == endTag)
stack.Pop();
else
{
valid = false;
break;
}
}
else if (!element.EndsWith("/>"))
{
// Write more informative message here if desired
string message = string.Format("Char({0})", match.Index);
stack.Push(new Tuple<string, string>(beginTag, message));
}
}
if (stack.Count > 0)
valid = false;
// Alternative return stack.Peek().Item2 for more informative message
return valid;
}
太糟糕了SO沒有API。我想象的是:for(問題q:questionsTagged(「regex」,「html」)){q.addAnswer(new Answer(「HTML不規則,所以正則表達式幾乎不是一個好的選擇。「);}` – 2009-08-03 18:08:45