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');
// 必須啟用驗證解析器選項才能
// 使此方法正常運作
$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)));
}
?>
我在使用 xml2assoc 函式搭配 isValid 方法時遇到了一些問題。
我使用這種方式來驗證整個 XML 檔案並將其放入關聯陣列中。
$xml = new XMLReader();
if (!$xml->xml($xml_string, NULL, LIBXML_DTDVALID)) {
echo "XML 無效:載入錯誤";
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 無效: ".$xml_errors;
exit();
}
//一切正常
這則評論僅部分正確
「除非您透過 $reader->setParserProperty(XMLReader::VALIDATE, true); 啟用有效性檢查,否則 isValid() 一律會傳回 false。」
這會啟用 DTD 檢查,但您也可以使用 RelaxNG 進行檢查(請參閱 setRelaxNGSchema() 和 setRelaxNGSchemaSource())。
而且,這是不正確的
「如果您只需要檢查 XML 檔案格式是否正確,成功載入到 XMLReader 物件通常就足夠了。」
這是不夠的。拉式解析器(Pull Parser)在串流上運作,如果您有一個很大的檔案,它們在讀取到檔案結尾之前不會知道它是否格式良好。如果您需要知道它是否格式良好或/且有效,請將其讀取到結尾或驗證錯誤(如果您不關心內容,可以使用 next() 快速讀取)。