私が知っていることから、これは単純な文字列分割では達成できません。なぜなら、すでにわかっているように、htmlを壊す可能性が非常に高いからです。
ただし、次のことができます。
1) HTML 文字列 char を char ごとに読み込み、タグの構造を追跡する
2) HTML をオブジェクトとして読み込み、要素のテキスト ノードをカウントする
2.1)ロードには、使用できます
- DOM - http://php.net/manual/en/book.dom.php
- SimpleXML - http://php.net/manual/en/book.simplexml.php
- HTML の読み込みを処理する PHP ライブラリは他にもたくさんあります
2.2) 読み込まれた要素を調べて、そのテキスト ノードを数えます
- コードを通過するアルゴリズムを使用する
- カウントが目的の長さになるまで、テキスト ノードをカウントします。
- その後、次に表示されるすべてのテキストノードを消去します
表示可能な文字については、PHP 自体は要素にどの CSS があるかを認識していませんgetAttribute('style')
。
注: 1) と 2) のどちらの場合も少しパフォーマンスが必要です。トラフィックの多いサイトにこれを適用する場合は、これらの結果に対して何らかのキャッシュを検討する必要があります。
編集: 広告 1)
開いているタグを追跡する方法のサンプル関数を作成しました
注:この関数は XHTML を想定しています。(自己閉鎖タグは自己閉鎖として期待さ<img>
れます。<img />
また、これを簡単に作成しただけなので、最善でも効率的な方法でもない可能性があることに注意してください:)
http://ideone.com/erSDlgで動作することがわかります。
//PHP
function closeTags( &$html, $length = 20 ){
$htmlLength = strlen($html);
$unclosed = array();
$counter = 0;
$i=0;
while( ($i<$htmlLength) && ($counter<$length) ){
if( $html[$i]=="<" ){
$currentTag = "";
$i++;
if( ($i<$htmlLength) && ($html[$i]!="/") ){
while( ($i<$htmlLength) && ($html[$i]!=">") && ($html[$i]!="/") ){
$currentTag .= $html[$i];
$i++;
}
if( $html[$i] == "/" ){
do{ $i++; } while( ($i<$htmlLength) && ($html[$i]!=">") );
} else {
$currentTag = explode(" ", $currentTag);
$unclosed[] = $currentTag[0];
}
} elseif( $html[$i]=="/" ){
array_pop($unclosed);
do{ $i++; } while( ($i<$htmlLength) && ($html[$i]!=">") );
}
} else{
$counter++;
}
$i++;
}
$result = substr($html, 0, $i-1);
$unclosed = array_reverse( $unclosed );
foreach( $unclosed as $tag ) $result .= '</'.$tag.'>';
print_r($result);
}
$html = "<div>123890<span>1234<img src='i.png' /></span>567890<div><div style='test' class='nice'>asfaasf";
closeTags( $html, 20 );