开发者

Split string to multiple columns (tags aware)

Trying to write such function. It must divide text into multiple columns and the output must be valid html, e.g. no unopened(!!!) close tags and no unclosed tags. Here is my code:

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 {
       开发者_StackOverflow社区     $l = $g;
            break;
        }
    }
    $result[] = $new_string;
}
return $result;
}

Works, but When trying to divide some text into 2 columns, I get unclosed tags in first column and unopened in second. How to fix this? Need help!


Here's my solution. I wanted some code that would be aware of paragraphs, blockquotes, tables etc. so the second column always starts after all tags have been closed.

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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