特定のhtmlタグと、その中の特定の属性のみ許可する正規表現を試行錯誤しています。

タグに関しては、

【方法1】

preg_replace('/(?!<\/?(p|a|font)(>|\s[^>]*>))<("[^"]*"|\'[^\']*\'|[^\'">])*>/', '', $text);

【方法2】

htmlescape($text, array('p', '/p', 'a', '/a', 'font', '/font'));

function htmlescape($sValue, $arrAllowTag = array()) {
  $sValue = htmlspecialchars($sValue, ENT_QUOTES);
  if (count($arrAllowTag) == 0) return $sValue;
  foreach($arrAllowTag as $sTag) {
    if (strpos($sTag, '/') === false) {
      $sValue = preg_replace_callback("/&lt;\/?". $sTag . "( .*?&gt;|\/?&gt;)/i", "htmlescape_unhtmlescape", $sValue);
    }
  }
  return $sValue;
}

function htmlescape_unhtmlescape($sValue){
  $sString = $sValue[0];
  $sString = str_replace("&lt;", "<", $sString);
  $sString = str_replace("&gt;", ">", $sString);
  $sString = str_replace("&quot;", "\"", $sString);
  $sString = str_replace("&#039;", "'", $sString);
  return $sString;
}

といった方法で可能なのですが、許可されたhtmlタグの中の、更に特定の属性のみ許可する場合の正規表現がうまくいきません。
例えば

  • <font>タグであれば、「color」属性のみ許可したい
  • <p>タグであれば、「align」属性で、かつ値は「right」「left」「center」のみ許可したい

といった場合です。また、属性が現れる順番は保証されていません。

preg_replace_callbackなどを利用して効率の良い書き方があれば、ご教授いただければ幸いです。

タグを除くとき、削除するのかエスケープするのかは、どちらでも問題ありません。