如何替换具有特定类(第n次出现)的标签的“innerHTML”(使用正则表达式)?

时间:2014-08-09 15:24:16

标签: php regex string preg-replace

我想要实现的目标

我试图在file_get_contents()字符串中替换任何(在我的情况下)html标记的'innerHTML',该标记具有分配给它的特定类,而不改变其他内容。稍后我将创建一个文件(file_put_contents())。

我特意试图避免使用DOMDocuments,Xpath,simple_html_dom,因为这些会改变文档的格式。

类标记只是标记源中元素的一种方法,就像灯箱一样。用类标记似乎最优雅,但是可能以不同的方式标记元素使解决方案更容易?我怀疑它会有所作为。


代码也应符合以下情况:

  • class="..."包含其他类
  • 当innerHTML包含其他标签时

没有必要,但如果它符合以下情况,那将是惊人的:

  • class="..."
  • 中有php
  • php in between class="...">

我尝试了什么

(按时间顺序排列)

1 - 尝试使用我在其他答案和php.net中找到的以下功能:

function preg_replace_nth($pattern, $replacement, $subject, $nth=1) {
    return preg_replace_callback($pattern,
        function($found) use (&$pattern, &$replacement, &$nth) {
                $nth--;
                if ($nth==0) return preg_replace($pattern, $replacement, reset($found) );
                return reset($found);
        },$subject ,$nth  );
}

我不是一名正则表达式专家,结合php函数,对我而言,这非常困难,这就是我寻求帮助的原因。 (我已经工作了一个小时或8个小时。)

我尝试用以下的正则表达式模式(做了很多小改动:

  1  '#(?<=class=\"classToMatch\".*?>).*?(?=</)#';

对于最后30次改动,它一直在返回:

  

警告:preg_replace_callback():编译失败:lookbehind断言在偏移量xx处不是固定长度

我意识到的事情可能是正则表达式的问题:

  • 我没有足够的能力寻找特定的结束标记(例如</h2>),因为标记可以是任何元素。如果真的必要,也许我应该将我的请求限制在<p>, <h(x)> and <a>元素。
  • 我认为处理嵌套元素可能会有问题。

2 - 使用simple_html_dom和DOMDocument

首先,我很高兴看到它有效,但是当我打开编辑过的文档的源代码时,我感到非常恐惧,因为它删除了很多格式。

这是工作代码,对于使用少量php和javascript的html文档的人来说应该没问题。

$nth = 0;              // nth occurrence (starts with 0)
$replaceWith = '';     // replacement string

$dom = new DOMDocument();
@$dom->loadHTMLFile("source.php");

// find all elements with specific class
$finder = new DomXPath($dom);
$nodes = $finder->query("//*[contains(concat(' ', normalize-space(@class), ' '), ' classname ')]");

if (!is_int($nodes->length) || $nodes->length < 1) die('No element found');

$nodeToChange = $nodes->item($nth);

$nodeToChange ->removeChild($nodeToChange ->firstChild);
$fragment = $dom->createDocumentFragment();
$fragment->appendXML($replaceWith);
$lentNodeToEdit->appendChild($fragment);

$dom->saveHTMLFile("test.php");

3 - 有strpos等的东西,我正在考虑回归这些功能。

1 个答案:

答案 0 :(得分:1)

以下正则表达式可能对您有所帮助:

<(?<tag>\w*)\sclass=\"lent-editable\">(?<text>.*)</\k<tag>>

您需要找到组名“text”,这是您要替换的内部HTML。