2012-02-17 6 views
4

この質問は、beforeと関連していますが、トピックが閉鎖されているため、さらに質問する必要があります。DOMパーサーがキーワードを強調表示しない

私の以前の答えでは、私は問題を十分に単純化し、単純ではあるが完全には機能しない解決策に終わった。私は最近、私のコードを実装していたときにそれを実現しました。

前の記事の解決策の問題は、置き換え機能によってHTMLタグが壊れてしまうことです。私はこのサイトの多くの記事で、DOM Parserを使用する必要があると読んでいます。私はこれに非常に慣れていないし、このpostのユーザー "ircmaxell"によって提案されたコードを試しましたが、それは私のためには機能しません。ここで

は私がやったことのサンプルです:

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


/* taken from user ircmaxell at https://stackoverflow.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; 

エコー$文字列のみを返します。

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

そして、最初の2つの言葉を、 'これ' と 'ブック' が強調表示されます。

通常、強調表示されたキーワードを含むすべての初期文字列が出力されているはずです。

私は以前stackoverflowとgoogleで多くの検索をしていましたが、同じことを以前に頼んだ人がたくさんいても目的を達成するために使いやすいコードは見つかりませんでした。

本当に助けが必要です。前もって感謝します!

答えて

7

私はこの質問を見たときに私が非常にであったことに幸運です。 ;)

答えとして受け取ったコードは、テストされていないようです。正しく動作する可能性があるかどうかわかりません。とにかく、私はすべての問題を修正し、あなたの作業バージョン発表 - PHP 5.3で自分のローカルにインストールされたApacheサーバ上でテスト:

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(); 
} 
+0

をこの答えは、[私の質問](http://stackoverflow.com/questions/を手伝ってくれました15526781/regular-expression-negative-lookahead-lookbehind-to-exclude-html-from-find-and-r)。ありがとう! – TerranRich

+1

退屈してくれてありがとう! :-) –

+0

Omg、最後に。あなたは伝説です。 私は結果でそれを実行したとき、私はかかわらず、このエラーを見ています: 「重大度:警告 メッセージ:のDOMDocument :: loadHTML():htmlParseEntityRef:エンティティで名前のない」 任意のアイデア? – Solvision

関連する問題