Как обрезать фрагменты HTML без разбивки тегов?

Скажем, у меня есть строка с 200 символами, содержащая разметку HTML. Я хочу показать предварительный просмотр только первых 50 символов. без «расщепления» тегов. Другими словами, фрагмент не должен содержать <b> без </b> . Любая обработка на стороне сервера должна быть в PHP.

Вы должны проверить Tidy HTML. Просто отрежьте его после первых 50 символов, отличных от HTML, а затем запустите его через Tidy, чтобы исправить HTML.

Простым подходом может быть strip_tags() а затем захват выдержки.

Короткий ответ: преобразуйте его в DOM с помощью DOMDocument::loadHTML($string) затем пройдите дерево, считая символы в текстовых узлах. Когда вы нажмете свой лимит, замените остальную часть этого узла на «…» или пустую строку и просто вызовите $node->parentNode->removeChild($node) на всех последующих узлах.

Вот быстрое и надежное решение, использующее DOMDocument, который является частью стандартного PHP:

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