PHP中用RelaxNG(RNG)验证XML如何显示全部错误?
PHP RelaxNG验证显示所有错误的解决方案
问题背景
使用PHP的DOMDocument::relaxNGValidate函数验证XML与RelaxNG(RNG)schema时,仅能捕获并显示第一个验证错误,无法获取全部错误信息。
现有代码(仅显示第一个错误)
<?php libxml_use_internal_errors(true); // 创建新的DOMDocument实例 $doc = new DOMDocument; // 加载XML文件 $doc->load('test.xml'); // 依据RNG验证XML if ($doc->relaxNGValidate('test.rng')) { echo "文件验证通过。"; } else { $errors = libxml_get_errors(); foreach ($errors as $error) { echo "错误:" . $error->message . "(行号 " . $error->line . ")\n"; } libxml_clear_errors(); } libxml_use_internal_errors(false); ?>
测试用资源
测试XML文件(test.xml)
<?xml version="1.0"?> <collegqe> <rollno> <name>John Smith</name> <subject>Web</subject> </rollno> <rollno> <nameq>John Doe</nameq> <subject>CSE</subject> </rollno> </collegqe>
RNG Schema文件(test.rng)
<grammar xmlns="http://relaxng.org/ns/structure/1.0"> <start> <element name="college"> <zeroOrMore> <element name="rollno"> <element name="name"> <text/> </element> <element name="subject"> <text/> </element> </element> </zeroOrMore> </element> </start> </grammar>
问题原因
DOMDocument::relaxNGValidate依赖的libxml库默认会在遇到第一个验证错误时中止流程,因此仅能捕获到首个错误。要获取全部错误,需开启RelaxNG全量检查模式。
修复后的代码(显示所有错误)
<?php libxml_use_internal_errors(true); // 配置流上下文,开启RelaxNG全量检查 $context = stream_context_create([ 'relaxng' => [ 'full_check' => true ] ]); libxml_set_streams_context($context); // 创建DOMDocument并加载XML $doc = new DOMDocument; $doc->load('test.xml'); // 执行验证并输出所有错误 if ($doc->relaxNGValidate('test.rng')) { echo "文件验证通过。"; } else { $errors = libxml_get_errors(); foreach ($errors as $error) { echo "错误:" . trim($error->message) . "(行号 " . $error->line . ")\n"; } libxml_clear_errors(); } libxml_use_internal_errors(false); ?>
验证效果
修复后会输出所有验证错误:
- 错误:Element collegqe does not match expected element college(行号 2)
- 错误:Element nameq does not match expected element name(行号 8)
关于转换为XSD的疑问
无需将RNG转换为XSD即可解决问题。开启RelaxNG全量检查是更直接高效的方案。若因其他需求需转换,可使用专门工具(如trang)完成格式转换,但这会增加额外操作步骤。
内容的提问来源于stack exchange,提问作者Pick
相关产品推荐
相关产品推荐

