0

So I have a working preg_match pattern for finding the value of an HTML attribute in a string, and I need to do the same thing with preg_replace - not find and return the value, but replace it with a new one.

But it doesn't work if I just use the preg_match pattern... I'm stuck.

Here's the code:

    $string = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" 
width="437" height="288" id="viddler">
<param name="movie" value="http://www.viddler.com/player/1234567890/" />
<param name="allowScriptAccess" value="always" />
<param name="allowFullScreen" value="true" />
<param name="flashvars" value="fake=1"/>
<embed src="http://www.viddler.com/player/1234567890/" 
width="437" height="288" type="application/x-shockwave-flash" 
allowScriptAccess="always" allowFullScreen="true" flashvars="fake=1" 
name="viddler" ></embed></object>';

preg_match("|<*[^>]*width=\"([^>]+)\"[^>]*>|Ui", $string, $results);

echo 'Width: '.$results[1];

This works and will return 437. If I use the same pattern in a preg_replace() function though, it will strip out the entire <object> tag. I need to replace that 437 with anything else, say 200. And while we're at it, I need to replace the height value as well. Finally, this should work for any embed code or iframe, so it should just look for width=" or height=", respectively... just like the preg_match example above.

Any help is much appreciated.

EDIT: Tim's solution below

I got Tim's pattern to work with a small modification:

$interm = preg_replace('|(<*[^>]*width=)"[^>]+"([^>]*>)|Ui', '\1"200"\2', $string);
$result = preg_replace('|(<*[^>]*height=)"[^>]+"([^>]*>)|Ui', '\1"300"\2', $interm);

Without this change, the first function replaces the width, but it takes out every attribute after that in the tag.

Thanks to Tim for the solution!

bobsoap
  • 4,844
  • 7
  • 30
  • 43
  • You are looking to parse HTML with a proper HTML parser. – Pekka Mar 16 '11 at 21:29
  • http://stackoverflow.com/questions/3577641/best-methods-to-parse-html/3577662#3577662 – Pekka Mar 16 '11 at 21:29
  • @Pekka, thanks for the link, honestly it seems like too much of an overhead for such a relatively small task. I get what you're saying (and that thread is very informative), but I think this particular case is better served with a single line of preg_replace. – bobsoap Mar 16 '11 at 21:52

1 Answers1

5

You need to capture the match around the string to be replaced:

Since you want to replace height and width with different values, you need two regexes, applied sequentially:

$interm = preg_replace('/(<*[^>]*width=)"[^>]+"([^>]*>)/', '\1"200"\2', $subject);
$result = preg_replace('/(<*[^>]*height=)"[^>]+"([^>]*>)/', '\1"300"\2', $interm);
Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • Nice! Thanks a lot - how would I set different values for width and height with the above? – bobsoap Mar 16 '11 at 21:21
  • 1
    You need two regexes for that. I first thought you could do it with a single regex with callback, but since each tag contains both values, and the regex matches the entire tag, you need to do it sequentially. – Tim Pietzcker Mar 17 '11 at 07:27