在 Perl 中比较来自 XML 的字符串?
Comparing strings from XML in Perl?
完全免责声明:我是 Perl 的新手,只有一周或更短的经验。在工作中,我当前的项目涉及一个过程,在该过程中,我们将代表来自不同机构的课程目录的 XML 个文件连接到一个文件中。我有一个工作的 Perl 脚本 + 模块可以精确地做到这一点;但是,我希望通过检查合并的文件是否满足以下条件来添加一些额外的功能:
1) 每个 class 列表都来自同一学期(包含在标签中)
2) 每个 class 列表都来自同一年(包含在标签中)
这是合并后 运行 我当前的子程序(这意味着问题肯定在下面的代码中):
sub check_files {
my ($self, $file) = @_;
my $parser;
my $parsed;
my @semesters;
my @years;
my $answer = 0;
my $correct = 0;
$parser = XML::LibXML->new;
$parsed = $parser->parse_file($file);
@semesters = $parsed->getElementsByTagName("SEMESTER");
@years = $parsed->getElementsByTagName("YEAR");
foreach my $semester1 (@semesters) {
my $semester2 = $semesters[1];
if($semester1 ne $semester2) {
if($semester1 ne "<SEMESTER>Do not delete this row</SEMESTER>") {
print "Check semesters in data! $semester1 $semester2 \n\n";
$answer += 1;
}
} else {
print "Equal strings: $semester1 $semester2 \n\n";
$correct += 1;
}
}
foreach my $year1 (@years) {
my $year2 = $years[1];
if($year1 ne $year2) {
if($year1 ne "<YEAR>Do not delete this row</YEAR>") {
print "Check years in data! $year1 $year2 \n\n";
$answer += 1;
}
} else {
print "Equal strings: $year1 $year2 \n\n";
$correct += 1;
}
}
print "Errors: $answer Correct: $correct \n\n";
return $answer;
}
我根据元素 1 而不是 0 检查所有内容,因为连接的第一个文件是 header 行(应该等于 "Do not delete this row" 的内容)。因此,"do not delete" 应该始终是元素 0。
我在控制台中收到很多很多 "Check semesters in data! 2013 2013" 行。事实上,我的 $correct 变量唯一一次递增是在 header 行 if condition fails 时。这让我觉得字符串比较在某种程度上被搞砸了;我能想到的唯一解释是指针问题和编码。但同样,我上周才开始使用 Perl,所以我真的不知道我在说什么。我知道我的代码也不优雅,对此深感抱歉。
感谢任何能提供帮助的人,或者读了这篇文章但决定不去的人。
当我根据您显示的数据 运行 您的代码时,我没有得到您描述的输出,但我确实有适合您的解决方案
您确实需要了解 XML 数据。它的嵌套非常像函数式编程语言,因此标签必须平衡,并且始终只有一个根节点。在您的数据中,它被称为 <ROOT>
,如果您在文件的末尾查看,将会有一个结束的 </ROOT>
此代码使用 XPath 表达式查找除第一个 SECTION
元素以外的所有元素,然后从每个元素中提取 YEAR
和 SEMESTER
子元素的值并在几个哈希值中保持计数
我不知道如果您的子例程找到多年或多个学期,您希望它做什么,所以它所做的只是打印几行摘要。我希望你能理解如何从这里继续下去
sub check_files2 {
my $self = shift;
my ($file) = @_;
my $doc = XML::LibXML->load_xml(location => $file);
my @sections = $doc->findnodes('/ROOT/SECTION[position() > 1]');
printf "%d sections found after the first\n", scalar @sections;
my (%years, %semesters);
for my $section ( @sections ) {
my $year = $section->findvalue('YEAR');
my $semester = $section->findvalue('SEMESTER');
++$semesters{$semester};
++$years{$year};
}
my @years = keys %years;
printf "%d different years: %s\n", scalar @years, "@years";
my @semesters = keys %semesters;
printf "%d different semesters: %s\n", scalar @semesters, "@semesters";
}
输出
24 sections found after the first
1 different years: 2013
1 different semesters: F
完全免责声明:我是 Perl 的新手,只有一周或更短的经验。在工作中,我当前的项目涉及一个过程,在该过程中,我们将代表来自不同机构的课程目录的 XML 个文件连接到一个文件中。我有一个工作的 Perl 脚本 + 模块可以精确地做到这一点;但是,我希望通过检查合并的文件是否满足以下条件来添加一些额外的功能:
1) 每个 class 列表都来自同一学期(包含在标签中)
2) 每个 class 列表都来自同一年(包含在标签中)
这是合并后 运行 我当前的子程序(这意味着问题肯定在下面的代码中):
sub check_files {
my ($self, $file) = @_;
my $parser;
my $parsed;
my @semesters;
my @years;
my $answer = 0;
my $correct = 0;
$parser = XML::LibXML->new;
$parsed = $parser->parse_file($file);
@semesters = $parsed->getElementsByTagName("SEMESTER");
@years = $parsed->getElementsByTagName("YEAR");
foreach my $semester1 (@semesters) {
my $semester2 = $semesters[1];
if($semester1 ne $semester2) {
if($semester1 ne "<SEMESTER>Do not delete this row</SEMESTER>") {
print "Check semesters in data! $semester1 $semester2 \n\n";
$answer += 1;
}
} else {
print "Equal strings: $semester1 $semester2 \n\n";
$correct += 1;
}
}
foreach my $year1 (@years) {
my $year2 = $years[1];
if($year1 ne $year2) {
if($year1 ne "<YEAR>Do not delete this row</YEAR>") {
print "Check years in data! $year1 $year2 \n\n";
$answer += 1;
}
} else {
print "Equal strings: $year1 $year2 \n\n";
$correct += 1;
}
}
print "Errors: $answer Correct: $correct \n\n";
return $answer;
}
我根据元素 1 而不是 0 检查所有内容,因为连接的第一个文件是 header 行(应该等于 "Do not delete this row" 的内容)。因此,"do not delete" 应该始终是元素 0。
我在控制台中收到很多很多 "Check semesters in data! 2013 2013" 行。事实上,我的 $correct 变量唯一一次递增是在 header 行 if condition fails 时。这让我觉得字符串比较在某种程度上被搞砸了;我能想到的唯一解释是指针问题和编码。但同样,我上周才开始使用 Perl,所以我真的不知道我在说什么。我知道我的代码也不优雅,对此深感抱歉。
感谢任何能提供帮助的人,或者读了这篇文章但决定不去的人。
当我根据您显示的数据 运行 您的代码时,我没有得到您描述的输出,但我确实有适合您的解决方案
您确实需要了解 XML 数据。它的嵌套非常像函数式编程语言,因此标签必须平衡,并且始终只有一个根节点。在您的数据中,它被称为 <ROOT>
,如果您在文件的末尾查看,将会有一个结束的 </ROOT>
此代码使用 XPath 表达式查找除第一个 SECTION
元素以外的所有元素,然后从每个元素中提取 YEAR
和 SEMESTER
子元素的值并在几个哈希值中保持计数
我不知道如果您的子例程找到多年或多个学期,您希望它做什么,所以它所做的只是打印几行摘要。我希望你能理解如何从这里继续下去
sub check_files2 {
my $self = shift;
my ($file) = @_;
my $doc = XML::LibXML->load_xml(location => $file);
my @sections = $doc->findnodes('/ROOT/SECTION[position() > 1]');
printf "%d sections found after the first\n", scalar @sections;
my (%years, %semesters);
for my $section ( @sections ) {
my $year = $section->findvalue('YEAR');
my $semester = $section->findvalue('SEMESTER');
++$semesters{$semester};
++$years{$year};
}
my @years = keys %years;
printf "%d different years: %s\n", scalar @years, "@years";
my @semesters = keys %semesters;
printf "%d different semesters: %s\n", scalar @semesters, "@semesters";
}
输出
24 sections found after the first
1 different years: 2013
1 different semesters: F