You need to divide the problem to solve it. You have got two main parts here:
- Division of the HTML into Top and Bottom parts.
- Doing the DOMDocument manipulation on (both?) HTML strings.
Let's just do that:
The first part is actually quite simple. Let's say all line separators are "
"
and the empty line is actually an empty line "
"
. Then this is a simple string operation:
list($top, $bottom) = explode("
", $html, 2);
This solves the first part already. Top html is in $top
and the rest we actually do not need to care much about is stored into $bottom
.
Let's go on with the second part.
With simple DOMDocument
operations you can now for example get a list of all images:
$topDoc = new DOMDocument();
$topDoc->loadHTML($top);
$topImages = $topDoc->getElementsByTagname('img');
The only thing you need to do now is to remove each image from it's parent:
$image->parentNode->removeChild($image);
And then insert it before the <h2>
element:
$anchor = $topDoc->getElementsByTagName('h2')->item(0);
$anchor->parentNode->insertBefore($image, $anchor);
And you're fine. Full code example:
$html = <<<HTML
<h2>Title here</h2>
<img src="001">
<p>Some content here. (for testing purposes)</p>
<img src="002">
<h2>Second Title here (for testing purposes)</h2>
<p>Some content here.</p>
<img src="003">
HTML;
list($top, $bottom) = explode("
", $html, 2);
$topDoc = new DOMDocument();
$topDoc->loadHTML($top);
$topImages = $topDoc->getElementsByTagname('img');
$anchor = $topDoc->getElementsByTagName('h2')->item(0);
foreach($topImages as $image) {
$image->parentNode->removeChild($image);
$anchor->parentNode->insertBefore($image, $anchor);
}
foreach($topDoc->getElementsByTagName('body')->item(0)->childNodes as $child)
echo $topDoc->saveHTML($child);
echo $bottom;
Output:
<img src="001"><img src="002"><h2>Title here</h2>
<p>Some content here. (for testing purposes)</p>
<h2>Second Title here (for testing purposes)</h2>
<p>Some content here.</p>
<img src="003">