【问题标题】:Truncate a HTML formatted text with SMARTY使用 SMARTY 截断 HTML 格式的文本
【发布时间】:2010-04-19 21:29:26
【问题描述】:

我有一个用随机 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 

问题是,我无法关闭元素。所以,我需要一个脚本,它检查代码中的&lt;*&gt; 元素(其中 * 可以是任何东西),如果它没有关闭标签,请关闭它们。

请帮助我。谢谢。

下班后的解决方案,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}

【问题讨论】:

  • 如果在标签中间截断也会遇到其他问题
  • 如果我这样写 > 怎么办?
  • bug :) 但是 html 脚本 ($pages[j].text) 是由文本编辑器 - jwysiwyg 编写的。它不会生成&lt;&lt;s。此后我将不再需要它,但是:您可以检查 PHP 的 $content 是否有重复项,如果您看到 &lt;&lt;&lt;&lt;&lt;... 等,请将其替换为 htmlspecialchars...

标签: html tags smarty truncate


【解决方案1】:

拉出所有打开的标签,将它们一个一个地推入一个数组(array_1)中。

拉出所有闭合标签,将它们一个接一个地推入一个数组(array_2)中(这包括自闭合标签)。

对于第一个数组(array_1)中没有在第二个数组(array_2)中找到的标签,将它们添加到html中。

[编辑]

当然,如果你不写正确的 html,这个方法会惨遭失败……但是 whatchagonnado 呢?

另一种方法是在字符串中向前看以查看哪些标签已关闭并根据需要关闭它们。

【讨论】:

    【解决方案2】:

    为简化起见,如果代码在截断之前是有效的 XML,并且您没有将标签切成两半,那么算法将是这样的:

    • 将开始标签推入堆栈
    • 找到结束标签时弹出它们(如果代码有效,它将匹配)
    • 当你走到尽头时,开始弹出以创建关闭。其余标记应附加到原始(截断)文本中。

    例子:

    <div>Lorem <i>ipsum <b>dolor <span>sit </span>amet</b><div>
    
    • 按“div”、“i”、“b”、“span”
    • 找到结束标记“span”
    • 流行“跨度”
    • 找到结束标记“b”
    • 流行“b”
    • 按“div”
    • 截断文本结束
    • Pop "div" --> 将&lt;/div&gt; 添加到文本中
    • Pop "b" --> 将&lt;/b&gt; 添加到文本中
    • Pop "i" --> 将&lt;/i&gt; 添加到文本中
    • Pop "div" --> 将&lt;/div&gt; 添加到文本中
    • 结束

    【讨论】:

    • @SeanJA,有效的 xhtml 也是有效的 xml。
    • @SeanJA @tloflin 是正确的 - 此方法适用于任何 XML,包括 XHTML。在许多情况下,HTML 不会强制您关闭标签(例如
    • ),因此算法不必关闭这些标签。
  • 很公平,不过我个人认为未封闭的 html 不合适。
  • 【解决方案3】:

    对于像我和你这样的其他人,我找到了这段代码,我认为这是一个更好的解决方案

    添加这个名为“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:' ...'}
    

    【讨论】:

      猜你喜欢
      相关资源
      最近更新 更多
      热门标签