dongshao8471 2011-09-15 19:18
浏览 108
已采纳

PHP Token替换了html实体

I want to make certain words/strings like links if found in the text. I have a piece of code from php.bet which does that, but it also removes the beginning and end of tags from <a href="http://www.domain.com/index.php" title="Home">go to homepage</a>. Can you help solve this?

Here's the piece of code:

<?php

$str_in =   '<p>Hi there worm! You have a disease!</p><a href="http://www.domain.com/index.php" title="Home">go to homepage</a>';
$replaces=      array(
                'worm' => 'http://www.domain.com/index.php/worm.html',
                'disease' => 'http://www.domain.com/index.php/disease.html'
                );

function addLinks($str_in, $replaces)
{
  $str_out = '';
  $tok = strtok($str_in, '<>');
  $must_replace = (substr($str_in, 0, 1) !== '<');
  while ($tok !== false) {
    if ($must_replace) {
      foreach ($replaces as $tag => $href) {
        if (preg_match('/\b' . $tag . '\b/i', $tok)) {
          $tok = preg_replace(
                                '/\b(' . $tag . ')\b/i',
                                '<a title="' . $tag . '" href="' . $href . '">\1</a>',
                                $tok,
                                1);
          unset($replaces[$tag]);
        }
      }
    } else {
      $tok = "<$tok>";
    }
    $str_out .= $tok;
    $tok = strtok('<>');
    $must_replace = !$must_replace;
  }
  return $str_out;
}

echo addLinks($str_in, $replaces);

The result is:

Hi there worm! You have a disease!

a href="http://www.domain.com/index.php" title="Home"/a

The "worm" and "disease" words are transformed into links like desired, but the rest...

Thanks a lot!

  • 写回答

2条回答 默认 最新

  • duanlaiyin2356 2011-09-15 22:16
    关注

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥20 求数据集和代码#有偿答复
  • ¥15 关于下拉菜单选项关联的问题
  • ¥15 如何修改pca中的feature函数
  • ¥20 java-OJ-健康体检
  • ¥15 rs485的上拉下拉,不会对a-b<-200mv有影响吗,就是接受时,对判断逻辑0有影响吗
  • ¥15 使用phpstudy在云服务器上搭建个人网站
  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况