首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何让HTML5与DOMDocument协同工作?

如何让HTML5与DOMDocument协同工作?
EN

Stack Overflow用户
提问于 2012-05-23 09:52:35
回答 6查看 16.3K关注 0票数 20

我正在尝试用DOMDocument解析HTML代码,对它做一些修改,然后把它组装成一个字符串,然后发送到输出。

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

下面是一个列表:

使用->loadHTML

- formats my document regardless of the `preserveWhitespace` and `formatOutput` settings (loosing whitespaces on preformatted text)
- gives me errors when I have html5 tags like `<header>`, `<footer>` etc. But they can be supressed, so I can live with this.
- produces inconsistent markup - for example if I add a `<link ... />` element (with a self-closing tag), after parsing/saveHTML the output will be `<link .. >`

使用->loadXML

- encodes entities like `>` from `<style>` or `<script>` tags: `body > div` becomes `body &gt; div`
- all tags are closed the same way, for example `<meta ... />` becomes `<meta...></meta>`; but this can be fixed with an regex.

我没有尝试HTML5lib,但出于性能原因,我更喜欢DOMDocument而不是自定义解析器

更新:

因此,就像前面提到的蜜罐一样,使用CDATA解决了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内容中做替换,这是我不想要的…

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2012-05-29 03:04:37

不幸的是,或者可能是幸运的是,domdocument被设计为不尝试保留原始文档的格式。这是为了使解析器的内部状态更易于管理,方法是使所有元素保持相同的样式。Afaik大多数解析器会在内存中创建一个树表示,并且不会担心文本格式,直到用户请求这样做。这就是为什么你的自闭合标签会输出单独的闭合标签。好消息是,这并不重要。

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

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

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

票数 7
EN

Stack Overflow用户

发布于 2012-05-23 12:57:38

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

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

Documentation

票数 14
EN

Stack Overflow用户

发布于 2016-04-26 20:41:04

如果您想要支持HTML5,请完全不要接触DOMDocument。

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

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

我还没有在生产中使用过html5-php,所以我不能提供任何关于这方面的真实经验。我在生产中使用过html5lib-php,我想说它可以正确地解析格式良好的文档,但是它有一些意外的错误,只有一些简单的语法错误。另一方面,它似乎正确地实现了领养代理算法和其他一些奇怪的角落情况。如果html5lib-php还在维护,我还是更喜欢它。然而,就目前的情况而言,我更喜欢使用html5-php,并可能帮助修复那里的剩余bug。

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10712503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档