PHP搜索文本突出显示函数
我有一个PHP突出显示功能,可以使某些单词加粗 下面是函数,它工作得很好,除非数组:$words包含一个值,即:b 例如,有人搜索:jessie j price tag feat b o b 这将在数组$words中包含以下条目:jessie、j、price、tag、feat、b、o、b 当一个“b”出现时,我的整个函数都出错了,它显示了一大堆错误的html标记。当然,我可以从数组中去掉任何“b”值,但这并不理想,因为高亮显示在某些查询中无法正常工作 此示例脚本:PHP搜索文本突出显示函数,php,highlight,Php,Highlight,我有一个PHP突出显示功能,可以使某些单词加粗 下面是函数,它工作得很好,除非数组:$words包含一个值,即:b 例如,有人搜索:jessie j price tag feat b o b 这将在数组$words中包含以下条目:jessie、j、price、tag、feat、b、o、b 当一个“b”出现时,我的整个函数都出错了,它显示了一大堆错误的html标记。当然,我可以从数组中去掉任何“b”值,但这并不理想,因为高亮显示在某些查询中无法正常工作 此示例脚本: function hi
function highlightWords2($text, $words)
{
$text = ($text);
foreach ($words as $word)
{
$word = preg_quote($word);
$text = preg_replace("/\b($word)\b/i", '<b>$1</b>', $text);
}
return $text;
}
$string = 'jessie j price tag feat b o b';
$words = array('jessie','tag','b','o','b');
echo highlightWords2($string, $words);
函数highlightWords2($text,$words)
{
$text=($text);
foreach($words作为$word)
{
$word=preg_quote($word);
$text=preg_replace(“/\b($word)\b/i”,“$1”,“$text”);
}
返回$text;
}
$string='jessie j price tag feat b o b';
$words=array('jessie','tag','b','o','b');
echo highlightWords2($string,$words);
将输出:
<<<b>b</b>><b>b</b></<b>b</b>>>jessie</<<b>b</b>><b>b</b></<b>b</b>>> j price <<<b>b</b>><b>b</b></<b>b</b>>>tag</<<b>b</b>><b>b</b></<b>b</b>>> feat <<b>b</b>><b>b</b></<b>b</b>> <<b>b</b>>o</<b>b</b>> <<b>b</b>><b>b</b></<b>b</b>>
jessie j价格标签壮举
这仅仅是因为数组中有“b”
你们能看到我能做些什么来让它正常工作吗?如果是我,我会使用javascript 但是使用PHP,因为问题似乎只是搜索中的重复条目,只需删除它们,也可以只运行一次preg_replace,而不是多次
$string = 'jessie j price tag feat b o b';
$words = array('jessie','tag','b','o','b');
print hl($string, $words);
function hl($inp, $words)
{
$replace=array_flip(array_flip($words)); // remove duplicates
$pattern=array();
foreach ($replace as $k=>$fword) {
$pattern[]='/\b(' . $fword . ')\b/i';
$replace[$k]='<b>$1<b>';
}
return preg_replace($pattern, $replace, $inp);
}
$string='jessie j price tag feat b o b';
$words=array('jessie','tag','b','o','b');
打印hl($string,$words);
函数hl($inp,$words)
{
$replace=array\u flip(array\u flip($words));//删除重复项
$pattern=array();
foreach($替换为$k=>$fword){
$pattern[]='/\b('.$fword.)\b/i';
$replace[$k]=“1美元”;
}
返回preg_replace($pattern,$replace,$inp);
}
您的问题是,当您的函数通过并查找所有要加粗的b时,它会看到加粗标记,并尝试加粗它们
@symcbean很接近,但忘了一件事
$string = 'jessie j price tag feat b o b';
$words = array('jessie','tag','b','o','b');
print hl($string, $words);
function hl($inp, $words)
{
$replace=array_flip(array_flip($words)); // remove duplicates
$pattern=array();
foreach ($replace as $k=>$fword) {
$pattern[]='/\b(' . $fword . ')(?!>)\b/i';
$replace[$k]='<b>$1</b>';
}
return preg_replace($pattern, $replace, $inp);
}
$string='jessie j price tag feat b o b';
$words=array('jessie','tag','b','o','b');
打印hl($string,$words);
函数hl($inp,$words)
{
$replace=array\u flip(array\u flip($words));//删除重复项
$pattern=array();
foreach($替换为$k=>$fword){
$pattern[]='/\b('.$fword.)(?!>)\b/i';
$replace[$k]=“1美元”;
}
返回preg_replace($pattern,$replace,$inp);
}
您是否看到这个添加了“(?!>”,这是一个否定的前瞻性断言,基本上它表示只有在字符串后面没有“>”时才匹配,而“>”就是打开粗体标记和关闭粗体标记。注意,我只在字符串后面检查“>”,以排除开头和结尾的粗体标记,因为在字符串开头查找它不会捕获结尾的粗体标记。上述代码的工作原理与预期完全相同。您的基本问题是在HTML中大量替换纯文本字符串。在替换标记和属性中的文本时,这确实会导致小字符串出现问题 相反,您只需要将搜索和替换应用于HTML文本之间的文本。此外,您也不希望在另一个高亮显示内高亮显示 要做到这一点,正则表达式是非常有限的。而是使用HTML解析器,在PHP中,这是例如
DOMDocument
。使用HTML解析器,可以只在HTML文本元素内部进行搜索(而不搜索标签、属性和注释等其他内容)
您可以在中找到文本的高亮显示,并详细说明其工作原理。问题是,它与您的问题非常相似,因此此片段可能很有用,它使用
而不是
标记:
$doc = new DOMDocument;
$doc->loadXML($str);
$xp = new DOMXPath($doc);
$anchor = $doc->getElementsByTagName('body')->item(0);
if (!$anchor)
{
throw new Exception('Anchor element not found.');
}
// search elements that contain the search-text
$r = $xp->query('//*[contains(., "'.$search.'")]/*[FALSE = contains(., "'.$search.'")]/..', $anchor);
if (!$r)
{
throw new Exception('XPath failed.');
}
// process search results
foreach($r as $i => $node)
{
$textNodes = $xp->query('.//child::text()', $node);
// extract $search textnode ranges, create fitting nodes if necessary
$range = new TextRange($textNodes);
$ranges = array();
while(FALSE !== $start = strpos($range, $search))
{
$base = $range->split($start);
$range = $base->split(strlen($search));
$ranges[] = $base;
};
// wrap every each matching textnode
foreach($ranges as $range)
{
foreach($range->getNodes() as $node)
{
$span = $doc->createElement('span');
$span->setAttribute('class', 'search_hightlight');
$node = $node->parentNode->replaceChild($span, $node);
$span->appendChild($node);
}
}
}
如果您对多个搜索词采用它,我会添加一个额外的类,根据搜索词的不同,添加一个数字,这样您就可以用不同颜色的CSS很好地为它设置样式
此外,您应该删除重复的搜索词,并使xpath表达式意识到不要查找已经是指定了突出显示范围的元素的一部分的文本。您在哪里找到该函数的?我在某个地方在线找到了它,但实际上我刚刚解决了我的问题。如果我将and更改为和,则它可以正常工作。preg_replace中的\b必须使用和标记。这是一个解决方法,直到
strong
成为搜索词。是否需要突出显示carport
中的carport或carport
中的carport等词?即将发布相同的内容。我还建议改为使用preg_replace with array,因为这样可以将文本的读取量限制为一次,从而消除复杂性并提高速度。如果文本具有包含搜索词的HTML属性,该怎么办?还是HTML注释?还是javascript?@hakre是的,如果你有什么废话,那会引起问题,这会让它废话连篇。除了在通过突出显示功能运行之前清理所有html的输入之外,我不能100%确定如何解决这个问题。非常感谢@Josh先生。。。这节省了我的时间!:)为了避免在HTML标记中使用@JoshStrange所说的文本,您可以正确地使用strip_tags()
仅用于与正则表达式匹配。我在搜索词中的实体(应该用CSS类突出显示)也遇到了问题,并提出了类似的建议:$decoded=html\u entity\u decode($words,ENT\u COMPAT,'UTF-8')代码>。