PHP If string contains, extract and replace

Just wondering how to detect if a string contains certain tags, extract particular parts of that tag and then replace.

Example:

$string = 'abc [video width="640" height="360" mp4="video.mp4"][/video] def';

1. How do I detect if this string contains  '*[video...[/video]*'  (... meaning anything in between, *  means anything on either side).
2. Then how to get the variables out of that string: so, width, height and mp4.
3. I can rewrite what i want for it to be (i'm sure you know where i'm going - to show the proper tags)
4. Then how to replace the new code with the old one.

Hope that makes sense.
Thanks in advance!

Cheers
Paul
dev09Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AJAY CHADHACommented:
Use this code, it does not uses regular expressions but it will work with your example given above. It will result in an array that contains all variables that you need as array elements.

<?php
$mystring = 'abc [video width="640" height="360" mp4="video.mp4"][/video] def';

$findme1 = '[video ';
$findme2 = '[/video]';

$pos1 = stripos($mystring, $findme1);
$pos2 = stripos($mystring, "]");
$pos3 = stripos($mystring, $findme1);

if ($pos1 === false) {
    echo "<p>The starting [video] tag was not found in the string '$mystring'</p>";
}

if ($pos3 === false) {
    echo "<p>The ending [/video] tag was not found in the string '$mystring'</p>";
}

$values = substr($mystring, $pos1+strlen($findme1), $pos2-($pos1+strlen($findme1)));
$variables = explode(" ",$values);
print_r($variables);
?>

Open in new window

Ray PaseurCommented:
From the look of the code above, the $findme2 variable is set in the script but unused.  My guess is that it should have been used on line 9.  But given the small amount of test data, the tests still passed without error.

This solution expands on it a little bit, returning an object that has property names matching the video tag attributes, and corresponding property values matching the tag values.  If you have actual HTML tags instead of BBCode you might use SimpleXMLElement or DomDocument.

You cannot parse HTML or BBCode with regular expressions because these markup languages are context-sensitive and regular expressions are incapable of working in that environment.  For a humorous take on the oft-asked question about regular expressions, please see this link.

I don't know how uniform your input might be, but if there is some chance of variability (for example if you're using human input), you might find this article useful.  It shows how to set up some simple tests for functions like these.
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_7830-A-Quick-Tour-of-Test-Driven-Development.html

<?php // demo/temp_dev09.php
/**
 * http://www.experts-exchange.com/questions/28695843/PHP-If-string-contains-extract-and-replace.html
 */
error_reporting(E_ALL);


// TEST DATA
$mystring = 'abc [video width="640" height="360" mp4="video.mp4"]Video Name Goes Here[/video] def';

// PROCESS AND SHOW RESULTS
$x = getAttributes($mystring);
if ($x->error) trigger_error($x->message, $x->error);
echo '<pre>';
var_dump($x);
echo PHP_EOL;
echo PHP_EOL . "The $x->mp4 has dimensions of $x->width x $x->height";


// A FUNCTION TO PARSE A BBCode STRING AND RETURN AN OBJECT
function getAttributes($mystring, $tag='video', $error=E_USER_ERROR)
{
    // OPTIMISTIC SETTINGS FOR RETURN
    $return          = new StdClass;
    $return->error   = FALSE;
    $return->message = NULL;
    $return->text    = NULL;

    // DELIMITING TAGS
    $findme1 = '['  . $tag . ' ';
    $findme2 = '[/' . $tag . ']';

    // CASE-INSENSITIVE TAG SEARCH
    $pos1 = stripos($mystring, $findme1);
    $pos2 = stripos($mystring, "]");
    $pos3 = stripos($mystring, $findme2);

    // ERROR IF TAGS CANNOT BE LOCATED
    if ($pos1 === false)
    {
        $return->error = $error;
        $return->message = "The [$tag] tag was not found in " . htmlentities($mystring);
        return $return;
    }
    if ($pos3 === false)
    {
        $return->error = $error;
        $return->message = "The [/$tag] tag was not found in " . htmlentities($mystring);
        return $return;
    }

    // LOCATE THE TEXT BETWEEN THE TAGS
    preg_match('#\](.*?)\[#', $mystring, $match);
    $return->text = $match[1];

    // ISOLATE THE ATTRIBUTES BY BREAKING ON WHITESPACE
    $values = substr($mystring, $pos1+strlen($findme1), $pos2-($pos1+strlen($findme1)));
    $values = preg_replace('#\s#',    ' ', $values);
    $values = preg_replace('#\s\s+#', ' ', $values);
    $attrs  = explode(" ",$values);

    // SET ATTRIBUTE PROPERTIES
    foreach ($attrs as $attr)
    {
        $arr = explode('=', $attr);
        $return->$arr[0] = trim($arr[1], '"');
    }

    return $return;
}

