【问题标题】:Simple HTML DOM - replace all occurrences of a certain word - without affecting attributes简单的 HTML DOM - 替换所有出现的某个单词 - 不影响属性
【发布时间】:2015-09-25 22:01:39
【问题描述】:

我想知道:如何更改 HTML 中某个单词的所有出现,但仅限于标签之外?

示例: 假设我想用<a href="#">myWordToReplace</a>替换所有出现的myWordToReplace

所以这个html

<p data-something="myWordToReplace"> myWordToReplace andSomeOtherText</p>

应该让步

<p data-something="myWordToReplace"> <a href="#">myWordToReplace</a> andSomeOtherText</p>

我试图用正则表达式来实现这一点,但这也是一团糟——我认为也许 DOM 解析器可以解决问题? 任何帮助表示赞赏?

编辑: 如果您的所有文本都包含在某些标签中,@Muhammet 的答案将起到作用 - 但如果您的部分文本没有标签,那么该文本当然不会被替换。我现在也在努力实现这一目标。

示例:如果我想将myWord 更改为someOtherWord

Nam myWord pharetra <strong>auctor myWord</strong>

应该让步

Nam someOtherWord pharetra <strong>auctor someOtherWord </strong>

但现在它只改变了第二个词 - 强标签内的那个。

【问题讨论】:

  • 为什么要投反对票? :)
  • 这不是一件小事。我建议不要在这里使用纯正则表达式方法,因为那将是一个巨大的努力。为此,您需要一个状态机,并且是一个非常复杂的状态机。...改为查看 DOM 解析器,遍历元素并 然后 使用正则表达式替换每个元素内容中的模式.
  • 这正是我的想法 - 但不知道如何接近,所以我问了这个问题。你说要看看 DOM 解析器吗?这是我在这里谈论的 DOM 解析器...?
  • 不,纯正则表达式方法将是一个字符串解析器,因为您输入一个字符串,替换其中的单词并输出一个字符串。 DOM 解析器是别的东西,是一个真正了解 HTML 标记结构的软件组件。它将您的输入解析为您可以迭代的 DOM 树(元素树):这样做的好处是您拥有合格的对象,您可以在其中轻松区分属性和内容。像这样的东西:simplehtmldom.sourceforge.net
  • 您可以发布您需要解析的 HTML 或更大的示例吗?

标签: php regex simple-html-dom


【解决方案1】:

你可以这样做

$html = file_get_html($file_url);
$content = $html->find('text');

foreach($content as $line) {
    if(strpos($line->innertext, 'myWordToReplace') !== false) {
        $line->innertext = str_replace('myWordToReplace','<a href="#">myWordToReplace</a>', $line->innertext);
    }
}

【讨论】:

  • 是的,这正是我在上面的 cmets 中建议的。
  • 所以你要逐行进行?你为什么不使用“find”方法来真正寻找你需要的东西呢?
  • @SpongePablo 因为 OP 可能想要替换所有出现而不仅仅是 p
  • 如果您通过 strpos 找到,可能需要将 $line-&gt;innertext = '&lt;a href="#"&gt;myWordToReplace&lt;/a&gt;'; 更改为 str_replace
  • @Muhammet 你说得对,但是 str_replace 应该为 $line->innertext 赋值 :) 谢谢你的时间
【解决方案2】:

这对我来说非常有用。我不知道为什么它不带“data-something”,它似乎不喜欢两个词之间的破折号。但它确实有效,我希望它对你有用。

我正在使用Simple HTML DOM Library

$my_html = '<p data="myWordToReplace"> myWordToReplace </p>';
$html = str_get_html($my_html);

foreach($html->find('p') as $p) {
    if (!empty($p->data) && ($p->data == 'myWordToReplace')) {
        $p->innertext = '<a href="#">'. $p->innertext .'</a>';
    }
}

echo $html; 

【讨论】:

  • 假设我想替换所有出现的地方 为什么你认为它只是p?为什么你认为只有p data == 'myWordToReplace'?为什么你认为文本只包含myWordToReplace
  • 因为是@trainoasis曝光的例子,他正在寻找它。将它保存在一个变量中并输入任何你想要的内容,在你想要搜索的元素上放置一个 id,或者更好地解释这个问题。
  • 谢谢海绵,也很有帮助
【解决方案3】:

这是另一个基于 DOM 的解决方案,用于将部分文本节点包装到 &lt;a&gt; 标记中(使用 search 作为示例):

$html = "<html><body>\n<!-- This is a comment for search //-->\n<span class=\"search\">New search performed</span></body></html>";
$key = "search";
$dom = new DOMDocument();
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$tt = $xpath->query('//text()');

foreach ($xpath->query('//text()') as $textNode) {
    $fragment = $dom->createDocumentFragment();
    $text = $textNode->nodeValue;

    while (($pos = stripos($text, $key)) !== false) {
      $fragment->appendChild(new DOMText(substr($text, 0, $pos)));
      $word = substr($text, $pos, strlen($key));

      $lnk = $dom->createElement('a');
      $lnk->appendChild(new DOMText($word));
      $lnk->setAttribute('href', '#');
      $fragment->appendChild($lnk);

      $text = substr($text, $pos + strlen($key));
    }
    if (!empty($text))
      $fragment->appendChild(new DOMText($text));
    $textNode->parentNode->replaceChild($fragment, $textNode);
}
echo $dom->saveHTML();

这是IDEONE demo

【讨论】:

    猜你喜欢
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    相关资源
    最近更新 更多