PHP Token replaces html entities

早过忘川 提交于 2019-12-08 19:30:35
Herbert

This pair of functions should do what you want without the problems that come with parsing HTML with regex or str_replace.

function process($node, $replaceRules)
{
    if($node->hasChildNodes()) {
        $nodes = array();
        foreach ($node->childNodes as $childNode) {
            $nodes[] = $childNode;
        }
        foreach ($nodes as $childNode) {
            if ($childNode instanceof DOMText) {
                $text = preg_replace(
                    array_keys($replaceRules),
                    array_values($replaceRules),
                    $childNode->wholeText);
                $node->replaceChild(new DOMText($text),$childNode);
            }
            else {
                process($childNode, $replaceRules);
            }
        }
    }
}

function addLinks($str_in, $replaces)
{
    $replaceRules = array();    
    foreach($replaces as $k=>$v) {
        $k = '/\b(' . $k . ')\b/i';
        $v = '<a href="' . $v . '">$1</a>';
        $replaceRules[$k] = $v;
    }

    $doc = new DOMDocument;
    $doc->loadHTML($str_in);
    process($doc->documentElement, $replaceRules);
    return html_entity_decode($doc->saveHTML());
}

Note: No need to worry if the HTML is not well structured (as in your example); however, the output will be well structured.

Credit where it’s due: The recursive process() function, which does most of the real work, comes direclty from Lukáš Lalinský’s answer to How to replace text in HTML. The addLinks() function is just a use case tailored to fit your question.

Marc B

Not sure why you've got that large construction, when something like:

$str_out = preg_replace('/(' . preg_quote(implode('|', array_keys($replaces))) . ')/', $replaces[$1], $str_in);

would accomplish about the same thing. Of course, using regexes to process HTML is a hazardous process. You should use DOM with some xpath to do this more reliably.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!