DiDOM icon indicating copy to clipboard operation
DiDOM copied to clipboard

How to unwrap a parent node and elevate the children?

Open scott8035 opened this issue 1 year ago • 0 comments

Hi all, I hope it's OK if I ask a question here, I haven't found any other place to ask.

I have the following sample HTML:

<body>
    <div>
        <p>1</p>
        <p>2</p>
        <p>3</p>
    </div>
    <div>
        <p>4</p>
        <p>5</p>
        <p>6</p>
        <div>
            <p>7</p>
            <p>8</p>
            <p>9</p>
        </div>
    </div>
</body>

What I want to do is "unwrap" each <div> by relocating the <p> child nodes to be direct descendants of the div's parent, and deleting the now-empty <div> node. I tried doing it using the code below, but it only works on some nodes; on others, the $tag element has no parent and therefore you can't use insertSiblingBefore(...) without throwing an exception.

Here's some sample code to call the the desired function:

// Remove <div> tags with no attributes
$divTags = $doc->find( 'div' );
foreach ( $divTags as $divTag ) {
    removeElementKeepingChildren( $divTag );
}

...and here's the offending code itself:

function removeElementKeepingChildren( Element $tag ) : void {
    // I'd like to avoid needing this check...but without it, certain $tags cause the exception
    if ( ! $tag->parent() ) {
        return;
    }

    // "Backup" the children
    $children = $tag->children();

    // Remove the children from the node to be removed
    $tag->removeChildren();

    foreach ( $children as $child ) {
        $tag->insertSiblingBefore( $child );
    }

    $tag->remove();
}

There's got to be a better way to do this...suggestions?

scott8035 avatar Jul 10 '23 14:07 scott8035