php整洁奇怪的行为

时间:2012-07-26 13:14:20

标签: php html tidy htmltidy

我正在使用php的整洁库来“清理和修复”来自用户输入的一些HTML。

一切正常,但我遇到了一个问题,我无法弄清楚它的原因是什么。我的代码是这样的:

$tidy = new tidy();

    $tidy_options = array(
        'hide-comments' => true,'tidy-mark' => false, 'indent' => false,
        'new-blocklevel-tags' => 'article,footer,header,hgroup,output,progress,section,video',
        'new-inline-tags' => 'audio,details,time,ruby,rt,rp',
        'drop-empty-paras' => false, 
        'doctype' => '<!DOCTYPE HTML>',
        'sort-attributes' => 'none', 'vertical-space' => false,
        'output-xhtml' => true,'wrap' => 180,
        'wrap-attributes' => false,
        'break-before-br' => false,
        'show-body-only' => true
        );
$data = $tidy->repairString($data, $tidy_options, 'UTF8');
echo $data;

这适用于所有类型的输入,除非我正在尝试使用html来嵌入swf文件 所以,我试试这段代码:

<object data="http://the_swf_file_url" type="application/x-shockwave-flash" width="853" height="520"> 
    <param name="movie" value="http://the_swf_file_url"> 
</object>

但是repairString对所有这些进行了条纹处理,并返回一个空字符串 最奇怪的是:
- 如果我输入一些文字和上面的内容,所以输入就像Hello world<object...>...</object>那样它可以正常工作。
- 或者如果我指定'show-body-only' => false它也可以正常工作!

任何线索为什么会发生这种情况? 提前谢谢。

编辑:尝试了pankar的建议,将preserve-entities设置为true但没有运气......

2 个答案:

答案 0 :(得分:6)

问题是您正在尝试处理HTML 片段

执行此操作时,文档的其余部分推断。如果您将配置保留为默认配置,并输出仅包含一段文字的整洁文档,您将看到DOCTYPEhtmlheadbody标记没有给它。它推断出这些标签必须存在。

这里的问题是HTML specification regarding objects表示:

  

OBJECT元素也可能出现在HEAD元素的内容中。

当推断出片段的位置时,它会将其置于可以发生的第一个位置。这意味着整洁会将其放在head标记中。

show-body-only影响您的输出的原因是因为您的片段没有放在body中。

<小时/> 然而当您添加一些文字时,它会强制您的代码段进入body标记。这是因为head标记中的原始文字不允许。因此,片段的逻辑推断位置位于body

在我看来,您可以选择的最佳选择是将所有代码片段注入“模板”文档,然后再将其解析出来。您可以使用DOMDocument轻松地完成此操作。

第二个解决方案是注入一个哨兵值,然后在仅显示身体时再次剥离。

____MY_MAGIC_TOKEN____
<object ...></object>

之后你可以再把它剥掉。

答案 1 :(得分:3)

尝试将configuration选项preserve-entities指定为true(默认为false)。

修改

秒(更彻底)的想法。这是预期的行为。通过将show-body-only设置为true,您告诉tidy输出xhtml已处理文档的正文部分。

此设置实际上会忽略文档<head>中的所有内容。 <object>组件是<head>的子组件。您只需指定

即可验证

$data = "<title>My Site</title>"

输出再次为空白。

您尝试将带前缀的文本放到<object>标记只是简单的诡计,因为它认为这些数据必须作为页面正文的一部分进行处理才能显示。

希望这次能帮到更多。