使用DOM的PHP关键字突出显示

时间:2011-11-01 16:50:21

标签: php dom

我使用Highlight keywords in a paragraph中的以下功能突出显示字符串中的关键字。因此它会生成此警告:

Warning: DOMDocument::loadHTML() [domdocument.loadhtml]: htmlParseEntityRef: expecting ';' in Entity, line: 1 in /../ on line 118

在这个帖子Warning: DOMDocument::loadHTML(): htmlParseEntityRef: expecting ';' in Entity,之后,答案建议使用html权利编码,但这样做会错过使用DOM搜索字符串并突出显示而不破坏标记的全部目的。例如。 htmlentities和html_entity_decode会突出显示alla出现。

我该如何解决这个问题?或者我缺少的功能还有其他一些问题吗?

function highlight($string,$query){
    $keywords = explode(" ",$query);
    //define
    $keywordsCIS = array();
    foreach($keywords as $value){
        $lcValue = strtolower($value);
        $keywordsCIS[] = $value;
        $keywordsCIS[] = $lcValue;
        $keywordsCIS[] = ucfirst($lcValue);
        $keywordsCIS[] = strtoupper($lcValue);
    }
    $dom = new DomDocument();
    $dom ->recover = true;
    $dom -> strictErrorChecking = false;
    $dom -> loadHtml($string);
    $xpath = new DomXpath($dom);
    foreach ($keywordsCIS as $keyword) {
        $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('strong');
                    $highlight->appendChild(new DomText($word));
                    $highlight->setAttribute('class', 'kw');
                    $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);
    $string = $dom->saveHTML();
    return $string;
}

2 个答案:

答案 0 :(得分:0)

我相信你得到的警告来自DomDocument试图解析的html。我假设您实际上并不希望在解析之前更改正在解析的$string中的html内容。

尝试使用loadHTML行上的@ operator来避免警告:

@$dom->loadHtml($string);

答案 1 :(得分:0)

如果您的HTML包含this & that,或者包含&的任何其他内容,则解析器将查找实体。它应该是&。这也适用于HTML验证。

您可以忽略@$dom->loadHTML($string);的错误,在这种情况下不会出现太多问题。也就是说,在使用这样的解析器时,您应该小心正确格式化HTML。