【问题标题】:DOMDocument::validate() problemDOMDocument::validate() 问题
【发布时间】:2010-10-31 10:46:32
【问题描述】:

我对 PHP DOMDocument::validate() 有一个大问题,似乎系统地询问 DTD。

当我想验证一个 XHTML 文档 as explained here 时,这是一个大问题。

由于 w3.org 似乎拒绝来自 PHP 服务器的所有请求,因此无法使用此方法验证我的文档...

有什么解决办法吗?

提前致谢

[编辑] 这是一些精度:

/var/www/test.php:

<?php
$implementation = new DOMImplementation();

$dtd = $implementation->createDocumentType
       (
         'html',                                     // qualifiedName
         '-//W3C//DTD XHTML 1.0 Transitional//EN',   // publicId
         'http://www.w3.org/TR/xhtml1/DTD/xhtml1-'
           .'transitional.dtd'                       // systemId
       );

$document = $implementation->createDocument('', '', $dtd);

$document->validate();

[http://]127.0.0.1/test.php

Warning: DOMDocument::validate(http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd): failed to open stream: HTTP request failed! HTTP/1.0 403 Forbidden
 in /var/www/test.php on line 14

Warning: DOMDocument::validate(): I/O warning : failed to load external entity "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" in /var/www/test.php on line 14

Warning: DOMDocument::validate(): Could not load the external subset "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" in /var/www/test.php on line 14

相关问题:

【问题讨论】:

  • 不确定您的问题是什么。 DOMDocument::validate 根据加载文档的 DTD 验证文档。
  • 例如,如果我提供这个 DTD:w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd,当我调用 DOMDocument::validate() 时,PHP 会发送一个请求以获取该文件,但 w3.org 会系统地回复 403 Forbidden或 503 服务不可用,PHP 向我发送警告:未能加载外部实体“w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
  • 我明白了,是的。有一个错误打开:bugs.php.net/bug.php?id=48080
  • 我知道,而且它很老了,但是有什么解决办法吗? (与这个错误报告的不同之处在于 w3.org 故意停止允许来自 PHP 的请求,因为它的行为......)
  • 我添加了一条评论,提供您指向错误报告的 w3 博客文章的链接。也许这会让它得到更多的关注。顺便说一句,好问题。

标签: php xml xhtml domdocument


【解决方案1】:

就像在 cmets 中指出的那样,DOMDocument::validate 有一个 Bug/FeatureRequest 来接受 DTD 作为字符串:

您可以自己托管 DTD 并相应地更改 systemId,或者您可以为通过 libxml 完成的任何加载提供自定义流上下文。例如,提供 UserAgent 将绕过 W3C 的阻止。您也可以通过这种方式添加代理。见

例子:

$di = new DOMImplementation;
$dom = $di->createDocument(
    'html',
    'html',
    $di->createDocumentType(
        'html',
        '-//W3C//DTD XHTML 1.0 Transitional//EN',
        'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'
    )
);
$opts = array(
    'http' => array(
        'user_agent' => 'PHP libxml agent',
    )
);
$context = stream_context_create($opts);
libxml_set_streams_context($context);

var_dump($dom->validate());

这会输出

Warning: DOMDocument::validate(): Element html content does not follow the DTD, expecting (head , body), got  

Warning: DOMDocument::validate(): Element html namespace name for default namespace does not match the DTD 

Warning: DOMDocument::validate(): Value for attribute xmlns of html is different from default "http://www.w3.org/1999/xhtml" 

Warning: DOMDocument::validate(): Value for attribute xmlns of html must be "http://www.w3.org/1999/xhtml" 

bool(false)

【讨论】:

  • 非常有趣的解决方案!它不能解决没有缓存的系统请求的问题(对于 w3 来说不是很公平,但没有必要在每次提供文档时都验证它),但是我现在可以验证我的文档了。谢谢你^^
  • @GQyy 实际上,感谢您提出这个问题。它让我今天也学到了一些关于 DOM 的新知识;)
猜你喜欢
  • 1970-01-01
  • 2012-02-05
  • 1970-01-01
  • 1970-01-01
  • 2019-04-09
  • 1970-01-01
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多