需要帮助preg_replace使用参数解释{variables}

时间:2010-10-05 21:36:09

标签: php regex

我想替换

  

{youtube}Video_ID_Here{/youtube}

使用youtube视频的嵌入代码。

到目前为止我已经

  

preg_replace('/{youtube}(.*){\/youtube}/iU',...)

它运作得很好。

但是现在我想能够解释高度,宽度等参数。所以我可以有一个正则表达式,无论是否有参数?它应该能够在下面解释所有这些......

  

{youtube height="200px" width="150px" color1="#eee" color2="rgba(0,0,0,0.5)"}Video_ID_Here{/youtube}

     

{youtube height="200px"}Video_ID_Here{/youtube}

     

{youtube}Video_ID_Here{/youtube}

     

{youtube width="150px" showborder="1"}Video_ID_Here{/youtube}

4 个答案:

答案 0 :(得分:1)

您可能希望使用preg_replace_callback,否则替换会变得非常复杂。

preg_replace_callback('/{youtube(.*)}(.*){\/youtube}/iU',...)

在回调中,检查$match[1]是否有类似/(width|showborder|height|color1)="([^"]+)"/i模式的内容。 preg_replace_callback中的一个简单的preg_match_all可以使所有部分保持良好状态。整洁,最重要的是清晰易懂。

答案 1 :(得分:1)

我会这样做:

preg_match_all("/{youtube(.*?)}(.*?){\/youtube}/is", $content, $matches);

for($i=0;$i<count($matches[0]);$i++)
{
  $params = $matches[1][$i];
  $youtubeurl = $matches[2][$i];

  $paramsout = array();

  if(preg_match("/height\s*=\s*('|\")([0-9]+px)('|\")/i", $params, $match)
  {
    $paramsout[] = "height=\"{$match[2]}\"";
  }

  //process others

  //setup new code
  $tagcode = "<object ..." . implode(" ", $paramsout) ."... >"; //I don't know what the code is to display a youtube video

  //replace original tag
  $content = str_replace($matches[0][$i], $tagcode, $content);
}

您可以在“{youtube”之后和“之前”查找params,但是您可以自行解决XSS问题。最好的方法是查找特定数量的参数并验证它们。不要允许像&lt;和&gt;要在你的标签内传递,因为有人可以把do_something_nasty();什么的。

答案 2 :(得分:1)

试试这个:

function createEmbed($videoID, $params)
{
    // $videoID contains the videoID between {youtube}...{/youtube}
    // $params is an array of key value pairs such as height => 200px

    return 'HTML...'; // embed code
}

if (preg_match_all('/\{youtube(.*?)\}(.+?)\{\/youtube\}/', $string, $matches)) {
    foreach ($matches[0] as $index => $youtubeTag) {
        $params = array();

        // break out the attributes
        if (preg_match_all('/\s([a-z0-9]+)="([^\s]+?)"/', $matches[1][$index], $rawParams)) {
            for ($x = 0; $x < count($rawParams[0]); $x++) {
                $params[$rawParams[1][$x]] = $rawParams[2][$x];
            }
        }

        // replace {youtube}...{/youtube} with embed code
        $string = str_replace($youtubeTag, createEmbed($matches[2][$index], $params), $string);
    }
}

此代码首先匹配{youtube} ... {/ youtube}标记,然后将属性拆分为数组,将它们(作为键/值对)和视频ID传递给函数。只需填写函数定义,使其验证您想要支持的参数,并构建相应的HTML代码。

答案 3 :(得分:0)

我根本不使用正则表达式,因为它们在解析标记方面非常糟糕。

由于您的输入格式首先非常接近HTML / XML,我依赖于

$tests = array(
    '{youtube height="200px" width="150px" color1="#eee" color2="rgba(0,0,0,0.5)"}Video_ID_Here{/youtube}'
  , '{youtube height="200px"}Video_ID_Here{/youtube}'
  , '{youtube}Video_ID_Here{/youtube}'
  , '{youtube width="150px" showborder="1"}Video_ID_Here{/youtube}'
  , '{YOUTUBE width="150px" showborder="1"}Video_ID_Here{/youtube}' // deliberately invalid
);

echo '<pre>';
foreach ( $tests as $test )
{
  try {
    $youtube = SimpleXMLYoutubeElement::fromUserInput( $test );

    print_r( $youtube );
  }
  catch ( Exception $e )
  {
    echo $e->getMessage() . PHP_EOL;
  }
}
echo '</pre>';

class SimpleXMLYoutubeElement extends SimpleXMLElement
{
  public static function fromUserInput( $code )
  {
    $xml = @simplexml_load_string(
        str_replace( array( '{', '}' ), array( '<', '>' ), strip_tags( $code ) ), __CLASS__
    );
    if ( !$xml || 'youtube' != $xml->getName() )
    {
      throw new Exception( 'Invalid youtube element' );
    }
    return $xml;
  }

  public function toEmbedCode()
  {
    // write code to convert this to proper embode code
  }
}