php - texto - Cómo recortar fragmentos de HTML sin romper las etiquetas?
php cortar cadena puntos suspensivos (4)
Aquí hay una solución rápida y confiable usando DOMDocument que es parte de PHP estándar:
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;
}
Supongamos que tengo una cadena de 200 caracteres que contiene marcas HTML. Quiero mostrar una vista previa de solo los primeros 50 caracteres. sin ''dividir'' las etiquetas. En otras palabras, el fragmento no debe contener un <b>
sin un </b>
. Cualquier procesamiento del lado del servidor debe estar en PHP.
Respuesta corta: DOMDocument::loadHTML($string)
en DOM con DOMDocument::loadHTML($string)
y recorra el árbol contando los caracteres en los nodos de texto. Cuando llegue a su límite, reemplace el resto de ese nodo con ''...'' o la cadena vacía, y simplemente llame a $node->parentNode->removeChild($node)
en todos los nodos siguientes.
Un enfoque simple podría ser strip_tags()
primero y luego capturar el extracto.
Deberías revisar Tidy HTML. Solo córtela después de los primeros 50 caracteres que no son HTML, luego ejecútelo con Tidy para corregir el HTML.