针对PHP中给定DTD的XML验证

时间:2009-08-13 19:46:56

标签: php xml validation dtd

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

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

(这似乎是在Validate XML using a custom DTD in PHP中提出但没有正确答案,因为解决方案只依赖于目标XML规定的DTD)

2 个答案:

答案 0 :(得分:16)

注意:XML validation可能受到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设置为原始,并且DOMDocument对象的doctype属性是只读的,因此您必须复制根节点(包含其中的所有内容)到新的DOM文档。

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

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

答案 1 :(得分:1)

我认为这只适用于XSD,请参阅:
http://php.net/manual/en/domdocument.schemavalidate#62032