1

許可されたスタイルのホワイト リストを用意しました。ホワイト リストからすべてのスタイルを HTML 文字列から削除したいと考えています。

$allowed_styles = array('font-size','color','font-family','text-align','margin-left');
$html = 'xyz html';
$html_string = '<bdoy>' . $html . '<body>';
$dom = new DOMDocument();
$dom->loadHTML($html_string);
$elements = $dom->getElementsByTagName('body');
foreach($elements as $element) {

foreach($element->childNodes as $child) {

if($child->hasAttribute('style')) {

$style = strtolower(trim($child->getAttribute('style')));

//match and get only the CSS Property name
preg_match_all('/(?<names>[a-z\-]+):/', $style, $matches);

for($i=0;$i<sizeof($matches["names"]);$i++) {

  $style_property = $matches["names"][$i];

  // if the css-property is not in allowed styles array
  // then remove the whole style tag from this child

  if(!in_array($style_property,$allowed_styles)) {

   $child->removeAttribute('style');
   continue;

   }

}

    }
  }
}

$dom->saveHTML();
$html_output = $dom->getElementsByTagName('body');

非常に多くの html 文字列をテストしましたが、どこでも問題なく動作します。しかし、このhtml文字列をフィルタリングしようとすると

$html_string = ​'<div style="font-style: italic; text-align: center; 
background-color: red;">On The Contrary</div><span 
style="font-style: italic; background-color: rgb(244, 249, 255); 
font-size: 32px;"><b style="text-align: center; 
background-color: rgb(255, 255, 255);">This is USA</b></span>';

この行を除いて、許可されていない他のすべてのスタイルがこの文字列から削除されます

<b style="text-align: center; background-color: rgb(255, 255, 255);">

ホワイトリスト以外のスタイルを削除するための他の効率的で堅牢な方法を教えてもらえますか

4

2 に答える 2

1

この (および他のネストされた) html では、次のような再帰関数を使用する必要があります。

$html = 'your html';
$allowed_styles = array('font-size','color','font-family','text-align','margin-left');
$html_string = '<body>' . $html . '</body>';
$dom = new DOMDocument();
$dom->loadHTML($html_string);
$elements = $dom->getElementsByTagName('body');
foreach ($elements as $element)
    clearHtml($element, $allowed_styles);
$html_output = $dom->saveHTML(); 

function clearHtml($tree, $allowed_styles) {
    if ($tree->nodeType != XML_TEXT_NODE) {
        if ($tree->hasAttribute('style')) {
            $style = strtolower(trim($tree->getAttribute('style')));
            preg_match_all('/(?<names>[a-z\-]+):/', $style, $matches);
            for($i = 0; $i < sizeof($matches['names']); $i++) {
                $style_property = $matches['names'][$i];
                if(!in_array($style_property, $allowed_styles)) {
                    $tree->removeAttribute('style');
                    continue;
                }
            }
        }
        if ($tree->childNodes)
            foreach ($tree->childNodes as $child)
                clearHtml($child, $allowed_styles);
    }
}
于 2013-03-29T16:08:56.030 に答える