【问题标题】:perl LibXML : validate doc against dtd, return booleanperl LibXML:根据 dtd 验证文档,返回布尔值
【发布时间】:2014-06-18 18:13:34
【问题描述】:

我正在尝试使用 LibXML 编写一个 perl 脚本,该脚本根据 dtd 验证文档并返回关于文档是否有效的布尔值。我希望能够在 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);
}

我在下面的脚本上尝试了许多变体,不使用那个子,将 parse 命令放在 eval 块中,等等。

根据this tutorial.,我在使用 filehandle->fd_open 时遇到了问题。我也不清楚 parse_file 函数根据cpan docs.返回什么

返回关于文档是否有效的布尔值的最佳方法是什么?

这是 xml 文档:

<?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)>

如果文件有效,脚本会按预期运行(它会在“子”之后到达该行),但是当我添加导致失败的标签时

<sometag/>

脚本打印出错误,但没有到达最后一行。 谢谢!

【问题讨论】:

  • sub isValid { my $file = shift; return eval { $parser-&gt;parse_file($file); 1 }; }

标签: xml perl libxml2


【解决方案1】:

The documentation 说:

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! 来检查结果。

【讨论】:

    【解决方案2】:

    XML::LibXML 不会根据 DTD 验证已解析的文档,除非设置了 validation 解析器选项:

    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 可能仍会在出现其他错误(未找到文件、文档格式不正确)时抛出异常。这取决于您的用例首选哪种行为。

    【讨论】:

      【解决方案3】:

      您可以使用 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;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-10-25
        • 2010-12-12
        • 1970-01-01
        • 2019-10-09
        • 1970-01-01
        • 2019-06-10
        • 2011-12-08
        • 1970-01-01
        相关资源
        最近更新 更多