【问题标题】:Search and replace a string of HTML using the PHP DOM Parser使用 PHP DOM Parser 搜索和替换 HTML 字符串
【发布时间】:2015-11-11 10:46:25
【问题描述】:

如何使用原生 PHP DOM Parser 在网页中搜索和替换特定字符串(文本 + html 标签)?

例如,搜索

<p> <a href="google.com"> Check this site </a> </p>

该字符串位于 html 树内的某个位置。

我想找到它并用另一个字符串替换它。例如,

<span class="highligher"><p> <a href="google.com"> Check this site </a> </p></span>

请记住,&lt;p&gt;&lt;a&gt; 节点没有 ID。可能有许多相同的节点,包含不同的文本。

我尝试了 str_replace,但由于复杂的 html 标记而失败,所以我现在求助于 HTML Parsers。

编辑:

要查找和替换的字符串可能包含各种 HTML 标记,如 div、标题、粗体等。因此,我正在寻找一种可以根据内容构建正则表达式或 DOM xpath 查询的解决方案正在搜索的字符串。

谢谢!

【问题讨论】:

  • 使用 JavaScript 并向&lt;p&gt; 添加 id / class 不是更好吗?
  • 你试过了吗:simplehtmldom.sourceforge.net
  • 我无法控制正在解析的 HTML 文档,因此我无法添加任何属性。我读过 Simple HTML DOM,但是人们说它不如原生 PHP DOM Parser
  • getElementsByTagName(..),然后用getAttribute(..)过滤?
  • 这可以返回 20+ 个不同的

    元素,你如何识别正确的并替换它?

标签: php html parsing dom domparser


【解决方案1】:

这是你想要的吗:

<?php
// load
$doc = new DOMDocument();
$doc->loadHTMLFile("filename.html");

// search p elements
$p_elements = $doc->getElementsByTagName('p');

// parse this elements, if available
if (!is_null($p_elements)) 
{
    foreach ($p_elements as $p_element) 
    {
        // get p element nodes
        $nodes = $p_element->childNodes;

        // check for "a" nodes in these nodes
        foreach ($nodes as $node) {

            // found an a node - check must be defined better!
            if(strtolower($node->nodeName) === 'a')
            {
                // create the new span element
                $span_element = $doc->createElement('span');
                $span_element->setAttribute('class', 'highlighter');

                // replace the "p" element with the span
                $p_element->parentNode->replaceChild($span_element, $p_element);
                // append the "p" element to the span
                $span_element->appendChild($p_element);
            }
        }
    }
}

// output
echo '<pre>';
echo htmlentities($doc->saveHTML());
echo '</pre>';

此 HTML 是转换的基础:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><title>Your Title Here</title></head><body bgcolor="FFFFFF">
<hr><a href="http://somegreatsite.com">Link Name</a>
is a link to another nifty site
<h1>This is a Header</h1>
<h2>This is a Medium Header</h2>
<p> <a href="amazon.com"> Check this site </a> </p>
Send me mail at <a href="mailto:support@yourcompany.com">
support@yourcompany.com</a>.
<p> This is a new paragraph!
</p><hr><p> <a href="google.com"> Check this site </a> </p>
</body></html>

输出看起来像这样,它包装了你提到的元素:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><head><title>Your Title Here</title></head><body bgcolor="FFFFFF">
<hr><a href="http://somegreatsite.com">Link Name</a>
is a link to another nifty site
<h1>This is a Header</h1>
<h2>This is a Medium Header</h2>
<span class="highlighter"><p> <a href="amazon.com"> Check this site </a> </p></span>
Send me mail at <a href="mailto:support@yourcompany.com">
support@yourcompany.com</a>.
<p> This is a new paragraph!
</p><hr><span class="highlighter"><p> <a href="google.com"> Check this site </a> </p></span>
</body></html>

【讨论】:

【解决方案2】:

您可以在 preg_replace 中使用正则表达式。

 preg_replace("/<\s*p[^>]*>(.*?)<\s*\/\s*p>/", '<span class="highligher"><p>$1</p></span>', '<p><a href="google.com"> Check this site</a></p>');

preg_replace的第三个参数可以用来限制替换次数

http://php.net/manual/en/function.preg-replace.php http://www.pagecolumn.com/tool/all_about_html_tags.htm - 有关 HTML 正则表达式的更多示例

您需要编辑正则表达式以仅捕获带有 google href 的 p 标签

编辑

preg_replace("/<\s*\w.*?><a href\s*=\s*\"?\s*(.*)(google.com)\s*\">(.*?)<\/a>\s*<\/\s*\w.*?>/", '<span class="highligher"><p><a href="$1$2">$3</a></p></span>', $string);

【讨论】:

  • 谢谢,看来我得使用正则表达式了。但是,被搜索和替换的字符串可能会有所不同。可能是 。所以,我正在寻找一个更通用的解决方案。可能是处理所有情况的动态表达式?
  • 另外,这是否意味着无法使用 DOM 解析器来完成此任务?必须可以加载一些 html 字符串并在已经解析的文件中搜索它?
  • 我不熟悉 DOM 解析器,但我认为如果没有 class 或 id 会很困难
  • 如果你投反对票,你至少可以发表评论,没有解释的投反对票是没有意义的,不是吗
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 1970-01-01
  • 2012-07-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多