2011-06-29 17 views
22

私がやっていることは、「専門用語集」を作ることです。 基本的に私はいくつかのhtmlといくつかの用語集をデータベースに持っています。 人が専門用語のバスターをクリックすると、テキスト内の単語が意味を示す素敵なツールチップ(wztooltip)に置き換えられます。 HTML内の単語の検索と置換

は、私はこの1つのハードしようとしてきたし、この質問 Regex/DOMDocument - match and replace text not in a link

で重く見て、答えがsimple_html_domのLIBSにあるように思えるが、私はそれが動作するのに問題を抱えています。明らかに既にリンクされている単語は触れられません。 ここに私が持っているもののストリップがあります。

$html = str_get_html($article['content']); 

$query_glossary = "SELECT word,glossary_term_id,info FROM glossary_terms WHERE status = 1 ORDER BY LENGTH(word) DESC"; 
$result_glossary = mysql_query_run($query_glossary); 

while($glossary = mysql_fetch_array($result_glossary)) { 
    $glossary_link = SITEURL.'/glossary/term/'.string_to_url($glossary['word']).'-'.$glossary['glossary_term_id']; 
    if(strlen($glossary['info'])>400) { 
     $glossary_info = substr(strip_tags($glossary['info']),0,350).' ...<br /> <a href="'.$glossary_link.'">Read More</a>'; 
    } 
    else { 
     $glossary_info = $glossary['info']; 
    } 
    $glossary_tip = 'href="javascript:;" onmouseout="UnTip();" class="article_jargon_highligher" onmouseover="'.tooltip_javascript('<a href="'.$glossary_link.'">'.$glossary['word'].'</a>',$glossary_info,400,1,0,1).'"'; 
    $glossary_word = $glossary['word']; 
    $glossary_word = preg_quote($glossary_word,'/'); 

    //once done we can replace the words with a nice tip  
    foreach ($html->find('text') as $element) { 
     if (!in_array($element->parent()->tag,array())) { 
      //problems are case aren't taken into account and grammer 
      $element->innertext = str_ireplace(''.$glossary['word'].' ',' <a '.$glossary_tip.' >'.$glossary['word'].'</a> ', $element->innertext); 

      //$element->innertext = str_ireplace(''.$glossary['word'].',',' <a '.$glossary_tip.'>'.$glossary['word'].'</a> ', $element->innertext); 
      //$element->innertext = preg_replace ("/\s(".$glossary_word.")\s/ise","nothing(' <a'.'$glossary_tip.'>'.'$1'.'</a> ')" , $element->innertext); 
      // $element->innertext = str_replace('__glossary_tip_replace__',$glossary_tip, $element->innertext); 
     } 
    } 
} 
$article['content'] = $html->save(); 
+0

私は同僚です。実際の問題は、単語内の単語ではなく、invidiaul単語にのみ一致するコードを得るのが難しいことです(つまり、おそらくAPS)。これらの単語はHTML内にもあります。だからそれは考慮する必要がある。 – David

+0

確かに、パワフルな正規表現を書いて、単語境界を検出するためにおそらく空白と句読点を使用するケースがありますが、私は自分自身を試して恥ずかしくないでしょう。+1 – shanethehat

+0

両方のタグを使用したため、JSソリューションまたはPHPソリューションが必要ですか? – Gerben

答えて

11

あなたの正規表現パターンの数字と文字以外の文字を選択するために、反転ワード文字\Wを使用してください。これはテキストブロブの境界でも失敗するため、これらの条件もテストする必要があります。このようにテキストとして単語「用語」を使用して、あなたが探している:用語はブロブの内容だけではないことを確認する

(^term$)|(^term\W)|(\Wterm\W)|(\Wterm$) 

最初の条件をチェックし、その最初の単語であれば第二のチェック、 3番目はブロブ内に含まれている場合は3番目、最後の単語の場合は最後になります。

他の文字を単語の文字(ハイフンなど)と見なす場合は、\Wには[^\w\-]と返す必要があります。

これが役に立ちます。おそらく同様に実行できる最適化がありますが、少なくともこれは良い出発点であるはずです。

+0

彼は単に '^'と '$'を '[]'に含めることもできます。 –

+2

^inside []は別のことを意味します。 $はドル記号に対応します。 しかし、あなたは(^ | \ W)(用語)(\ W | $)のような何かをすることができます – Gerben

+0

@Gerbenはるかに良い!しかし、これについてもう少し考えてみると、これと私の以前のパターンは別の問題を提示します:単語以外の文字もマッチに含まれます。これは、それらを除外する追加のロジックが必要です... – Rodaine

8

すべての用語集「単語」が標準の「単語」文字(つまり[A-Za-z0-9_])であると仮定すると、正規表現パターンの単語の前後に簡単な単語境界アサーションを配置できます。これでpertinant文を交換してみてください:

$element->innertext = preg_replace(
    '/\b'. $glossary_word .'\b/i', 
    '<a '. $glossary_tip .' >'. $glossary['word'] .'</a>', 
    $element->innertext); 

これは$glossary_wordは(あなたのコードはありません)トラフpreg_quoteを実行されていることを前提としています。

しかし、用語集に他の非標準の単語文字(たとえば、'-'ダッシュ)が含まれている場合は、見た目と見栄えを組み込んだより複雑な正規表現を作成して、単語全体が一致するようにすることができます。たとえば:

$re_pattern = "/   # Match a glossary whole word. 
    (?<=[\s'\"]|^)  # Word preceded by whitespace, quote or BOS. 
    {$glossary_word}  # Word to be matched. 
    (?=[\s'\".?!,;:]|$) # Word followed by ws, quote, punct or EOS. 
    /ix"; 
+0

ええ、この言葉が単語の形式と一致しないということがありました –

+0

@リチャード・ハウスハム:2番目の長い正規表現は、_any_ word(またはその点についてはスペースを含むフレーズ)でも機能します。 – ridgerunner

3

私は、個々の単語を取得JSでこの問題がありました。私がしたことは次のとおりでした(あなたはJSからPHPに変換できます):

実際には本当にうまく動作します。 :)

var words = document.body.innerHTML; 

// FIRST PASS 

// remove scripts 
words = words.replace(/<script[\s\S]*?>[\s\S]*?<\/script>/gi, ''); 
// remove CSS 
words = words.replace(/<style[\s\S]*?>[\s\S]*?<\/style>/gi, ''); 
// remove comments 
words = words.replace(/<!--[\s\S]*?-->/g, ''); 
// remove html character entities 
words = words.replace(/&.*?;/g, ' '); 
// remove all HTML 
words = words.replace(/<[\s\S]*?>/g, ''); 

// SECOND PASS 

// remove all newlines 
words = words.replace(/\n/g, ' '); 
// replace multiple spaces with 1 space 
words = words.replace(/\s{2,}/g, ' '); 

// split each word 
words = words.split(/[^a-z-']+/gi); 
関連する問題