DOM Parser 突出显示关键字不起作用

Posted

技术标签:

【中文标题】DOM Parser 突出显示关键字不起作用【英文标题】:DOM Parser to highlight keywords not working 【发布时间】:2012-03-09 07:00:22 【问题描述】:

这个问题与我提出的before 相关,但由于该主题现已关闭,我需要进一步提问,我将开始一个新问题,希望没问题。

在我之前的回答中,我充分简化了问题,并产生了简单但不完全有效的解决方案。这些天我在实现我的代码时意识到了这一点。

上一篇文章中解决方案的问题是html标签被替换功能破坏了。我在该站点的许多帖子中阅读了我需要使用 DOM Parser 的内容。我对此非常陌生,我尝试了用户“ircmaxell”在此post 中建议的代码,但它对我不起作用。

这是我所做的示例:

echo '<style type="text/css">
       .ht
         background-color: yellow;
       
     </style>'; 


/* taken from user ircmaxell at https://***.com/questions/4081372/highlight-keywords-in-a-paragraph

I just modified line $highlight->setAttribute('class', 'highlight') to $highlight->setAttribute('class', 'ht') and commented the first 2 lines   */

function highlight_paragraph($string, $keyword) 
  //$string = '<p>foo<b>bar</b></p>';
  //$keyword = 'foo';
  $dom = new DomDocument();
  $dom->loadHtml($string);
  $xpath = new DomXpath($dom);
  $elements = $xpath->query('//*[contains(.,"'.$keyword.'")]');
  foreach ($elements as $element) 
   foreach ($element->childNodes as $child) 
     if (!$child instanceof DomText) continue;
     $fragment = $dom->createDocumentFragment();
     $text = $child->textContent;
     $stubs = array();
     while (($pos = stripos($text, $keyword)) !== false) 
       $fragment->appendChild(new DomText(substr($text, 0, $pos)));
       $word = substr($text, $pos, strlen($keyword));
       $highlight = $dom->createElement('span');
       $highlight->appendChild(new DomText($word));
       $highlight->setAttribute('class', 'ht');
       $fragment->appendChild($highlight);
       $text = substr($text, $pos + strlen($keyword));
     
     if (!empty($text)) $fragment->appendChild(new DomText($text));
     $element->replaceChild($fragment, $child);
   
 
 $string = $dom->saveXml($dom->getElementsByTagName('body')->item(0)->firstChild);
 return $string;



$string = '<p>This book has been written against a background of both reckless optimism and reckless despair.</p>
<p>It holds that Progress and Doom are two sides of the same medal; that both are articles of superstition, not of faith. It was written out of the conviction that it should be possible to discover the hidden mechanics by which all traditional elements of our political and spiritual world were dissolved into a conglomeration where everything seems to have lost specific value, and has become unrecognizable for human comprehension, unusable for human purpose.</p>
<p> Hannah Arendt, The Origins of Totalitarianism (New York: Harcourt Brace Jovanovich, Inc., 1973 ed.), p.vii, Preface to the First Edition.</p>';

$keywords = array('This', 'book', 'has', 'been', 'written', 'background', 'reckless', 'optimism', 'despair.', 'holds', 'Progress', 'Doom ', 'two', 'sides', 'medal;', 'articles', 'superstition,', 'faith.', 'lost', 'Arendt,', 'Totalitarianism');

foreach ($keywords as $kw) 
  $string = highlight_paragraph($string, $kw);


echo $string;

echo $string 只返回:

This book has been written against a background of both reckless optimism and reckless despair.

只有前两个单词“This”和“book”被突出显示。

通常它应该输出所有带有突出显示的关键字的初始字符串。

我在 *** 和 google 中搜索了很多,但没有找到一个易于使用的代码来实现我的目的,即使之前有很多人问过同样的问题。

我在这里真的需要帮助。提前致谢!

【问题讨论】:

【参考方案1】:

你很幸运,当我看到这个问题时,我非常感到无聊。 ;)

