1

I have this code HTML:

<div class="wrap">
<div class="wp-checkbox" data-value="zf">content</div>
<div class="wp-checkbox" data-value="tdp">content</div>
</div>

I would like to replace the content of these divs, but each differently.

I tried to do it by code:

$pattern = '/=\"zf\">.*<\/div>/';
$pattern2 = '/=\"tdp\">.*<\/div>/';
$html = preg_replace( $pattern, '="zf">new content of div</div>', $html );
$html = preg_replace( $pattern2, '="tdp">new content of another div</div>', $html );

But there is a problem that this code - it replaced all my divs and I get this:

<div class="wrap">
<div class="wp-checkbox" data-value="zf">new content of div</div>
</div>

How can I change these divs one by one? How can I show in the pattern that I want to change only until the first closing </div> (not to last one)?

I would like to get this result:

<div class="wrap">
<div class="wp-checkbox" data-value="zf">new content of div</div>
<div class="wp-checkbox" data-value="tdp">new content of div</div>
</div>

Thank you in advance for help.

Nick
  • 138,499
  • 22
  • 57
  • 95
kibus90
  • 315
  • 2
  • 11
  • 1
    See https://stackoverflow.com/questions/3577641/how-do-you-parse-and-process-html-xml-in-php?rq=1 and use [`DOMDocument`](https://www.php.net/manual/en/class.domdocument.php) instead. – Nick Oct 04 '19 at 01:55
  • I am really glad that you tried to help me. But thank you, I am really bad in this! – kibus90 Oct 04 '19 at 01:57

1 Answers1

2

You really shouldn't try to use regex to parse HTML. Instead, use the DOMDocument class to process the HTML:

$doc = new DOMDocument();
$doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($doc);
$div = $xpath->query('//div[@data-value="zf"]')[0];
$div->nodeValue = "new content of div";
$div = $xpath->query('//div[@data-value="tdp"]')[0];
$div->nodeValue = "new content of another div";
echo $doc->saveHTML();

Output:

<div class="wrap">
<div class="wp-checkbox" data-value="zf">new content of div</div>
<div class="wp-checkbox" data-value="tdp">new content of another div</div>
</div>

Demo on 3v4l.org

If you must use regex, you just need to correct your patterns to make them non-greedy by adding ? after the .*:

$pattern = '/=\"zf\">.*?<\/div>/';
$pattern2 = '/=\"tdp\">.*?<\/div>/';
$html = preg_replace( $pattern, '="zf">new content of div</div>', $html );
$html = preg_replace( $pattern2, '="tdp">new content of another div</div>', $html );

Output:

<div class="wrap">
<div class="wp-checkbox" data-value="zf">new content of div</div>
<div class="wp-checkbox" data-value="tdp">new content of another div</div>
</div>

Demo on 3v4l.org

Nick
  • 138,499
  • 22
  • 57
  • 95
  • Thank you for your answer even I answerd you back not so nice. Unfortunately, the code is generated by the plugin, where I can change it only by function. So I do not know how to use it in function. – kibus90 Oct 04 '19 at 02:13
  • 1
    @kibus90 see my edit. I've included a fix for your regex. – Nick Oct 04 '19 at 02:17