PHP XMLReader检查(大型)XML文件语法



是否有方法对XML文件是否具有有效语法进行"简单"检查?我使用的是PHP的XMLReader。

我现在的处境是:我有多个XML文件,它们变化很大。因此,我无法对DTD文件进行XMLReader::isValid((检查。但这并不需要persé。我只想知道语法是否正常。因为有时XML文件在末尾就被破坏了。在对节点进行迭代之前,我想检查一下这一点。

另一件事是,有些文件的大小超过2GB,所以我无法在不使用大量内存的情况下进行简单的DOM检查。

我该怎么办?

当然,我尝试了评论中建议的选项,这很好,但只适用于小文件:

$dom = new DOMDocument;
if(!@$dom->load('example.xml')){ die("syntax error"); }

较大的文件会占用所有内存并崩溃。

当我在一个简单的XML阅读器程序中打开一个大的XML文件时;第一对象XML编辑器";,它在几毫秒内显示了语法错误行(30GB xml文件显示语法错误行需要1.7秒(。PHP XMLReader应该可以实现这样的功能吧?

编辑:目前我将使用上面的选项,但首先要检查文件大小。如果低于某个大小(仍在测试最大大小(,则检查语法。对于较大的文件,我将按照@IMSoP的建议,使用第三方工具和命令行检查构建一个选项。如果我找到一个稳定的解决方案,我会更新这个。

Edit2Progman的想法(答案如下(是迄今为止我见过的最好的。唯一的问题是它将迭代整个XML文件。因此,处理已经需要相当长的时间,现在将翻一番。我希望有一个快速的验证选项,但也许这根本不可能。我等了一会儿,看看是否还有其他选择,但除此之外,我认为我应该接受Progman答案作为大文件的最佳选择。

编辑3:解决方案好吧,我刚刚对Progman的解决方案进行了微调,使其在不使用set_error_handler选项的情况下使用。因为我已经在使用它来处理自定义错误,所以最适合我的是通过设置libxml_use_internal_errors(true(标志来抑制错误,然后像下面这样检查错误,简称:

libxml_use_internal_errors(true);
$xml = new XMLReader();
$xml->open("large.xml");
while($xml->read());
foreach (libxml_get_errors() as $error) {
print_r($error);
}

您可以使用XMLReader类来读取XML内容,而无需将整个内容加载到内存中。使用read()方法读取XML文档中的每个节点。当由于错误而无法读取当前节点时,此方法将发出警告。警告可能看起来像这样:

PHP警告:XMLReader::read((:file.xml:9183:语法分析器错误:xmlParseEntityRef:在file.PHP的第X行上没有名称

您可以使用set_error_handler()对收到的任何警告做出反应,查看其他问题,如PHP收到警告和错误消息?。使用一个简单的while()循环读取XML文档的每个节点,直到到达末尾。检查以下概念验证:

<?php
$xml = XMLReader::open('test.xml');
$warningCount=0;
set_error_handler(function($errno, $errstr, $errfile, $errline){
global $warningCount;
$warningCount++;
});
while($xml->read());
echo "All finen";
var_dump($warningCount);

如果没有警告(或任何其他错误类型(,则变量$warningCount将为0,如果有警告,则变量将大于0,很可能来自read()调用。

最新更新