给定一个HTML字符串,我想返回一个具有以下属性的修改后的字符串:
- 文本内容的前n个字符(HTML标记除外)应保留
- 满足n字符后的元素应完全删除
- 如果n字符不在元素的末尾,则同一元素中后面的文本不应保留
- n字符及其之前的元素上的标记应保留
基本上,我只想返回HTML的缩短版本,而不中断DOM结构,并且只基于文本内容的长度。
使用PHP的DOM实现,这似乎会过于复杂。使用模式匹配并不理想,因为修改后的字符串的条件可能会随着时间的推移而变化,而且每次都需要重写。
我是不是错过了一种更简单的方法?提前谢谢。
"使用PHP的DOM实现,这似乎过于复杂。"
真的吗
如果您想要<body>
标记及其子节点中的前100个字符,这里有一个非常简单的DOM实现。您可以进一步调整以删除换行符和多余的空格/制表符,或者检查foreach
中$content
字符串的长度,以中断循环并在达到一定数量的字符后停止串联。
$str = '...';
$dom = new DomDocument;
$dom->loadHTML($str);
$elements = $dom->getElementsByTagName('body');
$content = '';
foreach($elements as $node){
foreach($node->childNodes as $child) {
$content .= $child->nodeValue;
}
}
echo substr($content, 0, 100);
更新
根据您的评论,这里有一个简单的方法来计算HTML节点内的字符数,并在达到指定的字符限制后删除所有标记。请注意,不能在原始foreach
中执行删除操作,因为这会导致DOM
对节点进行重新索引,并且不会得到预期的结果。相反,我们将要删除的节点存储在数组中,并在初始迭代后删除它们。
$str = '...';
$dom = new DomDocument;
$dom->preserveWhitespace = FALSE;
$dom->loadHTML($str);
$elements = $dom->getElementsByTagName('body');
$remove = FALSE;
$maxChars = 100;
$content = '';
$delete = array();
foreach($elements as $node){
foreach($node->childNodes as $child) {
if ($remove) {
$delete[] = $child;
} else {
$content .= $child->nodeValue;
if ( ! $remove && strlen($content) >= $maxChars) {
$remove = TRUE;
}
}
}
}
foreach ($delete as $child) {
$child->parentNode->removeChild($child);
}
$dom->formatOutput = TRUE;
echo $dom->saveHTML();