3

リンクのリスト(配列内のhref)の単語リスト(配列内)をhtmlページに置き換えたいと思います。

私は主に2つのオプションがあると思います:

  1. 正規表現からこれを行う (html を解析して変更することは強くお勧めしません)。

  2. HTML パーサーを使用し、置換する単語とリンク リストごとに DOM を調べます。

2番目のオプションの問題は次のとおりです。

  1. タグが配置されているリストで見つかった各単語について知っておく必要がある、htmlページで以前に作成されたリンクを置き換えたくありません。

  2. DOM の各ノードの単語を置き換えたくありません。子を持たないノードのみ、つまりリーフのみを置き換えます。

簡単な例:

$aURLlist = array('www.google.com','www.facebook.com');
$aWordList = array('Google', 'Facebook');
$htmlContent='<html><body><div>Google Inc. is an American multinational corporation specializing in Internet-related services and products.</div><div>Facebook is an online social networking service, whose name stems from the colloquial name for the book given to students at the start of the academic year by some university administrations in the United States to help students get to know each other.</div></body></html>';
$dom = new DOMDocument();
$dom->loadHTML($htmlContent);
$htmlContent=walkingDom($dom,$aURLlist,$aWordList); //replace all words of $aWordList found in text nodes of $dom TO links with href equal to URL in $aURLlist

結果:

$htmlContent=<html><body><div><a href='www.google.com'>Google</a> Inc. is an American multinational corporation specializing in Internet-related services and products.</div><div><a href='www.facebook.com'>Facebook</a> is an online social networking service, whose name stems from the colloquial name for the book given to students at the start of the academic year by some university administrations in the United States to help students get to know each other.</div></body></html>';

DOMDocument lib を使用して DOM を移動する再帰関数がありますが、「アンカー」ノードを追加して、リーフの「テキスト」ノードにある単語を置き換えることはできません。

function walkDom($dom, $node, $element, $sRel, $sTarget, $iSearchLinks, $iQuantityTopics, $level = 0, $bLink = false) {
    $indent = '';
    if ($node->nodeName == 'a') {
        $bLink = true;
    }
    for ($i = 0; $i < $level; $i++)
        $indent .= '&nbsp;&nbsp;';
    if ($node->nodeType != XML_TEXT_NODE) {
        //echo $indent . '<b>' . $node->nodeName . '</b>';
        //echo $indent . '<b>' . $node->nodeValue . '</b>';

        if ($node->nodeType == XML_ELEMENT_NODE) {
            $attributes = $node->attributes;
            foreach ($attributes as $attribute) {
                //echo ', ' . $attribute->name . '=' . $attribute->value;
            }
            //echo '<br>';
        }
    } else {
        if ($bLink || $node->nodeName == 'img' || $node->nodeName == '#cdata-section' || $node->nodeName == '#comment' || trim($node->nodeValue) == '') {
            continue;
            //echo $indent;
            //echo 'NO replace: ';
            //var_dump($node->nodeValue);
            //echo '<br><br>';
        } elseif (!$bLink && $node->nodeName != 'img' && trim($node->nodeValue) != '') {
            //echo $indent;
            //echo "TEXT TO REPLACE: $element, $replace, $node->nodeValue, $iSearchLinks  <br>";
            $i = 0;
            $n = 1;
            while (i != $iSearchLinks && $n > 0 ) {
                //echo "Create link? <br>";

                $node->nodeValue = preg_replace('/'.$element->name.'/', '', $node->nodeValue, 1, $n);
                if ($n > 0) {
                    //echo "Creating link with $element->name <br>";
                    $link = $dom->createElement("a", $element->name);
                    $link->setAttribute("class", "nl_tag");
                    $link->setAttribute("id", "@@ID@@");
                    $link->setAttribute("hreflang", $element->type);
                    $link->setAttribute("title", $element->altname);
                    $link->setAttribute("href", $element->resource);
                    if ($sRel == "nofollow") $link->setAttribute("rel", $sRel);
                    if ($sTarget == "_blank") $link->setAttribute("target", $sTarget);
                    $node->parentNode->appendChild($link);
                    //var_dump($node->parentNode);
                    $dom->encoding = 'UTF-8';
                    $dom->saveHTML();
                    $iQuantityTopics++;
                }
                $i++;
                //saveHTML?
                //echo '<br><br>';
            }
        }
    }

appendChild 関数は子の最後にのみ新しい子を追加するため、このソリューションは機能しませんが、置換する単語が見つかった場所に追加したいと考えています。

また、preg_replace 関数を使用してリンク ダイレクトをリーフ テキスト ノードに追加しようとしましたが、アンカーが「テキスト形式」としてテキスト ノードに追加され、リーフ テキスト ノード内の単語を置き換えるリンク ノードとして追加する必要があります。位置しています。

私の質問は、PHP の html パーサーでこれを行うことは可能ですか、それとも正規表現に頼らなければならないのでしょうか? 前もって感謝します!

4

1 に答える 1

0

@スアメール:

「PHP エンジンがサポートしていないものがわからない: (?i)(?<!<[^>]*|>)(strWord)(?!<|[^<]*>)」
(?i)- はい、 i を最後に置く方が簡単ですが:

/(someregex)/i<br>
(?&lt;!<[^>]\*|>)

ここで先頭のタグを探しています。最初の < (一種の) を削除することで、これを機能させました。

したがって、最終的な正規表現は次のようになります。これは、実行しようとしていることに可能な限り近いものです。

/(?!<[^>]\*>).\*(strWord).\*(?!<\/[^<]\*>)/i<br>

ただし、はるかに単純なアプローチは次のようになります。

$text = "...";<br>
$words = array('him', 'her', ...);<br>
$links = array('&lt;a href="...">$0&lt;/a>', ...);<br>

foreach ($words as $word) {<br>
&emsp;array_push($regexes, "/\b{$word}\b/i");<br>
}<br>
$modified_array = preg_replace($regexes, $links, $text);<br>

$words と $links の要素数がまったく同じであることが重要です。そうしないと、エラーがスローされます。

$0 は、対応する正規表現の一致全体を参照します。この場合、探している特定の単語のみです。

また、preg_replace()各正規表現で修飾子が必要ないように、デフォルトで /g 修飾子を適用します。:-)

于 2014-02-17T19:56:15.717 に答える