修复未闭合的HTML标签

15
我正在设计一些博客布局,需要创建每篇文章的摘要(最新的15篇文章)以在主页上展示。现在我使用的内容已经通过textile库格式化为HTML标签。现在如果我使用substr获取文章的前500个字符,那么我面临的主要问题是如何关闭未关闭的标签。
<div>.......................</div>
<div>...........
     <p>............</p>
     <p>...........| 500 chars
     </p>
<div>  

我得到的是两个未闭合的标签 <p> 和 <div>,p标签不会造成太多麻烦,但是div标签会影响整个页面布局。所以有什么建议来跟踪开放标签并手动关闭它们或其他方法吗?


将开标签推入堆栈,并弹出已关闭的标签。考虑自闭合标签。当您消耗了足够的文本字符时,将剩余的标签序列化为关闭标签,后进先出。 - alex
这里有一个相关的讨论,涉及使用PHP进行DOM操作 链接 - moey
是的 @alex 我想到了,正在尝试实现它。有没有我可以参考的例子? - satin
除非在XHTML中,否则<p>标签不需要关闭。我们假设您正在使用XHTML吗? - BoltClock
不,我正在使用HTML。就像我说的那样,<p> 标签没问题,因为它们会自动关闭,但是 <div> 标签会导致主要布局问题。 - satin
3个回答

18

1
很好,PHP Tidy 真的很简单。 - Kristian Rafteseth
1
Tidy非常适合进行简单、快速和粗略的清理工作。呃,我的意思是清洁。HTML Purifier是一个强大的工具,非常适合处理复杂的规则集。 - zmonteca

18

如ajreal所说,DOMDocument是一个解决方案。

例子:

$str = "
<html>
 <head>
  <title>test</title>
 </head>
 <body>
  <p>error</i>
 </body>
</html>
";

$doc = new DOMDocument();
@$doc->loadHTML($str);
echo $doc->saveHTML();

优点:与 PHP Tidy 相反,Tidy 扩展是 PHP 的本地扩展。


如果你只是处理一个简单的问题,不想安装任何额外的库,那么这个答案很简单。在我的情况下,用户从电子邮件和Word中复制了不完整的HTML代码,这个方法解决了这个问题。 - Richard
那正是我在寻找的干净明了的答案。非常感谢你。 - lapin
我不得不使用 @$doc->loadHTML(utf8_decode($html)),但感谢您提供这个有用的答案。 - Entretoize

3

您可以使用DOMDocument来完成此操作,但要注意字符串编码问题。此外,您需要使用完整的HTML文档,然后提取所需的组件。以下是一个示例:

function make_excerpt ($rawHtml, $length = 500) {
  // append an ellipsis and "More" link
  $content = substr($rawHtml, 0, $length)
    . '&hellip; <a href="/link-to-somewhere">More &gt;</a>';

  // Detect the string encoding
  $encoding = mb_detect_encoding($content);

  // pass it to the DOMDocument constructor
  $doc = new DOMDocument('', $encoding);

  // Must include the content-type/charset meta tag with $encoding
  // Bad HTML will trigger warnings, suppress those
  @$doc->loadHTML('<html><head>'
    . '<meta http-equiv="content-type" content="text/html; charset='
    . $encoding . '"></head><body>' . trim($content) . '</body></html>');

  // extract the components we want
  $nodes = $doc->getElementsByTagName('body')->item(0)->childNodes;
  $html = '';
  $len = $nodes->length;
  for ($i = 0; $i < $len; $i++) {
    $html .= $doc->saveHTML($nodes->item($i));
  }
  return $html;
}

$html = "<p>.......................</p>
  <p>...........
    <p>............</p>
    <p>...........| 500 chars";

// output fixed html
echo make_excerpt($html, 500);

输出:

<p>.......................</p>
  <p>...........
    </p>
<p>............</p>
    <p>...........| 500 chars… <a href="/link-to-somewhere">More &gt;</a></p>

如果您正在使用WordPress,则应将substr()调用包装在对wpautop的调用中 - wpautop(substr(...))。您可能还希望测试传递给函数的$rawHtml的长度,并在不足够长时跳过附加“更多”链接。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接