【问题标题】:PHP Token replaces html entitiesPHP Token 替换 html 实体
【发布时间】:2011-09-15 19:18:21
【问题描述】:

如果在文本中找到某些单词/字符串,我想制作链接。我有一段来自 php.bet 的代码可以做到这一点,但它也从<a href="http://www.domain.com/index.php" title="Home">go to homepage</a> 中删除了标签的开头和结尾。你能帮忙解决这个问题吗?

这是一段代码:

<?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);

结果是:

你好,蠕虫!你有病!

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

“蠕虫”和“疾病”这两个词被转换成想要的链接,但其余的......

非常感谢!

【问题讨论】:

  • +1 表示研究工作经过深思熟虑的问题。

标签: php token strtok


【解决方案1】:

这对函数应该可以满足您的需求不会出现使用正则表达式解析 HTML 所带来的问题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());
}

注意: 如果 HTML 结构不正确(如您的示例),则无需担心;但是,输出将结构良好。

应得的信用: 完成大部分实际工作的递归 process() 函数直接来自 Lukáš Lalinský 对 How to replace text in HTML 的回答。 addLinks() 函数只是为满足您的问题而量身定制的用例。

【讨论】:

    【解决方案2】:

    不知道为什么你有这么大的结构,比如:

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

    会完成同样的事情。当然,使用正则表达式处理 HTML 是一个hazardous process。您应该使用带有一些 xpath 的 DOM 来更可靠地执行此操作。

    【讨论】:

    • 在这种情况下 $replaces[$1] 是什么?我问这个是因为它会引发错误。谢谢!
    • 您的代码似乎不起作用。有谁知道在这种情况下如何避免弄乱 html 实体?再次感谢!
    猜你喜欢
    • 2012-08-22
    • 2015-12-20
    • 2013-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-29
    • 2019-03-20
    相关资源
    最近更新 更多