2011-09-16 32 views
3

試圖編寫此類函數。它必須將文本分成多個列,並且輸出必須是有效的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; 
} 

的作品,但是當試圖某些文本分成兩列,我得到了第一列和第二未拆封未關閉的標籤。如何解決這個問題?需要幫忙!

+0

任何時候你使用字符串函數(或正則表達式)來做_anything_與HTML,你一定會遇到問題。也就是說,你得到的和你想要的東西的一些樣本輸出將會有所幫助。 :) – Herbert

+0

closetags()做什麼?你能告訴我們這個方法嗎? – Chris

+0

嗨Zhlobopotam。我剛開始研究同樣的問題,並樂於分享我的最終解決方案,如果它有幫助。正如@Chris所說 - closetags()做了什麼? – BaronGrivet

回答

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