2009-08-05 4 views
1

は、文字列が正規表現を使用して閉じていない最後のHTMLタグを見つけるにはどうすればよいですか?

 $string = "<body> 
       <img src='' alt= 
       "; 
であれば、それは別の例

最新閉じていないタグであるので、私は結果が「H1」になりたい私は、この文字列

 $string = "<html> 
       <body> 
       <h1> 
       <b>aaa</b> bbbb 
       "; 

を考えてみましょう

最新の非公開タグであるため、結果は「img」タグになります

正規表現ではできますが、正規表現を使用していないとわかりました

+3

...「閉鎖されていない」とはどういう意味ですか?最初の例では、 '

' *要素*は '

'が存在しないため、閉じられていません。 2番目の例では、 ''には '>'がありません。これは閉じられていない*タグ*ですが、HTML以外の文書( '>'が与えられている場合)では閉じられていない*要素です。 –

答えて

3

検索するパターンではないため、正規表現ではこれを行うことはできません。

私はスタックを使用して文字列を調べています。開いているタグがスタックに置かれるたびに、一致する終了タグがスタックから削除されるたびに表示されます。

あなたは例1の最初の部分を通り抜けたのであれば:

<html> 
    <body> 
    <h1> 
     <b> 

あなたのスタックは次のようになります。

HTML、ボディ、H1、

B次B閉じ、それをスタックから削除すると、スタックは次のようになります。

html、body、h1

ここで、スタック(h1)の上にあるタグは、常にあなたが探しているタグです。

あなたが私に何かを得ることを望みます、私に知らせていないならば。

0

私はほとんどの正規表現を書き始めたが、私はまた、潜在的に終了タグとして評価でき、テキストを含む(例えば、属性値など)のコメントと文字列を無視しなければならないことを認識した後、あきらめた:

$string = "<html> 
       <body> 
       <h1> 
       <b>aaa</b> bbbb 
       <!--</h1> maybe it's silly to have such a comment but who knows--> 
       "; 
+0

これは本当に問題ではありません。コメントを削除し、新しい文字列を新しい変数に格納して正規表現を実行します。 – usoban

3

私のアドバイスは、正規表現ではなく、実際のパーサーを使用することです。

+0

私はそれも考えましたが、彼の入力はほとんどソースコードが無効であるようです。あなたが私に尋ねるならば、それを解析することは非常にスマートな動きではありません。 –

+0

私たちのソフトウェアではhtmlpurifierを使用して、ユーザーが送信した無効なコードを修正しています。それはhtmlpurifierの主なタスクです。 –

+0

はい、彼は壊れたコードを修正したくありません。彼の入力は壊れたコードであり、彼はそれを使用したいと思っています。パーサーが問題を修正し、結果を変更します。だから私はパーサーを使うことに反対して投票します。 –

0

以下のコードは、構文解析を行うために正規表現のカップルを使用しています。実際の世界のhtmlは、タグやコードの中にランダムなスペースやタブetzを挿入すると簡単に壊れるかもしれないことに注意してください。以下のコードには、問題コードを実行するための一連のテストケースが含まれています。

ここでのアイデアは、まずhtmlをクリーンアップしてから、終了タグでタグを削除し、最後に利用可能な最後のタグを戻すことです。

<html> 

<head><title>Last Open HTML Tag</title> 

<body> 

<h1>Last Open HTML Tag</h1> 
<?php 

$htmlstrings[] ="<html> 
       <body> 
       <h1> 
       <b>aaa</b> bbbb 
       "; 

$htmlstrings[] ="<html> 
       <body> 
       <h3>test</h3> 
       <h1> 
       <b>aaa <i>test2</i></b> <i>test</i> bbbb 
       "; 

$htmlstrings[] = "<body> 
       <img src='' alt= 
       "; 

$htmlstrings[] = "<body> 
       < img src='' alt= 
       "; 

$num = 1;    
foreach($htmlstrings as $rawstring){ 
    // First remove whitespace in tags 
    $string = preg_replace ("/<\s*(\w)/", "<$1", $rawstring); 
// $string = preg_replace ("/<\s*/\s*(\w)/", "</$1", $string); 

    $real_matches = array(); 

    // Find open html tag (<a ...) 
    if(preg_match("/<(\w*)\W[^><]*$/", $string, $matches) > 0){ 
     $real_matches = $matches; 
    // Find html tag with no end tag (<h1>...) 
    } else { 
     $newstrin = null; 
     while(true){ 
      $newstring = preg_replace("/<(\\w*)>[^<>]*<\\/\\1>/s", "", $string); 
      if($newstring == $string){ 
       break; 
      } 
      $string = $newstring; 
     } 
     preg_match("/<(\\w*)>[^<>]*$/", $newstring, $matches); 
     $real_matches = $matches; 
    } 

    echo "<p>Parse $num\n"; 
    $rawstring = preg_replace ("/</is", "&lt;", $rawstring); 
    $rawstring = preg_replace ("/>/is", "&gt;", $rawstring); 
    echo "<br>$rawstring\n"; 
    foreach($real_matches as $match){ 
     $result = preg_replace ("/</is", "&lt;", $match); 
     $result = preg_replace ("/>/is", "&gt;", $result); 
     echo "<br>" . $result . "\n"; 
    } 
    $num++; 

    echo "<br>LAST OPEN TAG: " . $matches[1] . "\n"; 
} 

?> 
</body> 
</html> 
関連する問題