针对 PHP 中给定 DTD 的 XML 验证

发布于 2024-08-01 14:04:07 字数 372 浏览 6 评论 0原文

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

这可以完成吗?如何完成?或者我是否必须将 DTD 转换为 XML 模式,以便可以使用 schemaValidate 方法?

(这似乎在 在 PHP 中使用自定义 DTD 验证 XML 中被问到 但没有正确答案,因为该解决方案仅依赖于目标 XML 指定的 DTD)

In PHP, I am trying to validate an XML document using a DTD specified by my application - not by the externally fetched XML document. The validate method in the DOMDocument class seems to only validate using the DTD specified by the XML document itself, so this will not work.

Can this be done, and how, or do I have to translate my DTD to an XML schema so I can use the schemaValidate method?

(this seems to have been asked in Validate XML using a custom DTD in PHP but without correct answer, since the solution only relies on DTD speicified by the target XML)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

潇烟暮雨 2024-08-08 14:04:07

注意: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 设置为原始数据,并且读取 DOMDocument 对象的 doctype 属性-only,因此您必须将根节点(及其中的所有内容)复制到新的 DOM 文档。

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

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

Note: XML validation could be subject to the Billion Laughs attack, and similar DoS vectors.

This essentially does what rojoca mentioned in his comment:

<?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();

?>

This will validate the document against the bar.dtd.

You can't just call $new->loadXML(), because that would just set the DTD to the original, and the doctype property of a DOMDocument object is read-only, so you have to copy the root node (with everything in it) to a new DOM document.

I only just had a go with this myself, so I'm not entirely sure if this covers everything, but it definitely works for the XML in my example.

Of course, the quick-and-dirty solution would be to first get the XML as a string, search and replace the original DTD by your own DTD and then load it.

花期渐远 2024-08-08 14:04:07

我认为这只能通过 XSD 实现,请参阅:
http://php.net/manual/en/domdocument.schemavalidate#62032

I think that's only possible with XSD, see:
http://php.net/manual/en/domdocument.schemavalidate#62032

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文