PHP htmlentities () без преобразования HTML-тегов - PullRequest
5 голосов
/ 13 июня 2011

Я нашел несколько постов, в которых говорится о проблеме, но ни одно из них не решило ее полностью.

Мне нужна функция, которая будет выводить содержимое, преобразуя все специальные символы так, как это делает htmlentities (), но сохраняя все теги html.

Я пробовал много разных подходов, но, как я упоминал выше, ни один из них не работает так, как ожидалось.

Мне было интересно, есть ли способ сделать это, используя PHP-класс DomDocument.

Я пытался сделать это, используя следующее:

$objDom = new DOMDocument('1.0', 'utf-8');
$objDom->loadhtml($content);
return $objDom->savehtml();

, который работает, но также добавляет всю структуру страницы, т.е.

<head><body> etc.

Мне нужно только преобразовать содержимое переменной $ content и выполнить работу.

Еще одна вещь, о которой стоит упомянуть, это то, что $ content может также содержать некоторые символы, преобразованные в жалобу xhtml - как это происходит из Wysiwyg. Таким образом, он может содержать & и т. Д., Которые также должны быть сохранены.

Кто-нибудь знает способ сделать это с DomDocument - возможно, я должен использовать другой метод сохранения?

Хорошо - я придумала следующее - не очень, но работает на:

$objDom = new DOMDocument('1.0', 'UTF-8');
$objDom->loadHTML($string);
$output = $objDom->saveXML($objDom->documentElement);
$output = str_replace('<html><body>', '', $output);
$output = str_replace('</body></html>', '', $output);
$output = str_replace('&#13;', '', $output);
return $output; 

Любые лучшие идеи будут высоко оценены.

Ответы [ 4 ]

5 голосов
/ 13 июня 2011

Вы можете использовать get_html_translation_table и удалить элементы < и >:

$trans = get_html_translation_table(HTML_ENTITIES, ENT_NOQUOTES);
unset($trans['<'], $trans['>']);
$output = strtr($input, $trans);
4 голосов
/ 13 июня 2011

get_html_translation_table (HTML_ENTITIES) предоставляет вам таблицу перевода, используемую в htmlentities () в качестве массива.Вы можете удалить <,> и "из массива следующим образом:

<?php
$trans = get_html_translation_table(HTML_ENTITIES);
unset($trans["\""], $trans["<"], $trans[">"]);
$str = "Hallo <strong>& Frau</strong> & Krämer";
$encoded = strtr($str, $trans);

echo $encoded;
?>
0 голосов
/ 15 июня 2011

Хорошо - после многих исследований я нашел окончательный вариант - который, кажется, как раз то, что мне нужно.

Я использовал HTMLPurifier и отфильтровалсодержание, используя следующее:

require_once('HTMLPurifier/HTMLPurifier.auto.php');
$config = HTMLPurifier_Config::createDefault();
$config->set('HTML.Doctype', 'XHTML 1.0 Transitional');
$objPurifier = new HTMLPurifier($config);
return $objPurifier->purify($string);

Я надеюсь, что кто-то еще найдет это полезным.

0 голосов
/ 13 июня 2011

Позвольте мне начать с того, что, по моему мнению, то, что вы пытаетесь сделать, в корне неверно.Что делать, если кто-то хочет ввести знак «меньше»?Лично я вижу htmlentities() как способ убедиться, что пользователи не могут ввести свой собственный HTML-код.

Если вам нужно, чтобы пользователи могли стилизовать текст, есть много решенийуже сделано для этого (проверьте TinyMCE или Markdown , например).

Если вы должны разрешить пользователям вводить теги HTML, и Вы должны предположить, что они не знают, как использовать сущности, вот простая функция, которая работает:

function my_htmlentities ($str)
{
  // We'll append everything to this.
  $result = '';

  // Continue while there are HTML tags.
  while (($lt = strpos($str, '<')) !== false)
  {
    // Run `htmlentities` on everything before the tag, and pop it 
    // off the original string.
    $result .= htmlentities(substr($str, 0, $lt));
    $str = substr($str, $lt);

    // We want to continue until we reach the end of the tag. I know 
    // these loops are bad form. Sorry. I still think in F77 :p
    while (true)
    {
      // Find the closing tag as well as quotes.
      $gt = strpos($str, '>');
      $quot = strpos($str, '"');

      // If there is no closing bracket, append the rest of the tag 
      // as plaintext and exit.
      if ($gt === false)
        return $result . $str;

      // If there is a quote before the closing bracket, take care 
      // of it.
      if ($quot !== false && $quot < $gt)
      {
        // Grab everything before the quote.
        $result .= substr($str, 0, $quot+1);
        $str = substr($str, $quot+1);

        // Find the closing quote (if there is none, append and 
        // exit).
        if (($quot = strpos($str, '"')) === false)
          return $result . $str;

        // Grab the inside of the quote.
        $result .= substr($str, 0, $quot+1);
        $str = substr($str, $quot+1);

        // Start over as if we were at the beginning of the tag.
        continue;
      }

      // We just have the closing bracket to deal with. Deal.
      $result .= substr($str, 0, $gt+1);
      $str = substr($str, $gt+1);
      break;
    }
  }

  // There are no more tags, so we can run `htmlentities()` on the 
  // rest of the string.
  return $result . htmlentities($str);

  // Alternatively, if you want users to be able to enter their own
  // entities as well, you'll have to use this last line instead:
  return str_replace('&amp;', '&', $result . htmlentities($str));
}

Но, пожалуйста, позвольте мне повторить: это крайне небезопасно!Я дам вам преимущество сомнения, что вы знаете, чего хотите, но я не думаю, что вы (или кто-либо другой) должны этого хотеть.

...