2012-02-20 102 views
0

给定一个HTML字符串的第一个字符“n”,我想具有以下属性返回修改后的字符串:使用PHP的DOM实现返回一个HTML字符串

  1. 第一ň的字符文本内容(除了HTML标签)应该保留。
  2. 之后的元素n字符已被符合应完全删除。
  3. 如果n字符不在一个元素的末尾,则相同元素中的文本不应保留。
  4. 之前的元素标签应保留字符。

基本上,我只是想返回HTML的缩短版本,没有DOM结构被打断,并且仅基于文本内容的长度。

使用PHP的DOM实现,看起来这会过于复杂。使用模式匹配并不理想,因为修改过的字符串的条件可能随时间而改变,并且每次都需要重写。

我错过了一个更简单的方法吗?提前致谢。

+0

因此,忽略html标签,你想要的第一个n个字符的内容? 1个元素?整个文件的? – Zac 2012-02-20 17:37:49

+0

我想要整个文档的前n个字符的内容,但不要删除标签(但不要将标签作为n个字符的一部分计数)。 – melkamo 2012-02-20 18:10:36

回答

1

“使用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); 

UPDATE

根据您的评论,这里有一个简单的方法来计算节点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(); 
+0

谢谢,但这只是文本内容,删除了所有标签。 – melkamo 2012-02-20 18:12:08

+0

@melkamo我以为这就是你要找的。如果你能够澄清你想要的内容,我很乐意更新。 *“文本内容的前n个字符(保留HTML标签)应保留。“* – rdlowrey 2012-02-20 18:13:17

+0

对不起,我不明白,我试图说明修改后的字符串和原始字符串之间的区别,并不是说删除标签,换句话说,截断文本的节点应该仅基于文本的长度但是标签应该保留 – melkamo 2012-02-20 18:16:18