【问题标题】:Fix HTML fragment修复 HTML 片段
【发布时间】:2011-06-01 11:28:41
【问题描述】:

我正在尝试学习如何使用PHP's DOM functions。作为练习,我想修复无效的 HTML 片段。到目前为止,我已经能够生成一个完整文档

<?php

$fragment = '<div style="font-weight: bold">Lorem ipsum <div>dolor sit amet,
    <strong><em class=foo>luptate</strong></em>. Excepteur proident,
    <div class="bar">sunt in culpa</div> officia est laborum.';

$doc = new DOMDocument;
libxml_use_internal_errors(TRUE);
$doc->loadHTML($fragment);
libxml_use_internal_errors(FALSE);
$doc->formatOutput = TRUE;
echo $doc->saveHTML();

?>

... 打印:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><div style="font-weight: bold">Lorem ipsum <div>dolor sit amet,
    <strong><em class="foo">luptate</em></strong>. Excepteur proident,
    <div class="bar">sunt in culpa</div> officia est laborum.</div>
</div></body></html>

我的问题:

  1. 有没有办法只打印与原始片段对应的 HTML?
  2. 是否有更适合此类任务的内置库?

【问题讨论】:

    标签: php html dom html-parsing


    【解决方案1】:

    您可以运行一个函数来替换您不希望总是出现的部分,例如:

    $result = $doc->saveHTML();
    $result = str_replace('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd"><html><body>', '', $result);
    $result = str_replace('</body></html>', '', $result);
    

    你总是可以试试这个课程:

    http://www.barattalo.it/html-fixer/

    这显然会像这样简单:

    $dirty_html = ".....bad html here......";
    
    $a = new HtmlFixer();
    $clean_html = $a->getFixedHtml($dirty_html);
    

    这完全取决于您将如何处理这些信息。

    【讨论】:

    • 使用字符串函数处理最终输出有点超过了使用 DOM 的目的;-) 感谢您提供链接,但正如我所说,这只是一个练习,所以我可以学习。
    【解决方案2】:

    嗯,PHP >= 5.1 显然也有一个DocumentFragment,它有一个appendXML 函数:http://php.net/manual/en/domdocumentfragment.appendxml.php。也许你可以使用它?我不确定它是否有自己的字符串表示,但谁知道呢。

    编辑:

    好吧,那行不通:)

    不过,您可以做的是直接使用 SimpleXML,或者通过创建DOMElement 然后使用simplexml_import_dom($domelement)-&gt;asXML()http://php.net/manual/en/function.simplexml-import-dom.php。祝你好运! :)

    【讨论】:

    • 是的,DocumentFragment 看起来很有希望,但我也无法使用它。 SimpleXML 会根据我的判断生成完整的文档。
    【解决方案3】:

    这应该可以,但有点难看

    $doc->loadHTML($fragment);
    echo simplexml_import_dom( $doc->getElementsByTagName('div')->item(0) )->asXML();
    

    输出:

    <div style="font-weight: bold">Lorem ipsum <div>dolor sit amet,
      <strong><em class="foo">luptate</em></strong>. Excepteur proident,
        <div class="bar">sunt in culpa</div> officia est laborum.</div></div>
    

    稍微优雅一点

    $xpath   = new DOMXPath($doc);
    $query   = '/html/body/*';        <-- always <html><body>...
    $entries = $xpath->query($query);
    foreach ($entries as $entry)
    {
      echo simplexml_import_dom($entry)->asxml();
    }
    

    【讨论】:

    • 我认为没有直接的机制(例如,DOMNode::outerHTML() 方法),您必须自己编写。第一种方法采用特定的结构,但第二种方法效果很好(尽管我将一些新行字符转换为 HTML 实体,这并不是严格错误,但它很丑)。
    • 同意,这可能有帮助,也可能没有帮助preserveWhiteSpace
    【解决方案4】:

    似乎最新的 PHP 版本终于实现了这个:

    How to return outer html of DOMDocument?

    这样我们就可以做到:

    if( version_compare(PHP_VERSION, '5.3.6', '>=') ){
        $body = $dom->documentElement->firstChild;
        if( $body->hasChildNodes() ){
            foreach($body->childNodes as $node){
                echo $dom->saveHTML($node);
            }
        }
    }
    

    ...或者这个:

    if( version_compare(PHP_VERSION, '5.3.6', '>=') ){
        $body = $dom->getElementsByTagName('body')->item(0);
        if( $body->hasChildNodes() ){
            foreach($body->childNodes as $node){
                echo $dom->saveHTML($node);
            }
        }
    }
    

    太糟糕了,我们仍然需要一个针对旧版本的丑陋解决方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-02-25
      • 1970-01-01
      • 2015-09-15
      • 2015-04-30
      • 2022-01-10
      • 2014-02-07
      • 1970-01-01
      • 2020-10-19
      相关资源
      最近更新 更多