我正在粘贴下面的PHP类我以前写了长时间,但我知道它的工作原理。它并不完全是你所追求的,因为它处理的是单词而不是字符数,但我认为它非常接近,有人可能会觉得它有用。
class HtmlWordManipulator
{
var $stack = array();
function truncate($text, $num=50)
{
if (preg_match_all('/\s+/', $text, $junk) <= $num) return $text;
$text = preg_replace_callback('/(<\/?[^>]+\s+[^>]*>)/','_truncateProtect', $text);
$words = 0;
$out = array();
$text = str_replace('<',' <',str_replace('>','> ',$text));
$toks = preg_split('/\s+/', $text);
foreach ($toks as $tok)
{
if (preg_match_all('/<(\/?[^\x01>]+)([^>]*)>/',$tok,$matches,PREG_SET_ORDER))
foreach ($matches as $tag) $this->_recordTag($tag[1], $tag[2]);
$out[] = trim($tok);
if (! preg_match('/^(<[^>]+>)+$/', $tok))
{
if (!strpos($tok,'=') && !strpos($tok,'<') && strlen(trim(strip_tags($tok))) > 0)
{
++$words;
}
else
{
/*
echo '<hr />';
echo htmlentities('failed: '.$tok).'<br /)>';
echo htmlentities('has equals: '.strpos($tok,'=')).'<br />';
echo htmlentities('has greater than: '.strpos($tok,'<')).'<br />';
echo htmlentities('strip tags: '.strip_tags($tok)).'<br />';
echo str_word_count($text);
*/
}
}
if ($words > $num) break;
}
$truncate = $this->_truncateRestore(implode(' ', $out));
return $truncate;
}
function restoreTags($text)
{
foreach ($this->stack as $tag) $text .= "</$tag>";
return $text;
}
private function _truncateProtect($match)
{
return preg_replace('/\s/', "\x01", $match[0]);
}
private function _truncateRestore($strings)
{
return preg_replace('/\x01/', ' ', $strings);
}
private function _recordTag($tag, $args)
{
// XHTML
if (strlen($args) and $args[strlen($args) - 1] == '/') return;
else if ($tag[0] == '/')
{
$tag = substr($tag, 1);
for ($i=count($this->stack) -1; $i >= 0; $i--) {
if ($this->stack[$i] == $tag) {
array_splice($this->stack, $i, 1);
return;
}
}
return;
}
else if (in_array($tag, array('p', 'li', 'ul', 'ol', 'div', 'span', 'a')))
$this->stack[] = $tag;
else return;
}
}
truncate是你想要的,并且你把它传递给你想要修剪的html和字数。它在计算单词时忽略html,但随后在html中重新包装所有内容,甚至由于截断而关闭尾随标签。
请不要判断我完全缺乏oop原则。我当时年少无知。
编辑:
所以它原来的使用更是这样的:
$content = $manipulator->restoreTags($manipulator->truncate($myHtml,$numOfWords));
愚蠢的设计决策。允许我在未封闭的标签内注入html。
您是否希望将文本计算为不使用html,但随后返回包装在原始html中? – 2011-04-19 04:09:22
是的。我希望它被包裹在html中,以便我可以在页面上显示它。 – Vin 2011-04-19 09:00:32
我在前面的答案中添加了一些伪元素 - 希望它能指引您朝着正确的方向发展。我真的很抱歉,我没有时间去做正确的工作,但通过交叉手指会让你渡过难关。发布你的答案,如果你拿出解决方案!我很想看。 – 2011-04-20 18:02:07