Open in new window

Ray PaseurCommented:
This expands on the code to show how we might replace the contents of some of the attributes or the text inside the tags.
Please see the demo here: http://iconoun.com/demo/temp_dev09.php
<?php // demo/temp_dev09.php
/**
 * http://www.experts-exchange.com/questions/28695843/PHP-If-string-contains-extract-and-replace.html
 */
error_reporting(E_ALL);


// TEST DATA
$mystring = 'abc [video width="640" height="360" mp4="video.mp4"]Video Name Goes Here[/video] def';

// PROCESS AND SHOW RESULTS
$x = getAttributes($mystring);
if ($x->error) trigger_error($x->message, $x->error);
echo '<pre>';
var_dump($x);
echo PHP_EOL;
echo PHP_EOL . "The $x->mp4 has dimensions of $x->width x $x->height";
echo PHP_EOL;


// REPLACE SOME ELEMENTS IN THE OBJECT AND RECREATE THE VIDEO TAG
$x->height = 270;
$x->width  = 480;
$x->text   = 'New Video Name';
$new
= '[video '
. 'width="'  . $x->width  . '"'
. ' '
. 'height="' . $x->height . '"'
. ' '
. 'mp4="video.mp4"]'
. $x->text
. '[/video]'
;
echo PHP_EOL . htmlentities($new);
echo PHP_EOL;



// A FUNCTION TO PARSE A BBCode STRING AND RETURN AN OBJECT
function getAttributes($mystring, $tag='video', $error=E_USER_ERROR)
{
    // OPTIMISTIC SETTINGS FOR RETURN
    $return          = new StdClass;
    $return->error   = FALSE;
    $return->message = NULL;
    $return->text    = NULL;

    // DELIMITING TAGS
    $findme1 = '['  . $tag . ' ';
    $findme2 = '[/' . $tag . ']';

    // CASE-INSENSITIVE TAG SEARCH
    $pos1 = stripos($mystring, $findme1);
    $pos2 = stripos($mystring, "]");
    $pos3 = stripos($mystring, $findme2);

    // ERROR IF TAGS CANNOT BE LOCATED
    if ($pos1 === false)
    {
        $return->error = $error;
        $return->message = "The [$tag] tag was not found in " . htmlentities($mystring);
        return $return;
    }
    if ($pos3 === false)
    {
        $return->error = $error;
        $return->message = "The [/$tag] tag was not found in " . htmlentities($mystring);
        return $return;
    }

    // LOCATE THE TEXT BETWEEN THE TAGS
    preg_match('#\](.*?)\[#', $mystring, $match);
    $return->text = $match[1];

    // ISOLATE THE ATTRIBUTES BY BREAKING ON WHITESPACE
    $values = substr($mystring, $pos1+strlen($findme1), $pos2-($pos1+strlen($findme1)));
    $values = preg_replace('#\s#',    ' ', $values);
    $values = preg_replace('#\s\s+#', ' ', $values);
    $attrs  = explode(" ",$values);

    // SET ATTRIBUTE PROPERTIES
    foreach ($attrs as $attr)
    {
        $arr = explode('=', $attr);
        $return->$arr[0] = trim($arr[1], '"');
    }

    return $return;
}

Open in new window

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
dev09Author Commented:
Thank you, exactly what i was after :)
Ray PaseurCommented:
Glad to help.  Thanks for the points and thanks for using E-E, ~Ray
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.