1. 如果您根据 relax-ng 进行验证,则无需调用 $xml->setParserProperty(XMLReader::VALIDATE, true);
2. 请注意,$xml->isValid() 将返回当前活动节点的有效性(即使用 $xml->read() 定位的节点)。它不会一次性检查整个树的有效性,而是在逐步检查基础上进行。
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
XMLReader::isValid — 指示解析的文档是否有效
返回一个布尔值,指示正在解析的文档是否根据 DTD 或 XML 或 RelaxNG 模式当前有效。如果没有模式,并且未提供 DTD 验证选项,此方法将返回 false
。
此函数没有参数。
示例 #1 验证 XML
<?php
$xml = XMLReader::open('test.xml');
// 必须启用 validate 解析器选项才能
// 此方法正常工作
$xml->setParserProperty(XMLReader::VALIDATE, true);
var_dump($xml->isValid());
?>
注意: 这检查的是当前节点,而不是整个文档。
1. 如果您根据 relax-ng 进行验证,则无需调用 $xml->setParserProperty(XMLReader::VALIDATE, true);
2. 请注意,$xml->isValid() 将返回当前活动节点的有效性(即使用 $xml->read() 定位的节点)。它不会一次性检查整个树的有效性,而是在逐步检查基础上进行。
请注意,$xml->isValid() 仅返回当前活动节点的有效性,因此您必须遍历节点。
以下是如何针对 XSD 模式验证整个 XML 文件的示例
<?php
$xmlReader = new \XMLReader();
$xmlReader->open('./example.xml');
$xmlReader->setParserProperty(\XMLReader::VALIDATE, true);
$xmlReader->setSchema('./schema.xsd');
\libxml_use_internal_errors(true);
$msgs = [];
while ($xmlReader->read()) {
if (!$xmlReader->isValid()) {
$err = \libxml_get_last_error();
if ($err && $err instanceof \libXMLError) {
$msgs[] = \trim($err->message) . ' on line ' . $err->line;
}
}
}
if ($msgs) {
throw new \Exception("XML schema validation errors:\n - " . implode("\n - ", array_unique($msgs)));
}
?>
我在使用 isValid 方法与 xml2assoc 函数时遇到了一些问题。
我用这种方式来验证整个 xml 文件并将其放入一个关联数组中。
$xml = new XMLReader();
if (!$xml->xml($xml_string, NULL, LIBXML_DTDVALID)) {
echo "XML not valid: load error";
exit();
}
libxml_use_internal_errors(TRUE);
$xml_array = xml2assoc($xml);
$arErrors = libxml_get_errors();
$xml_errors = "";
foreach ($arErrors AS $xmlError) $xml_errors .= $xmlError->message;
if ($xml_errors != "") {
echo "XML not valid: ".$xml_errors;
exit();
}
// 都正常
此评论仅部分正确
"isValid() 始终返回 false,除非您通过 $reader->setParserProperty(XMLReader::VALIDATE, true); 启用验证检查"
这启用了 DTD 检查,但您也可以使用 RelaxNG 检查(参见 setRelaxNGSchema() 和 setRelaxNGSchemaSource())。
此外,这也不正确
"如果您只需要检查 XML 文件是否格式正确,将它成功加载到 XMLReader 对象中通常就足够了"
这还不够。拉取解析器对流进行操作,如果您有一个足够大的文件,它们将无法知道它是否格式正确,直到它被读到最后。如果您需要知道它是否格式正确或/和有效,请将其读到最后或验证错误(如果您不在乎内容,可以使用 next() 进行快速读取)。