1

我在为 xml 标签解析文件时遇到问题,问题是文件可以有许多 xml 标签,或者它可能只有一个。我已经尝试通过正则表达式和使用 LibXML 来做到这一点。正则表达式的问题是,如果同一行上有两个结束标记,我的表达式甚至会打印第一个标记开始到第二个结束标记结束之间的数据

xml 文件 -

She outsprinted Becky Smith and Joan Hare to the line, with Becky and Joan
finishing in a time of <time>1:02:41</time> and <time>  1:02:45</time>
respectively. 

我正在使用的正则表达式(想要提取时间详细信息) -

   if (/<time>(.*)<\/time>/) {
    ($hh, $mm, $ss) = split(':', $1);
    say "Time Entered - ", $hh, ":", $mm, ":", $ss, " ";
    print "***$1***\n";
    }

输出

Time Entered - 1:02:41</time> and <time>  1

预期的 -

1:02:41
1:02:45

** 第二种方法 - 使用 LibXML ** 我尝试使用下面的代码,但它给了我一个错误提示

"KnoxHalfResults:1: parser error : Start tag expected, '<' not found
Jim Colatis won Tuesday's Knoxville half marathon in a blistering pace"

输入文件有这个数据-

Jim Colatis won Tuesday's Knoxville half marathon in a blistering pace 
of <time>   0:56:45   </time>. He was followed to the line by long time nemesis 
Mickey Mouse in a time of <time>0:58:49</time>.

my code for LibXML -
use warnings;
#use XML::Twig;
use XML::LibXML;

my $filein;
my $fileout;

($filein, $fileout) = @ARGV;

my $parser = XML::LibXML->new();
my $xmldoc = $parser->parse_file($filein);

for my $sample ($xmldoc->findnodes('/time')) {

print $sample->nodeName(), ": ", $sample->textContent(), "\n";

}
4

2 回答 2

1

如前所述,数据不是 XML,因此您不能使用 XML 解析器。

有什么方法可以使它成为格式良好的 XML?将它包装在一个虚拟的根标记中可能就足够了,然后使用您的 XML::LibXML(或 XML::Twig ;--)代码。

#!/usr/bin/perl

use strict;
use warnings;
use XML::Twig;
use File::Slurp;

my ($filein, $fileout) = @ARGV;

my @times;

my $t= XML::Twig->new( twig_handlers => { time => sub { push @times, $_->text; } })
                ->parse( '<dummy>' . read_file( $filein) . '</dummy>');

print "$_\n" foreach @times;

您必须确保文件中的文本是正确的 XML 文本。它不应包含<&不属于标记的一部分。

于 2013-11-02T05:20:54.110 回答
0

一种方法是使用您的文件并将模式与正则表达式匹配。

注意:我建议使用解析器而不是正则表达式!

use strict;
use warnings;

open my $fh, '<', $file or die "failed: $!";
my $data = do { local $/; <$fh> };
close $fh;

while ( $data =~ /(\d{1,2}:\d{2}:\d{2})/g ) {
     print "Time Entered - $1 ***$1***\n";
}

或匹配您的标签

while ( $data =~ /<time>\s*(.*?)\s*<\/time>/g ) {
     print "Time Entered - $1 ***$1***\n";
}

working demo

输出

Time Entered - 1:02:41 ***1:02:41***
Time Entered - 1:02:45 ***1:02:45***
于 2013-11-02T03:13:02.487 回答