10

在 PHP 中,我试图使用我的应用程序指定的 DTD 验证 XML 文档,而不是通过外部获取的 XML 文档。DOMDocument 类中的 validate 方法似乎只使用 XML 文档本身指定的 DTD 进行验证,因此这不起作用。

这可以做到吗?如何,或者我必须将我的 DTD 转换为 XML 模式,以便我可以使用 schemaValidate 方法?

(这似乎在Validate XML using a custom DTD in PHP中被问过,但没有正确答案,因为该解决方案仅依赖于目标 XML 指定的 DTD)

4

2 回答 2

17

注意:XML 验证可能会受到Billion Laughs攻击和类似的 DoS 攻击。

这基本上就是 rojoca 在他的评论中提到的:

<?php

$xml = <<<END
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE foo SYSTEM "foo.dtd">
<foo>
    <bar>baz</bar>
</foo>
END;

$root = 'foo';

$old = new DOMDocument;
$old->loadXML($xml);

$creator = new DOMImplementation;
$doctype = $creator->createDocumentType($root, null, 'bar.dtd');
$new = $creator->createDocument(null, null, $doctype);
$new->encoding = "utf-8";

$oldNode = $old->getElementsByTagName($root)->item(0);
$newNode = $new->importNode($oldNode, true);
$new->appendChild($newNode);

$new->validate();

?>

这将根据bar.dtd.

您不能只调用$new->loadXML(),因为这只会将 DTD 设置为原始,并且doctypeDOMDocument 对象的属性是只读的,因此您必须将根节点(其中包含所有内容)复制到新的 DOM 文档。

我自己只是尝试过,所以我不完全确定这是否涵盖了所有内容,但它绝对适用于我的示例中的 XML。

当然,快速而简单的解决方案是首先获取 XML 作为字符串,搜索并用您自己的 DTD 替换原始 DTD,然后加载它。

于 2009-08-13T22:08:04.147 回答
1

我认为只有 XSD 才有可能,请参阅: http:
//php.net/manual/en/domdocument.schemavalidate#62032

于 2009-08-23T19:30:28.413 回答