Обрезать текст в формате HTML с помощью SMARTY - PullRequest
3 голосов
/ 20 апреля 2010

У меня есть переменная, отформатированная со случайным HTML-кодом. Я называю это {$text} и усекаю его.

Значение, например:

<div>Lorem <i>ipsum <b>dolor <span>sit </span>amet</b>, con</i> elit.</div>

Если я урежу первые ~ 30 букв текста, я получу это:

<div>Lorem <i>ipsum <b>dolor <span>sit 

Проблема в том, что я не могу закрыть элементы. Итак, мне нужен скрипт, который проверяет элементы <*> в коде (где * может быть что угодно), и если у него нет закрывающего тега, закройте их.

Пожалуйста, помогите мне в этом. Спасибо.

Решение в нерабочее время и 4 голосования @ stackoverflow:

PHP:

...
function closetags($content) {
   preg_match_all('#<(?!meta|img|br|hr|input\b)\b([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $content, $result);
    $openedtags = $result[1];
  preg_match_all('#</([a-z]+)>#iU', $content, $result);
 $closedtags = $result[1];
  $len_opened = count($openedtags);
  if (count($closedtags) == $len_opened) {
       return $content;
  }
  $openedtags = array_reverse($openedtags);
  for ($i=0; $i < $len_opened; $i++) {
        if (!in_array($openedtags[$i], $closedtags)) {
         $content .= '</'.$openedtags[$i].'>';
       } else {
           unset($closedtags[array_search($openedtags[$i], $closedtags)]);
        }
  }
  return $content;
}
...

TPL:

{$pages[j].text|truncate:300|@closetags}

Ответы [ 3 ]

0 голосов
/ 20 апреля 2010

Чтобы упростить, если код является допустимым XML перед усечением, и вы не обрезаете теги пополам, алгоритм будет выглядеть примерно так:

  • Вставка открывающих тегов в стек
  • Отключите их, когда найдете закрывающий тег (который будет совпадать, если код верен).
  • Когда вы дойдете до конца, начните появляться, чтобы создать закрытие.Остальные теги должны быть добавлены к исходному (усеченному) тексту.

Пример:

<div>Lorem <i>ipsum <b>dolor <span>sit </span>amet</b><div>
  • Нажмите "div", "i", "b","span"
  • Найденный закрывающий тег "span"
  • Pop "span"
  • Найденный закрывающий тег "b"
  • Pop "b"
  • Нажмите «div»
  • Конец усеченного текста
  • Выделите «div» -> добавьте </div> к тексту
  • Поп «b» -> добавьте</b> к тексту
  • Pop "i" -> добавить </i> к тексту
  • Pop "div" -> добавить </div> к тексту
  • End
0 голосов
/ 04 марта 2018

для других людей, таких как я, и вы, я нашел этот код, я думаю, что это лучшее решение

добавить этот файл с именем "modifier.html_substr.php"

        <?php
    /*
    * Smarty plugin
    *
    -------------------------------------------------------------
    * File: modifier.html_substr.php
    * Type: modifier
    * Name: html_substr
    * Version: 1.0
    * Date: June 19th, 2003
    * Purpose: Cut a string preserving any tag nesting and matching.
    * Install: Drop into the plugin directory.
    * Author: Original Javascript Code: Benjamin Lupu <hide@address.com>
    * Translation to PHP & Smarty: Edward Dale <hide@address.com>
    * Modification to add a string: Sebastian Kuhlmann <hide@address.com>
    * Modification to put the added string before closing <p> or <li> tags by Peter Carter http://www.podhawk.com
    -------------------------------------------------------------
    */
    function smarty_modifier_html_substr($string, $length, $addstring="")
    {

    //some nice italics for the add-string
    if (!empty($addstring)) $addstring = "<i> " . $addstring . "</i>";

    if (strlen($string) > $length) {
    if( !empty( $string ) && $length>0 ) {
    $isText = true;
    $ret = "";
    $i = 0;

    $currentChar = "";
    $lastSpacePosition = -1;
    $lastChar = "";

    $tagsArray = array();
    $currentTag = "";
    $tagLevel = 0;

    $addstringAdded = false;

    $noTagLength = strlen( strip_tags( $string ) );

    // Parser loop
    for( $j=0; $j<strlen( $string ); $j++ ) {

    $currentChar = substr( $string, $j, 1 );
    $ret .= $currentChar;

    // Lesser than event
    if( $currentChar == "<") $isText = false;

      // Character handler
      if( $isText ) {

          // Memorize last space position
          if( $currentChar == " " ) { $lastSpacePosition = $j; }
          else { $lastChar = $currentChar; }

          $i++;
          } else {
          $currentTag .= $currentChar;
          }

          // Greater than event
          if( $currentChar == ">" ) {
              $isText = true;

              // Opening tag handler
              if( ( strpos( $currentTag, "<" ) !== FALSE ) &&
              ( strpos( $currentTag, "/>" ) === FALSE ) &&
              ( strpos( $currentTag, "</") === FALSE ) ) {

              // Tag has attribute(s)
              if( strpos( $currentTag, " " ) !== FALSE ) {
                  $currentTag = substr( $currentTag, 1, strpos( $currentTag, " " ) - 1 );
                  } else {
                  // Tag doesn't have attribute(s)
                  $currentTag = substr( $currentTag, 1, -1 );
                  }

                  array_push( $tagsArray, $currentTag );

                  } else if( strpos( $currentTag, "</" ) !== FALSE ) {
                  array_pop( $tagsArray );
                  }

              $currentTag = "";
              }

          if( $i >= $length) {
          break;
          }
      }

    // Cut HTML string at last space position
    if( $length < $noTagLength ) {
    if( $lastSpacePosition != -1 ) {
    $ret = substr( $string, 0, $lastSpacePosition );
    } else {
    $ret = substr( $string, $j );
    }
    }

    // Close broken XHTML elements
    while( sizeof( $tagsArray ) != 0 ) {
    $aTag = array_pop( $tagsArray );
      // if a <p> or <li> tag needs to be closed, put the add-string in first
      if (($aTag == "p" || $aTag == "li") && strlen($string) > $length) {
      $ret .= $addstring;
      $addstringAdded = true;
      }
    $ret .= "</" . $aTag . ">\n";
    }

    } else {
    $ret = "";
    }

    // if we have not added the add-string already 
    if ( strlen($string) > $length && $addstringAdded == false) {
    return( $ret.$addstring );
    }
    else {
    return ( $ret );
    }
    }
    else {
    return ( $string );
    }
    }
    ?>

использование

{$yourdata|html_substr:300:' ...'}
0 голосов
/ 20 апреля 2010

Вытащите все открытые теги, вставьте их в массив (array_1) по одному.

Вытащите все закрытые теги, вставьте их в массив (array_2) один за другим (включая самозакрывающиеся теги).

Для тегов в первом массиве (array_1), которые не найдены во втором массиве (array_2), добавьте их в HTML.

[править]

Конечно, этот метод с треском провалится, если вы не напишите правильный html ... но whatchagonnado?

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

...