33

I have a DOM object with loaded HTML markup. I'm trying to replace all embed tags that look like this:

<embed allowfullscreen="true" height="200" src="path/to/video/1.flv" width="320"></embed>

With a tag like this:

<a 
href="path/to/video/1.flv" 
style="display:block;width:320px;height:200px;" 
id="player">
</a>

I'm having troubles figuring this out and I don't want to use regular expression for this. Could you help me out?

EDIT:

This is what I have so far:

         // DOM initialized above, not important
            foreach ($dom->getElementsByTagName('embed') as $e) {
                $path = $e->getAttribute('src');
          $width = $e->getAttribute('width') . 'px';
          $height = $e->getAttribute('height') . 'px';
          $a = $dom->createElement('a', '');
          $a->setAttribute('href', $path);
          $a->setAttribute('style', "display:block;width:$width;height:$height;");
          $a->setAttribute('id', 'player');
          $dom->replaceChild($e, $a); // this line doesn't work
      }
3
  • Don't have time to write up an answer right now, but check out php.net/manual/en/class.domdocument.php Commented Jul 7, 2010 at 13:09
  • I have looked but I cannot figure it out. I have updated my answer with the code I already have but the last line which is supposed to switch elements does not work. Commented Jul 7, 2010 at 13:20
  • See similar question: stackoverflow.com/q/17864378 Commented Jul 25, 2013 at 22:48

1 Answer 1

53

It's easy to find elements from a DOM using getElementsByTagName. Indeed you wouldn't want to go near regular expressions for this.

If the DOM you are talking about is a PHP DOMDocument, you'd do something like:

$embeds= $document->getElementsByTagName('embed');
foreach ($embeds as $embed) {
    $src= $embed->getAttribute('src');
    $width= $embed->getAttribute('width');
    $height= $embed->getAttribute('height');

    $link= $document->createElement('a');
    $link->setAttribute('class', 'player');
    $link->setAttribute('href', $src);
    $link->setAttribute('style', "display: block; width: {$width}px; height: {$height}px;");

    $embed->parentNode->replaceChild($link, $embed);
}

Edit re edit:

$dom->replaceChild($e, $a); // this line doesn't work

Yeah, replaceChild takes the new element to replace-with as the first argument and the child to-be-replaced as the second. This is not the way round you might expect, but it is consistent with all the other DOM methods. Also it's a method of the parent node of the child to be replaced.

(I used class not id, as you can't have multiple elements on the same page all called id="player".)

Sign up to request clarification or add additional context in comments.

4 Comments

"Also it's a method of the parent node of the child to be replaced." - this ended my 40 minutes of debugging session. Thanks!
If you try to replace DOM elements within a foreach loop then elements will be skipped because you are altering a "live" object. Iterating backwards, converting the node list to an array, or using a while loop based on the node list length are a few ways to solve that issue.
You saved my day!! I was looking for this in my dreams all the night.
Since PHP 8 this is possible: $embed->replaceWith($link);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.