2009-08-03 14 views
2

クローズドHTMLタグに一致する正規表現を誰かが持っていますか?閉じられていないHTMLタグの正規表現

<i><b>test<i>ing</i> 

は、正規表現のために、この複雑すぎる:たとえば、正規表現は、<b><i>秒ではなく、最初の<i>か、初の決算</i>タグと一致でしょうか?いくつかの再帰的なプログラム処理が必要なのでしょうか?

答えて

6

確かに、いくつかの正規表現の達人が解決策に近似しているものを一緒に投げつけることができますが、それは悪い考えです:HTML isn't regular。このような問題を識別できるHTMLパーサーか、それとも自分で解析するかを検討してください。

+3

あまりにも悪いのは、APIがありません。私は次のようなものを描いています: 'for(Question q:questionsTagged(" regex "、" html ")){q.addAnswer(new Answer(" HTMLは正規ではないので、正規表現は決して良い選択ではありません。");} –

+2

もちろん、OPが質問の中でその反応を先制したら、あなたはここでほとんどそうしたように見えます。 –

+0

@mmyers:正に、私は何かにリンクする機会に抵抗できませんでしたウェルボットの – Pesto

2

はい、再帰的な処理が必要であり、潜在的にはかなり深い(または幻想的なループです)、正規表現では実行されません。いくつかのレベルを扱った正規表現は作成できますが、htmlファイルだけでは動作しません。これはパーサーがストリーム内の任意の点で開いているタグを覚えていなければならず、正規表現がそれほどうまくいかないからです。

いくつかのカウンターでSAXパーサーを使用するか、ポップ・オフ/プッシュオンのスタックを使用して状態を維持してください。このゲームをどのようにコーディングしてhtmlタグの深さがどういう意味であるかを考えてみてください。 http://en.wikipedia.org/wiki/Tower_of_Hanoi

1

@Pestoによると、HTMLは規則的ではないので、html文法規則を作成して再帰的に適用する必要があります。

プログラムでHTMLを修正しようとしている場合は、html tidyというコンポーネントを使用してかなりの成功を収めています。ほとんどの言語(COM +、Dotnet、PHPなど)のビルドがあります。

手動で修正する必要がある場合は、いいIDEをお勧めします。 Visual Studio 2008は優れた仕事をしますが、最新のDreamweaverもそうです。

1

いいえ、それは正規表現では複雑です。あなたの問題は、成功のために少なくともpushdown automatonを必要とするブラケットの適切な使用の算術式をテストすることと同等です。

あなたの場合、開始タグ、終了タグ、テキストノード(例:正規表現)でHTMLコードを分割する必要があります。結果をリストに格納します。次に、ノードリストを反復して、すべての開始タグをスタックにプッシュすることができます。ノードリストに終了タグがある場合は、最上位のスタックエントリが同じタイプの開始タグであることを確認する必要があります。それ以外の場合は、あなたが探しているHTML構文エラーが見つかりました。

1

私は、の場合、単独の自己完結型の線を扱う場合があります。次の正規表現が私のために働いた:<[^/]+$ "<"と一致し、 "/"以外のもの。

0

私はNokogiriを使用することをお勧め:

 
    Nokogiri::HTML::DocumentFragment.parse(html).to_html 
1

あなたはすべての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; 
}