PHP DOM find div class and output html inside div

Solution 1:

I would approach the issue by using xpath to select the target element, convert it to string and then use string manipulation methods to get to the desired output. It's a bit convoluted, but the code below should work for both html strings (the one in your question and the one in your comment); however, depending on the html structure, may have to be modified:

$html1 = <<<HTML
    <div class="test1">Test1<div class="test2"></div>Some Text</div>
    HTML;
$html2 = <<<HTML
    <div class="xx1">Some Extra Test<div class="test1">Test1<div class="test2"></div>Some Text</div></div>
    HTML;
$doc = new DOMDocument;
$doc->loadhtml($html2); //or html1
$xpath = new DOMXPath($doc); 

#get the right element using xpath
$node= $xpath->query('//div[@class="test1"]');

#convert the element to string
$target = $node[0]->ownerDocument->saveHTML($node[0]);

#now manipulate the string; it can be done in one step, but I broke it into two for clarity
$step1=explode('class="test1">',$target);
$step2 = explode('</div>',$step1[1]);
echo implode("", $step2);

Output in either case:

Test1<div class="test2">Some Text

Solution 2:

You can not use createTextNode because by definition this is only text and will not contain HTML tags.

The correct approach should be:

  1. You loop all the children of your $node. So in your case you have 3 children:
  • The text element Test1
  • The HTML tag <div class="test2"></div>
  • The text element Some Text
  1. For each of these children, you move them up 1 level: from being contained within your $node, to being attached to its parent. To do so, you clone the node, then you insertBefore to the $prent
  2. You remove the initial $node

In code:

foreach ($nodes as $node) {
    $prent = $node->parentNode;
    foreach ($node->childNodes as $childNode) {
        $prent->insertBefore($childNode->cloneNode(true), $node);
    }
    $prent->removeChild($node);
}

This will output, as requested

Test1<div class="test2"></div>Some Text