我正在尝试使用LibXML编写一个perl脚本,该脚本根据dtd验证文档,并返回一个关于doc是否有效的布尔值。我希望能够在xml文件的文件夹上运行脚本,报告哪些是有效的,哪些不是,并记录那些无效的错误。
我所拥有的脚本确实会验证文档,但它会在第一个无效的文档中停止。
use strict;
use warnings;
no warnings 'uninitialized';
use XML::LibXML;
use IO::Handle;
# script to test dtd validity against test xml instance
my $instance = 'C:\jason\code\perl\dev\well-formed-test\family-instance1.xml';
$instance =~ s#\\#/#g;
print "about to test $instance \nagainst dtd\n\n";
my $parser = XML::LibXML->new();
$parser->validation(1);
print "here we go...\n";
print "test : ", &isValid( $instance );
print "after sub.\n";
sub isValid {
my $file = shift;
return $parser->parse_file($instance);
}
我在下面的脚本上尝试了很多变体,没有使用那个sub,将parse命令放在eval块中等等。
我根据this tutorial.使用filehandle-> fd_open时出现问题。我也不清楚parse_file函数根据cpan docs.
返回什么返回布尔值以确定doc是否有效的最佳方法是什么?
这是xml doc:
<?xml version="1.0"?>
<!DOCTYPE family SYSTEM "family.dtd">
<family>
<member gender="female">
<firstName>Sally</firstName>
<lastName>Smith</lastName>
</member>
<member gender="male">
<firstName>Bernie</firstName>
<lastName>Smith</lastName>
</member>
<member gender="female">
<firstName>Anna</firstName>
<lastName>Smith-Jones</lastName>
</member>
</family>
和dtd:
<?xml version="1.0" encoding="UTF-8"?>
<!ELEMENT family (member+)>
<!ELEMENT member (firstName, lastName)>
<!ATTLIST member gender (male|female) 'male'>
<!ELEMENT firstName (#PCDATA)>
<!ELEMENT lastName (#PCDATA)>
脚本按预期运行(如果文件有效,它会在'sub'之后到达该行),但是当我添加导致失败的标记时
<sometag/>
脚本打印出错误,但不会到达最后一行。 谢谢!
答案 0 :(得分:2)
All of the functions listed below will throw an exception if the document is invalid.
To prevent this causing your program exiting, wrap the call in an eval{} block
和parse_file是其中一项功能。
使用eval,您可以预期S@
或S!
来检查结果。
答案 1 :(得分:1)
您可以使用File :: Find处理多个文件。
use strict;
use warnings;
use File::Find;
use XML::Parser;
my $parser = XML::Parser->new();
find({
wanted => \&wanted,
no_chdir => 1,
follow_fast => 1,
},
$ARGV[0],
);
sub wanted {
return unless -f and m/\.xml$/i;
eval {
$parser->parsefile($File::Find::name);
}; if( $@ ){
printf STDERR "Not a valid XML document: %s\n", $File::Find::name;
} else {
printf STDERR "A valid XML document: %s\n", $File::Find::name;
}
}
答案 2 :(得分:1)
validation
解析器选项,否则 XML::LibXML
将不会针对DTD验证已解析的文档:
my $parser = XML::LibXML->new(
validation => 1,
);
如果解析了无效文档,这将抛出异常。将呼叫包裹在parse_file
块中的eval
以捕获异常。
my $doc = eval { $parser->parse_file($filename) };
if ( ! $doc ) {
print("Can't parse $filename: $@");
}
或者,您可以在不进行验证的情况下解析文档,然后使用is_valid
方法进行验证:
my $doc = $parser->parse_file('filename.xml');
if ( ! $doc->is_valid ) {
# Document does not validate...
}
在这种情况下,如果发现其他错误(文件未找到,文档格式不正确),parse_file
可能仍会抛出异常。这取决于您的用例,首选行为。