首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 精準截取 HTML 字符串並保持標籤完整性

     編輯:PHP 綜合知識

處理「含 HTML 標籤的字符串截取」是經典難題:若直接按字符數 substr(),極易產生未閉合標籤、屬性斷裂,導致前端渲染錯亂。本文對比兩種思路,推薦使用 Tidy 擴展 將字符串解析為 DOM 樹,再針對文本節點截斷,最後序列化回 HTML,確保結構完整。

痛點分析

需求:從 <div><a>張三</a> 評論了 <a>李四</a>…</div> 截取前 N 個「可見字符」(中文算 2 寬度),保留所有標籤結構。手動遍歷字符、狀態機判斷 </>、UTF-8 多字節跳過,邏輯極其繁瑣且易出錯(UTF-8 中文可能 3 或 4 字節)。

Tidy 方案詳解

<?php
// 1. 解析為 Tidy 文檔對象(注意編碼參數為 'utf8' 而非 'utf-8')
$tidy = tidy_parse_string($htmlStr, [], 'utf8');
$body = tidy_get_body($tidy); // 取得 <body> 節點

// 2. 遞歸遍歷節點樹,針對文本節點做寬度截取
function trimHtml($node, &$len, &$out) {
    foreach ($node->child as $child) {
        if ($child->type === TIDY_NODETYPE_TEXT) { // 文本節點
            $w = mb_strwidth($child->value, 'utf-8');
            if ($w >= $len) {
                $child->value = mb_strimwidth($child->value, 0, $len, '…', 'utf-8');
                $out .= $child->value;
                $len = 0;
                return false; // 停止遍歷
            } else {
                $out .= $child->value;
                $len -= $w;
            }
        } elseif ($child->type === TIDY_NODETYPE_START || $child->type === TIDY_NODETYPE_END) {
            $out .= $child->value; // 直接輸出標籤原文
            if ($len > 0) trimHtml($child, $len, $out);
        }
        if ($len <= 0) return false;
    }
    return true;
}

$len = 100; // 目標寬度(中文算 2)
$trimed = '';
trimHtml($body, $len, $trimed);
echo $trimed;
?>

關鍵函數說明

  • mb_strwidth():按「寬度」計算長度,ASCII 1、中文 2,完美契合排版需求。
  • mb_strimwidth():同樣按寬度截取,自動補全尾部省略號,避免半個中文字符亂碼。
  • Tidy 會自動補全缺失標籤、修正巢狀,輸出的 HTML 結構必然合法。

替代方案:現代 DOMDocument + XPath

PHP 5.4+ 可用 DOMDocument::loadHTML() 搭配 DOMXPath 定位目標容器,再遍歷 childNodes 處理 DOMText 節點,邏輯同 Tidy 但無需額外擴展。注意 loadHTML() 會自動補全 <html><body>,需手動提取片段。

前端協作建議

若僅為展示截斷,CSS text-overflow: ellipsis 配合 display: -webkit-box; -webkit-line-clamp: 3; 可實現多行截斷,無需後端介入。但涉及「存入數據庫的純文本摘要」、「RSS/JSON 輸出」等場景,後端截取仍不可或缺。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved