将字符串拆分为多列(可识别标记)

时间:2011-09-16 08:46:48

标签: php tags split paragraph

尝试编写此类功能。它必须将文本分成多列,输出必须是有效的html,例如没有未打开(!!!)关闭标签,没有未关闭的标签。这是我的代码:

function convert2columns($content = '', $columns = 2) {
$result = array();
$content = closetags($content);
$bodytext = array("$content");
$text = implode(",", $bodytext);
$length = strlen($text);
$length = ceil($length / $columns);
$words = explode(" ", $text);    
$c = count($words);
$l = 0;
for ($i = 1; $i <= $columns; $i++) {
    $new_string = "";
    for ($g = $l; $g <= $c; $g++) {
        if (strlen($new_string) <= $length || $i == $columns) {            
if (in_array(substr(@$words[$g], $length - 1, 1), array(' ', '.', '!', '?')))
                $new_string .= @$words[$g] . " ";
            else {
                $split = substr(@$words[$g], 0, $length - 1);
                $lastSpace = strrpos($split, ' ');
                if ($lastSpace !== false) {
                    $split = substr($split, 0, $lastSpace);
                }
                if (in_array(substr($split, -1, 1), array(','))) {
                    $split = substr($split, 0, -1);
                }
                $new_string .= $split . " ";
            }
        } else {
            $l = $g;
            break;
        }
    }
    $result[] = $new_string;
}
return $result;
}

可以使用,但是当尝试将一些文本划分为2列时,我会在第一列中获得未关闭的标记,而在第二列中打开未打开的标记。如何解决这个问题?需要帮助!

1 个答案:

答案 0 :(得分:4)

这是我的解决方案。我想要一些能够识别段落,块引用,表格等的代码,所以第二列总是在所有标签关闭后开始。

function ContentToTwoColumns($fullContent){
  //Get character length of content
  $fullContentLength = strlen($fullContent);
  //Set the ratio of column size
  $column1Percent = .55;
  $column2Percent = .45;

  //Break the content into two columns using the ratios given.
  $columnsContent = array();
  $columnBreak = round($column1Percent * $fullContentLength);
  $columnsContent[0] = substr($fullContent, 0, $columnBreak);
  $columnsContent[1] = substr($fullContent, $columnBreak);

  //Check for unclosed tags in the first column by comparing
  //the number of open tags with closed tags.
  $numTags = countOpenClosedTags($columnsContent[0]);
  $numOpened = $numTags[0];
  $numClosed = $numTags[1];
  $unclosedTags = $numOpened - $numClosed;

  //echo '<p>Opened Tags: '.$numTags[0].'</p>';
  //echo '<p>Closed Tags: '.$numTags[1].'</p>';
  //echo '<p>Unclosed Tags: '.$unclosedTags.'</p>';

  //If there are unclosed tags recalculate the column break.
  if($unclosedTags > 0){

    //Return the identity of all open tags in the first column.
    preg_match_all("#<([a-z]+)( .*)?(?!/)>#iU", $columnsContent[0], $result);
    $openedTags = $result[1];

    //Return the identity of all closed tags in the first column.
    preg_match_all("#</([a-z]+)>#iU", $columnsContent[0], $result);
    $closedTags = $result[1];

    //Reverse array of open tags so they can be matched against the closed tags.
    $openedTags = array_reverse($openedTags);

    //Loop through open/closed tags to identify first unclosed tag
    //in first column on content.
    for( $i = 0; $i < $numOpened; $i++ ){
      if ( !in_array ( $openedTags[$i], $closedTags ) ){
        $firstOpenTag = $openedTags[$i];
        //echo '<p>Open Tag: &lt;'.$firstOpenTag.'&gt;</p>';
      } else {
        unset ( $closedTags[array_search ( $openedTags[$i], $closedTags)] );
      }
    }

    //Get name of first open tag and create a closed version.
    //$firstOpenTag = $openedTags[$tagNum][0];
    $firstOpenTagClosed = '</'.$firstOpenTag.'>';

    //Calculate the tag length of the closed version.
    $tagLength = strlen($firstOpenTagClosed);

    //Locate the position of the first closed tag in the second column
    //content that matches the first opened tag in the first column
    $positionCloseTag = strpos($columnsContent[1], $firstOpenTagClosed);

    //Calculate the position of the new column break using the
    //position of and length the final closing tag.
    $columnBreak = $columnBreak + $positionCloseTag + $tagLength;

    //echo '<p>Final Closing Tag: &lt;/'.$firstOpenTag.'&gt;</p>';
    //echo '<p>Column Break Point: '.$columnBreak.'</p>';

    // Break the content into two columns using the new break point. 
    $columnsContent[0] = substr($fullContent, 0, $columnBreak);
    $columnsContent[1] = substr($fullContent, $columnBreak);
   }

  // Return the two columns as an array
  return $columnsContent;
}

function countOpenClosedTags($html){
  //Return the identity and position of all open tags in the HTML.
  preg_match_all("#<([a-z]+)( .*)?(?!/)>#iU", $html, $result, PREG_OFFSET_CAPTURE);

  //Check that the returned result array isn't empty.
  if (!isset($result[1])){
    $numOpened = 0;
  } else {
    //If the result array isn't empty get the number of open tags.
    $openedTags = $result[1];
    $numOpened = (!$openedTags) ? 0 : count($openedTags);
  }

  //Return the identity and position of all close tags in the HTML.
  preg_match_all("#</([a-z]+)>#iU", $html, $result, PREG_OFFSET_CAPTURE);

  //Check that the returned result array isn't empty.
  if (!isset($result[1])){
    $numClosed = 0;
  } else {
    //If the result array isn't empty get the number of close tags.
    $closedTags = $result[1];
    $numClosed = (!$closedTags) ? 0 : count($closedTags);
  }

  //Create an array to return the open and close counts.
  $numTags = array($numOpened, $numClosed);
  return $numTags;
}