Php 如何在不破坏标记的情况下剪裁HTML片段?

Php 如何在不破坏标记的情况下剪裁HTML片段?,php,html,post,tags,Php,Html,Post,Tags,假设我有一个包含HTML标记的200个字符的字符串。我只想展示前50个字符的预览。没有“拆分”标签。换句话说,片段不应该包含没有的。任何服务器端处理都应该使用PHP。一个简单的方法可能是先去除标签(),然后捕获摘录。只需在前50个非HTML字符后剪切它,然后在Tidy中运行它来修复HTML。简短回答:使用DOMDocument::loadHTML($string)将其转换为DOM然后遍历树,计算文本节点中的字符数。当达到极限时,用“…”或空字符串替换该节点的其余部分,然后在所有后续节点上调用$n

假设我有一个包含HTML标记的200个字符的字符串。我只想展示前50个字符的预览。没有“拆分”标签。换句话说,片段不应该包含没有
。任何服务器端处理都应该使用PHP。

一个简单的方法可能是先
去除标签()
,然后捕获摘录。

只需在前50个非HTML字符后剪切它,然后在Tidy中运行它来修复HTML。

简短回答:使用
DOMDocument::loadHTML($string)将其转换为DOM
然后遍历树,计算文本节点中的字符数。当达到极限时,用“…”或空字符串替换该节点的其余部分,然后在所有后续节点上调用
$node->parentNode->removeChild($node)

这里有一个使用标准PHP的一部分DOMDocument的快速可靠的解决方案:

function cut_html ($html, $limit) {
    $dom = new DOMDocument();
    $dom->loadHTML(mb_convert_encoding("<div>{$html}</div>", "HTML-ENTITIES", "UTF-8"), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
    cut_html_recursive($dom->documentElement, $limit);
    return substr($dom->saveHTML($dom->documentElement), 5, -6);
}

function cut_html_recursive ($element, $limit) {
    if($limit > 0) {
        if($element->nodeType == 3) {
            $limit -= strlen($element->nodeValue);
            if($limit < 0) {
                $element->nodeValue = substr($element->nodeValue, 0, strlen($element->nodeValue) + $limit);
            }
        }
        else {
            for($i = 0; $i < $element->childNodes->length; $i++) {
                if($limit > 0) {
                    $limit = cut_html_recursive($element->childNodes->item($i), $limit);
                }
                else {
                    $element->removeChild($element->childNodes->item($i));
                    $i--;
                }
            }
        }
    }
    return $limit;
}
function cut\u html($html,$limit){
$dom=新的DOMDocument();
$dom->loadHTML(mb_convert_编码(“{$html}”、“html-ENTITIES”、“UTF-8”)、LIBXML_html_noimpled、LIBXML_html_NODEFDTD);
剪切html递归($dom->documentElement,$limit);
返回substr($dom->saveHTML($dom->documentElement),5,-6);
}
函数cut\u html\u递归($element,$limit){
如果($limit>0){
如果($element->nodeType==3){
$limit-=strlen($element->nodeValue);
如果($limit<0){
$element->nodeValue=substr($element->nodeValue,0,strlen($element->nodeValue)+$limit);
}
}
否则{
对于($i=0;$i<$element->childNodes->length;$i++){
如果($limit>0){
$limit=cut\u html\u recursive($element->childNodes->item($i),$limit);
}
否则{
$element->removeChild($element->childNodes->item($i));
$i--;
}
}
}
}
返回$limit;
}

我同意——这是我一直在做的事。唯一的缺点是丢失了strong、em等的格式。。以及任何链接-但我总是接受它并继续前进:-)