修复未关闭的 HTML 标签

Posted

技术标签:

【中文标题】修复未关闭的 HTML 标签【英文标题】:Fixing unclosed HTML tags 【发布时间】:2012-01-19 23:39:57 【问题描述】:

我正在处理一些博客布局,我需要为每篇文章(比如最近的 15 篇)创建一个摘要以显示在主页上。现在我使用的内容已经被 Textile 库格式化为 html 标签。现在,如果我使用 substr 获取帖子的第 500 个字符,我面临的主要问题是如何关闭未关闭的标签。

例如

<div>.......................</div>
<div>...........
     <p>............</p>
     <p>...........| 500 chars
     </p>
<div>  

我得到的是两个未闭合的标签

, p 不会造成太大的麻烦,但 div 只是弄乱了整个页面布局。那么有什么建议如何跟踪开始标签并手动关闭它们吗?

【问题讨论】:

将开始标签推入堆栈,并弹出关闭的标签。考虑自闭合标签。当您消耗了足够多的文本字符后,将剩余的标签序列化为结束标签,后进先出。 有类似的讨论与使用 php here 进行 DOM 操作有关。 是的@alex 我想到了,尝试实现它有什么我可以效仿的例子吗? &lt;p&gt; 标签不需要关闭,除非在 XHTML 中。我们假设您使用的是 XHTML 吗? 不,我正在使用 html。正如我所说&lt;p&gt; 很好.. 它们是自动关闭的,但它的 div 标签导致主要布局问题 【参考方案1】:

您可以使用 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 的长度,如果不够长,则跳过附加“更多”链接。

【讨论】:

【参考方案2】:

正如 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 中,与 PHP Tidy 相反。

【讨论】:

我很感激这是一个简单的答案,如果您正在处理一个简单的问题,并且不希望安装任何额外库的开销。就我而言,我让用户从电子邮件和 Word 中粘贴不完整的 HTML,这解决了它。 这正是我正在寻找的那种干净的答案。非常感谢。【参考方案3】:

有很多方法可以使用:

    使用适当的 HTML 解析器,例如 DOMDocument 使用PHP Tidy修复未关闭的标签 有些人会建议HTML Purifier

【讨论】:

不错,php tidy 真的很简单。 tidy 非常适合简单、快速和肮脏。呃,我的意思是清洁。 HTML Purifier 是一个野兽,非常适合复杂的规则集。

以上是关于修复未关闭的 HTML 标签的主要内容,如果未能解决你的问题,请参考以下文章

springboot 1.5.2 thymeleaf 标签未关闭异常解决办法

在 VS Code 中保存时关闭自动关闭的 HTML 标签?

PHP 关闭未关闭的标签

播放 HTML5 音频标签,但控件未按预期工作

从 xhtml 文档中删除未关闭的打开 <p> 标签

使用 jinja 标签在 html 标签内使用 if 条件