如何使HTML5与DOMDocument一起使用?

时间:2012-05-23 01:52:35

标签: php html5 domdocument

我尝试使用DOMDocument解析HTML代码,对其进行更改,然后将其组合回我发送到输出的字符串。

但是有一些关于解析的问题,这意味着我发送给DOMDocument的内容并不总是以相同的形式返回:)

这是一个列表:

  1. 使用->loadHTML

    • 格式化我的文档,无论preserveWhitespaceformatOutput设置如何(在预先格式化的文本上丢失空格)
    • 当我拥有像<header><footer>等html5标签时,
    • 会给我错误。但是他们可以被压制,所以我可以忍受这个。
    • 产生不一致的标记 - 例如,如果我添加<link ... />元素(带有自闭标记),解析/ saveHTML后输出将为<link .. >
  2. 使用->loadXML

    • 对来自><style>代码的<script>实体进行编码:body > div变为body &gt; div
    • 所有标记都以相同方式关闭,例如<meta ... />变为<meta...></meta>;但这可以用正则表达式修复。
  3. 我没有尝试HTML5lib,但出于性能原因,我更喜欢DOMDocument而不是自定义解析器


    更新

    就像使用CDATA提到的Honeymonster修复了loadXML的主要问题。

    有没有什么方法可以阻止除了某个集合之外的所有空HTML标签的自动关闭,而不使用正则表达式?

    现在我有:

    $html = $dom->saveXML($node);
    
    $html = preg_replace_callback('#<(\w+)([^>]*)\s*/>#s', function($matches){
    
           // ignore only these tags
           $xhtml_tags = array('br', 'hr', 'input', 'frame', 'img', 'area', 'link', 'col', 'base', 'basefont', 'param' ,'meta');
    
           // if a element that is not in the above list is empty,
           // it should close like   `<element></element>` (for eg. empty `<title>`)
           return in_array($matches[1], $xhtml_tags) ? "<{$matches[1]}{$matches[2]} />" : "<{$matches[1]}{$matches[2]}></{$matches[1]}>";
    }, $html);
    

    哪个有效,但它也会替换CDATA内容,我不想要......

5 个答案:

答案 0 :(得分:13)

使用html5lib。它可以解析html5并生成DOMDocument。例如:

require_once '/path/to/HTML5/Parser.php';
$dom = HTML5_Parser::parse('<html><body>...');

Documentation

答案 1 :(得分:7)

不幸的是,或者可能幸运的是,domdocument旨在不尝试保留原始文档的格式。这是为了使所有元素保持相同的样式,使解析器的内部状态更容易管理。 Afaik大多数解析器将在内存中创建树表示,并且在用户请求之前不用担心文本格式。这就是为什么你的自闭标签输出带有单独的结束标签。好消息是没关系。

对于将<>转换为&lt;&gt;的样式标记和脚本标记,您可以通过使用推荐的cdata标记围绕相关元素的内容来避免转换:

<style>
  /*<![CDATA[*/
    body > div {
      width: 50%;
    }
  /*]]>*/
</style>

cdata声明周围的注释/* */允许不知道cdata部分的破坏客户端,而是将声明视为CSS代码。如果您仅在内部使用该文档,则可以省略/* */注释周围环境并仅使用cdata声明。如果您操作文档然后将其发送到浏览器而不检查以确保保留/* */注释,则可能会遇到上述损坏客户端的问题;我不确定domdocument是否会保留这些。

答案 2 :(得分:7)

如果您想支持HTML5,请不要触及DOMDocument。

目前最好的选择似乎是https://github.com/Masterminds/html5-php

以前最好的选择是https://github.com/html5lib/html5lib-php,但正如描述所说,它“目前尚未维护”。这是自2011年10月以来的状态,所以我不再屏住呼吸了。

我没有在制作中使用html5-php所以我无法提供任何真实世界的经验。我已经在生产中使用了html5lib-php,我会说它正确地解析了格式良好的文档但是它有一些简单的语法错误而出现意外错误。另一方面,似乎正确地实施了采用代理算法和其他一些奇怪的角落案例。如果仍然保留html5lib-php,我仍然会更喜欢它。但是,就目前情况而言,我更倾向于使用html5-php,并可能帮助修复那里的剩余错误。

答案 3 :(得分:3)

我尝试了html5lib和html5php,但都没有使用我提供的HTML。能够解析HTML的替代方法是:https://github.com/ivopetkov/html5-dom-document-php

主类扩展了PHP的本机DomDocument。

答案 4 :(得分:-6)

初始化domDocument时,请执行以下操作:

$dom = new DOMDocument(5, 'UTF-8');