使用XML::Simple提取XML值报错‘Not a HASH reference’排查
"Not a HASH reference" 错误原因解析
示例XML
<A> <B> <C>..</C> <D>..</D> <E>..</E> </B> </A>
问题代码
use strict; use warnings; use Data::Dumper; use XML::Simple; open(my $fh, '<', '/tmp/abc.xml'); my $xml = new XML::Simple; my $data = $xml->XMLin($fh) or die "Failed to find $fh"; my $value = $data->{'B'}; print $value->{'C'}
错误信息
Not a HASH reference.
原因分析
问题出在XML::Simple的默认解析行为上:当XML中某个节点(比如<B>)仅出现一次时,XMLin会默认将该节点的子节点直接合并到父节点的哈希结构中,而不是把<B>保留为独立的哈希引用。
换句话说,解析后$data的实际结构是:
{ 'C' => '..', 'D' => '..', 'E' => '..' }
而非你预期的:
{ 'B' => { 'C' => '..', 'D' => '..', 'E' => '..' } }
此时$data->{'B'}返回的是undef,对undef调用哈希引用的访问操作->{'C'},自然会抛出"Not a HASH reference"错误。
解决办法
- 强制节点为数组引用:调用
XMLin时添加ForceArray => 1参数,让所有节点(哪怕只出现一次)都以数组形式存在,这样就能按预期层级访问:my $data = $xml->XMLin($fh, ForceArray => 1) or die "Failed to parse $fh"; print $data->{B}->[0]->{C}; - 直接访问子节点:既然
<B>的子节点被合并到了<A>层级,直接跳过<B>访问目标节点即可:print $data->{'C'};
调试技巧
可以用Data::Dumper打印解析后的$data结构,直观查看哈希的实际组织形式:
print Dumper($data);
内容的提问来源于stack exchange,提问作者dbnoob
相关产品推荐
相关产品推荐

