Как я могу удалить атрибуты из HTML-тега?

Как я могу использовать php для удаления всех / любых атрибутов из тега, скажем, тега абзаца?

<p class="one" otherrandomattribute="two"> в <p>

6 ответов

Хотя есть и лучшие способы, вы могли бы на самом деле вырезать аргументы из тегов html с помощью регулярного выражения:

<?php
function stripArgumentFromTags( $htmlString ) {
    $regEx = '/([^<]*<\s*[a-z](?:[0-9]|[a-z]{0,9}))(?:(?:\s*[a-z\-]{2,14}\s*=\s*(?:"[^"]*"|\'[^\']*\'))*)(\s*\/?>[^<]*)/i'; // match any start tag

    $chunks = preg_split($regEx, $htmlString, -1,  PREG_SPLIT_DELIM_CAPTURE);
    $chunkCount = count($chunks);

    $strippedString = '';
    for ($n = 1; $n < $chunkCount; $n++) {
        $strippedString .= $chunks[$n];
    }

    return $strippedString;
}
?>

Выше может быть написано меньше символов, но это делает работу (быстро и грязно).

Удалите атрибуты, используя SimpleXML (Стандарт в PHP5)

<?php

// define allowable tags
$allowable_tags = '<p><a><img><ul><ol><li><table><thead><tbody><tr><th><td>';
// define allowable attributes
$allowable_atts = array('href','src','alt');

// strip collector
$strip_arr = array();

// load XHTML with SimpleXML
$data_sxml = simplexml_load_string('<root>'. $data_str .'</root>', 'SimpleXMLElement', LIBXML_NOERROR | LIBXML_NOXMLDECL);

if ($data_sxml ) {
    // loop all elements with an attribute
    foreach ($data_sxml->xpath('descendant::*[@*]') as $tag) {
        // loop attributes
        foreach ($tag->attributes() as $name=>$value) {
            // check for allowable attributes
            if (!in_array($name, $allowable_atts)) {
                // set attribute value to empty string
                $tag->attributes()->$name = '';
                // collect attribute patterns to be stripped
                $strip_arr[$name] = '/ '. $name .'=""/';
            }
        }
    }
}

// strip unallowed attributes and root tag
$data_str = strip_tags(preg_replace($strip_arr,array(''),$data_sxml->asXML()), $allowable_tags);

?>

Вот одна функция, которая позволит вам удалить все атрибуты, кроме тех, которые вы хотите:

function stripAttributes($s, $allowedattr = array()) {
  if (preg_match_all("/<[^>]*\\s([^>]*)\\/*>/msiU", $s, $res, PREG_SET_ORDER)) {
   foreach ($res as $r) {
     $tag = $r[0];
     $attrs = array();
     preg_match_all("/\\s.*=(['\"]).*\\1/msiU", " " . $r[1], $split, PREG_SET_ORDER);
     foreach ($split as $spl) {
      $attrs[] = $spl[0];
     }
     $newattrs = array();
     foreach ($attrs as $a) {
      $tmp = explode("=", $a);
      if (trim($a) != "" && (!isset($tmp[1]) || (trim($tmp[0]) != "" && !in_array(strtolower(trim($tmp[0])), $allowedattr)))) {

      } else {
          $newattrs[] = $a;
      }
     }
     $attrs = implode(" ", $newattrs);
     $rpl = str_replace($r[1], $attrs, $tag);
     $s = str_replace($tag, $rpl, $s);
   }
  }
  return $s;
}

В примере это будет:

echo stripAttributes('<p class="one" otherrandomattribute="two">');

или если вы, например. хотите сохранить атрибут "класс":

echo stripAttributes('<p class="one" otherrandomattribute="two">', array('class'));

Или же

Предполагая, что вы должны отправить сообщение в папку "Входящие", и вы создали сообщение с помощью CKEDITOR, вы можете назначить функцию следующим образом и передать ее переменной $message перед отправкой. Обратите внимание, что функция с именем stripAttributes() удалит все ненужные HTML-теги. Я попробовал, и все работает нормально. я только видел форматирование, которое я добавил, как жирный шрифт и т. д.

$message = stripAttributes($_POST['message']);

или вы можете echo $message; для предварительного просмотра.

Я искренне считаю, что единственный разумный способ сделать это - использовать белый список тегов и атрибутов с библиотекой HTML-очистителя. Пример скрипта здесь:

<html><body>

<?php

require_once '../includes/htmlpurifier-4.5.0-lite/library/HTMLPurifier/Bootstrap.php';
spl_autoload_register(array('HTMLPurifier_Bootstrap', 'autoload'));

$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Allowed', 'p,b,a[href],i,br,img[src]');
$config->set('URI.Base', 'http://www.example.com');
$config->set('URI.MakeAbsolute', true);

$purifier = new HTMLPurifier($config);

$dirty_html = "
  <a href=\"http://www.google.de\">broken a href link</a
  fnord

  <x>y</z>
  <b>c</p>
  <script>alert(\"foo!\");</script>

  <a href=\"javascript:alert(history.length)\">Anzahl besuchter Seiten</a>
  <img src=\"www.example.com/bla.gif\" />
  <a href=\"http://www.google.de\">missing end tag
 ende 
";

$clean_html = $purifier->purify($dirty_html);

print "<h1>dirty</h1>";
print "<pre>" . htmlentities($dirty_html) . "</pre>";

print "<h1>clean</h1>";
print "<pre>" . htmlentities($clean_html) . "</pre>";

?>

</body></html>

Это дает следующий чистый, соответствующий стандартам фрагмент HTML:

<a href="http://www.google.de">broken a href link</a>fnord

y
<b>c
<a>Anzahl besuchter Seiten</a>
<img src="http://www.example.com/www.example.com/bla.gif" alt="bla.gif" /><a href="http://www.google.de">missing end tag
ende 
</a></b>

В вашем случае белый список будет:

$config->set('HTML.Allowed', 'p');

HTML Purifier - один из лучших инструментов для очистки HTML с помощью PHP.

Вы также можете посмотреть в HTML-очиститель. Правда, он довольно раздутый и может не соответствовать вашим потребностям, если он только придумает этот конкретный пример, но он предлагает более или менее "пуленепробиваемую" очистку от возможных враждебных html. Также вы можете разрешить или запретить определенные атрибуты (это настраивается).

http://htmlpurifier.org/

Другие вопросы по тегам