您收到的作为答案的代码似乎没有经过测试 - 我不知道它是如何正常工作的。无论如何,我解决了所有问题并为您提供了一个工作版本 - 在我本地安装的 Apache 服务器上使用 php 5.3 进行了测试:

function highlight_paragraph($string, $keyword) 
  $dom = new DOMDocument();
  $dom->loadHtml($string);

  // Search for all text blocks containing the keyword
  $xpath = new DOMXpath($dom);
  $textNodes = $xpath->query('//*[contains(.,"'.$keyword.'")]/text()');

  foreach ($textNodes as $textNode) 
    $fragment = $dom->createDocumentFragment();
    $text = $textNode->nodeValue;
    $stubs = array();

    while (($pos = stripos($text, $keyword)) !== false) 
      $fragment->appendChild(new DOMText(substr($text, 0, $pos)));
      $word = substr($text, $pos, strlen($keyword));

      $highlight = $dom->createElement('span');
      $highlight->appendChild(new DOMText($word));
      $highlight->setAttribute('class', 'ht');
      $fragment->appendChild($highlight);

      $text = substr($text, $pos + strlen($keyword));
    

    if (!empty($text))
      $fragment->appendChild(new DOMText($text));

    $textNode->parentNode->replaceChild($fragment, $textNode);
 

 return $dom->saveHTML();

【讨论】:

这个答案对my question有帮助。谢谢! 非常感谢您的无聊! :-) 天啊,终于。 @denisw 你是个传奇。但是当我在结果上运行它时,我看到了这个错误:“严重性:警告消息:DOMDocument::loadHTML(): htmlParseEntityRef: no name in Entity”有什么想法吗? 发现问题。源代码中的 HTML 格式不正确。通过添加修复:libxml_use_internal_errors(true);在 loadHTML 行上方 我发现的一件事是突出显示不区分大小写。 EG 关键字是“Andrew”,所以从 db 返回带有“andrew”的结果,但不突出显示【参考方案2】:

上述解决方案不起作用.. 这是一个非常老套但可靠的解决方法,以避免突出显示和破坏 html。

function highlight_fancy($string, $keywords=array()) 
    $dom = new DOMDocument();
    $dom->loadHtml($string);

    // Search for all text blocks containing the keyword
    $xpath = new DOMXpath($dom);
    foreach($keywords as $keyword)
        $textNodes = $xpath->query('//*[contains(.,"'.$keyword.'")]/text()');

        foreach ($textNodes as $textNode) 
            $fragment = $dom->createDocumentFragment();
            $text = $textNode->nodeValue;
            $stubs = array();

            while (($pos = stripos($text, $keyword)) !== false) 
                $fragment->appendChild(new DOMText(substr($text, 0, $pos)));
                $word = substr($text, $pos, strlen($keyword));

                $highlight = $dom->createElement('span');
                $highlight->appendChild(new DOMText($word));
                $highlight->setAttribute('class', 'hl');
                $fragment->appendChild($highlight);

                $text = substr($text, $pos + strlen($keyword));
            

            if (!empty($text))
                $fragment->appendChild(new DOMText($text));

            $textNode->parentNode->replaceChild($fragment, $textNode);
        
    
    $html= $dom->saveHTML();
    $e=explode("<body><p>",$html);
    $e=explode("</p></body>",$e[1]);
    return $e[0];

【讨论】:

以上是关于DOM Parser 突出显示关键字不起作用的主要内容,如果未能解决你的问题,请参考以下文章

将 UIImageView 从正常更改为突出显示不起作用

jQuery 突出显示在 bootstrap v4 按钮上不起作用

Sublime 3 编辑器语法突出显示 PHP + HTML 不起作用

IBM Worklight 6.1 - 禁用焦点上的橙色轮廓突出显示不起作用

Visual Studio 2010-intellisense 和 javascript 中的突出显示不起作用

比较两张纸上的值,突出显示相似之处,运行但不起作用