我有一个Perl脚本将下面的XML文件转换为哈希:
<university>
<name>svu</name>
<location>ravru</location>
<branch>
<electronics>
<student name="xxx" number="12">
<semester number="1"subjects="7" rank="2"/>
</student>
<student name="xxx" number="15">
<semester number="1" subjects="7" rank="10"/>
<semester number="2" subjects="4" rank="1"/>
</student>
<student name="xxx" number="16">
<semester number="1"subjects="7" rank="2"/>
<semester number="2"subjects="4" rank="2"/>
</student>
</electronics>
</branch>
</university>.
.
.
.
.
.
<data>
<student name="msr" number="1" branch="computers" />
<student name="ksr" number="2" branch="electronics" />
<student name="lsr" number="3" branch="EEE" />
<student name="csr" number="4" branch="IT" />
<student name="msr" number="5" branch="MEC" />
<student name="ssr" number="6" branch="computers" />
<student name="msr" number="1" branch="CIV" />
.............................
..............................
.....................
</data>
如何为数据元素创建哈希表,名称和数字作为键,分支是该哈希值。我需要这个,因为有些学生名字相同,有些学生的编号相同。
通过使用此哈希密钥,我必须在大学节点中搜索学生,如果找到并打印每个学生的分支名称。
我在XML::Simple
中编写了一些脚本,但无法创建哈希值。
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
use XML::Simple;
my $xml = new XML::Simple;
my $data = $xml->XMLin("data.xml", forcearray => [ 'student' , 'semister' ],
KeyAttr => { student => "+Name" } );
print Dumper($data);
通过使用数据转储器我打印孔xml信息。但我只需要打印数据节点元素,请帮我解决这个问题。
答案 0 :(得分:1)
无需一起使用XML::Simple
和XML::Fast
。两者的表现基本相同。
为相同的功能调用多个XML解析器会以不良行为的形式引发麻烦,代码应该可以工作但不会和调试会让你牵着你的手,因为同名的方法正在相互踩踏脚趾。
对于这种情况,我会坚持使用XML::Fast
:
use strict;
use warnings;
use XML::Fast;
my $data = xml2hash 'data.xml', array => [ 'student', 'semester' ];
即使结构不完全是理想结构,$data
也可以很容易地进行后处理和调味(毕竟它是一种数据结构)。
答案 1 :(得分:1)
我可能会编写自己的XML::Parser
处理程序,将属性组合成键值(如果XML::Simple
支持的话,我在文档中找不到它)。这个例子可以帮助你入门:
#!/usr/bin/perl
use strict;
use warnings;
use XML::Parser;
use Data::Dumper;
my %hash;
sub tag_start { my ($expat, $tagname) = (shift, shift);
# attributes are now in @_
my %a = grep { $_=$_=>shift } @_; # attribute hash for this tag
my $context = join('/',$expat->context()) || '';
if ($context eq 'xml/data') {
if ($tagname eq 'student') {
push @{($hash{"$a{name}:$a{number}"}||=[])}, $a{branch};
}
} elsif ($context eq ...) {
...
}
}
my $p = new XML::Parser(Handlers => { Start=>\&tag_start });
$p->parsefile('file.xml');
print Dumper \%hash;
请注意,要实现此功能,我必须将XML封装在<xml>
标记中并添加一些缺少的空格来清理XML:
<xml>
<university>
<name>svu</name>
<location>ravru</location>
<branch>
<electronics>
<student name="xxx" number="12">
<semester number="1" subjects="7" rank="2"/>
</student>
<student name="xxx" number="15">
<semester number="1" subjects="7" rank="10"/>
<semester number="2" subjects="4" rank="1"/>
</student>
<student name="xxx" number="16">
<semester number="1" subjects="7" rank="2"/>
<semester number="2" subjects="4" rank="2"/>
</student>
</electronics>
</branch>
</university>
<data>
<student name="msr" number="1" branch="computers" />
<student name="ksr" number="2" branch="electronics" />
<student name="lsr" number="3" branch="EEE" />
<student name="csr" number="4" branch="IT" />
<student name="msr" number="5" branch="MEC" />
<student name="ssr" number="6" branch="computers" />
<student name="msr" number="1" branch="CIV" />
</data>
</xml>
结果:
$VAR1 = {
'ksr:2' => [
'electronics'
],
'msr:1' => [
'computers',
'CIV'
],
'csr:4' => [
'IT'
],
'ssr:6' => [
'computers'
],
'msr:5' => [
'MEC'
],
'lsr:3' => [
'EEE'
]
};