【发布时间】:2013-09-09 06:37:15
【问题描述】:
我通过调用递归方法process_node处理了几个XML文件:
for my $file (@ARGV) {
my $doc = XML::LibXML->load_xml(location => $file);
my $report;
my $items = [];
process_node($doc->getDocumentElement, $report, $items);
print Dumper($items);
}
它们都有相似的结构:
- 一个名为
CalRunnerReport的大父节点,其属性为BSN、ProjectName、StationName - 还有很多名为
TestItem的子节点
我正在尝试准备一个由变量 $items- 引用的哈希数组,用作 DataTables.net(一个 HTML 表格组件)的数据源:
sub process_node($$$) {
my ($node, $report, $items) = @_;
return unless $node->nodeType == XML_ELEMENT_NODE;
if ($node->nodeName eq 'CalRunnerReport') {
my $attr = get_attributes($node);
$report = {
BSN => $attr->{BSN},
ProjectName => $attr->{ProjectName},
StationName => $attr->{StationName},
}
} elsif ($node->nodeName eq 'TestItem') {
my $attr = get_attributes($node);
push @$items, [ # XXX fails to create a hash
%$report,
%$attr,
];
}
for my $child ($node->getChildnodes) {
process_node($child, $report, $items);
}
}
sub get_attributes($) {
my $node = shift;
my $attr = {};
for my $a ($node->attributes) {
my $key = $a->name;
my $val = $a->value;
$attr->{$key} = $val;
}
return $attr;
}
但是在Data:Dumper 输出中,我看到上面的push 语句没有创建哈希,而是创建了一个列表:
[
'BSN',
'1147386447',
'ProjectName',
'R089',
'StationName',
'B',
'ExecutionTime',
'00:00:00',
'Result',
'PASS',
'EndTime',
'03/09/2013 21:00:03',
'StartTime',
'03/09/2013 21:00:03',
'Name',
'RecordOperationParameter'
],
[
'BSN',
'1147386447',
'ProjectName',
'R089',
'StationName',
'B',
'ExecutionTime',
'00:00:00',
'Result',
'PASS',
'EndTime',
'03/09/2013 21:00:03',
'StartTime',
'03/09/2013 21:00:03',
'Name',
'ClearLimitTestPendingList'
]
有没有一种很好的方法可以将%$report 和 %$attr 的 2 个哈希值组合成一个哈希值 - 而无需遍历它们的所有密钥?
【问题讨论】:
-
你能说清楚你期待什么数据结构吗?
-
不,这不可能。您将不得不遍历键。最好的解决方案是
{ %$report, %$attr },除非您想检查%$attr中的值是否会覆盖%$report中的值。