【问题标题】:Fixing unclosed HTML tags修复未关闭的 HTML 标签
【发布时间】: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 标签导致主要布局问题

标签: php html dom


【解决方案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】:

    有很多方法可以使用:

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

    【讨论】:

    • 不错,php tidy 真的很简单。
    • tidy 非常适合简单、快速和肮脏。呃,我的意思是清洁。 HTML Purifier 是一个野兽,非常适合复杂的规则集。
    猜你喜欢
    • 1970-01-01
    • 2011-03-04
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 2013-03-31
    • 1970-01-01
    • 2012-08-03
    • 1970-01-01
    相关资源
    最近更新 更多