я пытаюсь сделать «жаргон». В основном у меня есть некоторые html и некоторые термины глоссария в базе данных. Когда человек нажимает на jargon buster, он заменяет слова в тексте хорошей подсказкой (wztooltip), которая показывает им значения.
Я очень стараюсь в этом вопросе и сильно смотрю на этот вопрос Regex / DOMDocument – сопоставляю и заменяю текст не ссылкой
и кажется, что ответ лежит в файлах simple_html_dom, но у меня возникают проблемы с его работой. Очевидно, что любые слова, уже связанные, не затрагиваются. Вот полоса от того, что у меня есть.
$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();
Используйте символ инвертированного слова \W
чтобы выбрать для любых символов, кроме цифр и букв, в вашем шаблоне регулярного выражения. Поскольку это все равно будет терпеть неудачу на границах текстового блока, вам также необходимо будет проверить эти условия. Таким образом, используя слово «термин» в качестве текста, который вы ищете:
(^term$)|(^term\W)|(\Wterm\W)|(\Wterm$)
Первое условие проверяет, чтобы этот термин не был единственным содержимым blob, второй проверяет, имеет ли его первое слово, третье, если оно содержится внутри blob, и последнее, если оно имеет последнее слово.
Если вы хотите рассматривать любые другие символы как символы слов (например, дефис), вам нужно будет отменить \W
с помощью [^\w\-]
.
Надеюсь это поможет. Возможно, есть оптимизация, которая может быть выполнена, но это, по крайней мере, должно быть хорошей отправной точкой.
Предполагая, что все слова «слова» вашего словаря состоят из стандартных «словесных» символов (т. [A-Za-z0-9_]
), тогда утверждение слова с простым словом может быть помещено до и после слова в шаблоне регулярных выражений. Попробуйте заменить это утверждение следующим образом:
$element->innertext = preg_replace( '/\b'. $glossary_word .'\b/i', '<a '. $glossary_tip .' >'. $glossary['word'] .'</a>', $element->innertext);
Это предполагает, что $glossary_word
выполняется через preg_quote
(что делает ваш код).
Однако, если слова глоссария могут содержать другие нестандартные словарные символы (например, '-'
тире), может быть сформулировано более сложное регулярное выражение, которое включает в себя lookahead и lookbehind для обеспечения соответствия только целых слов. Например:
$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";
У меня была эта проблема в 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(/[^az-']+/gi);