【问题标题】:Replace the content of a tag with a certain class用某个类替换标签的内容
【发布时间】:2010-06-05 06:02:18
【问题描述】:

我正在寻找合适的替换代码,允许我替换任何具有特定类的 HTML 标记内的内容,例如

$class = "blah";
$content = "new content";
$html = '<div class="blah">hello world</div>';

// code to replace, $html now looks like:
// <div class="blah">new content</div>

请记住:

  1. 不一定是 div,也可以是&lt;h2 class="blah"&gt;
  2. 该类可以有多个类,但仍需要替换,例如&lt;div class="foo blah green"&gt;hello world&lt;/div&gt;

我认为正则表达式应该能够做到这一点,否则我愿意接受其他建议,例如使用 DOM 类(尽管我宁愿尽可能避免这样做,因为它必须与 PHP4 兼容)。

【问题讨论】:

  • 如果你能负担得起使用 JavaScript,尤其是 jQuery,这将非常容易。
  • php4 中似乎存在一些 html 解析器:google.com/…
  • 我会使用之前发布的正则表达式,但使用 simple_html_dom 也是一种可能的解决方案。

标签: php html


【解决方案1】:

Do not use regular expressions to parse HTML。你可以使用内置的DOMDocument,或者类似simple_html_dom

require_once("simple_html_dom.php");

$class = "blah";
$content = "new content";
$html = '<div class="blah">hello world</div>';

$doc = new simple_html_dom();
$doc->load($html);

foreach ( $doc->find("." . $class) as $node ) {
    $node->innertext = $content;
}

抱歉,我没有看到 PHP4 的要求。这是使用上述标准 DOMDocument 的解决方案。

function DOM_getElementByClassName($referenceNode, $className, $index=false) {
    $className = strtolower($className);
    $response  = array();

    foreach ( $referenceNode->getElementsByTagName("*") as $node ) {
        $nodeClass = strtolower($node->getAttribute("class"));

        if (
                $nodeClass == $className || 
                preg_match("/\b" . $className . "\b/", $nodeClass)
            ) {
            $response[] = $node;
        }
    }

    if ( $index !== false ) {
        return isset($response[$index]) ? $response[$index] : false;
    }

    return $response;
}

$doc = new DOMDocument();
$doc->loadHTML($html);

foreach ( DOM_getElementByClassName($doc, $class) as $node ) {
    $node->nodeValue = $content;
}

echo $doc->saveHTML();

【讨论】:

  • 这更像是一部现代史诗而不是咆哮;)
【解决方案2】:

如果您确定 $html 是有效的 HTML 代码,您可以使用 HTML 解析器,如果它是有效的 XML 代码,甚至可以使用 XML 解析器。

但是 Regex 中快速而肮脏的方式是这样的:

$html = preg_replace('/(<[^>]+ class="[^>]*' . $class . '[^"]*"[^>]*>)[^<]+(<\/[^>]+>)/siU', '$1' . $content . '$2', $html);

没有过多地测试它,但它应该可以工作。告诉我你是否发现没有的情况。 ;)

编辑:添加“和脏”... ;)

编辑 2:RegEx 的新版本:

<?php

$class = "blah";
$content = "new content";
$html = '<div class="blah test"><h1><span>hello</span> world</h1></div><div class="other">other content</div><h2 class="blah">remove this</h2>';

$html = preg_replace('/<([\w]+)(\s[^>]*class="[^"]*' . $class . '[^"]*"[^>]*>).+(<\/\\1>)/siU', '<$1$2' . $content . '$3', $html);

echo $html;

?>

剩下的最后一个问题是,如果有一个类名称中只有“blah”,例如“tooMuchBlahNow”。让我们看看如何解决这个问题。顺便说一句:很明显我喜欢玩 RegEx 吗? ;)

【讨论】:

  • @b-i-d 这似乎适用于字母数字字符,但如果标签内有 HTML...?
  • 是的,这不在问题的规范中。对于标签中的 HTML,RegEx 必须稍微复杂一些。让我想想……
  • 更新了我的答案。只剩下一个“问题”了。
【解决方案3】:

没有必要使用 DOM 类,正如 Khnle 所说,这可能使用 jQuery 最快完成,或者您可以使用 preg_replace() 函数。给我一些时间,我可以为你写一个快速的正则表达式。

但我建议使用 jQuery 之类的东西,这样您可以快速将页面提供给用户,并让他们的计算机代替您的服务器进行处理。

【讨论】:

  • 如果用户禁用了 JavaScript 怎么办?如果您可以在服务器上做某事,那么在 JS 中做某事绝不是一个好主意,因为服务器比客户端可能快得多。
  • Javascript 和 jQuery 并不是万能的解决方案。
  • + 重点是我不能使用 jQuery 它必须是服务器端!
猜你喜欢
  • 2022-12-08
  • 1970-01-01
  • 2021-10-10
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 2015-10-26
  • 2011-11-03
  • 2016-01-11
相关资源
最近更新 更多