访问属性值的XML :: LibXML意外错误

时间:2016-09-07 19:42:12

标签: xml perl hash attributes libxml2

我正在XML::LibXML处对Perl XML::LibXML by Example的温和介绍,似乎无法使哈希属性正常工作。例如,以下代码有什么问题?

#!/usr/bin/perl

use strict;
use warnings;

use XML::LibXML;

my $version = XML::LibXML::LIBXML_VERSION;
my $dot_version = XML::LibXML::LIBXML_DOTTED_VERSION;
my $run_version = XML::LibXML::LIBXML_RUNTIME_VERSION;
print "LibXML version: $version\n";
print "LibXML dotted version: $dot_version\n";
print "LibXML runtime version: $run_version\n";
print "Perl version: $^V\n";

my $xml = q{
<record>
  <entry atr1="a" atr2="b" atr3="c" />
</record>
};

my $dom = XML::LibXML->load_xml( string => $xml );
my ($entry) = $dom->documentElement->getChildrenByTagName('entry');

print "\$entry is a: ", ref($entry), "\n";
print "node name: ", $entry->nodeName, "\n";
print "Attribute: ", $entry->getAttribute('atr1'), "\n";    # Line 26
print "Attribute: ", $entry->{'atr1'}, "\n";                # Line 27

使用以下输出:

$./hashtest.pl 
LibXML version: 20706
LibXML dotted version: 2.7.6
LibXML runtime version: 20706
Perl version: v5.10.1
$entry is a: XML::LibXML::Element
node name: entry
Attribute: a
Not a HASH reference at ./hashtest.pl line 27.

我希望第26行和第27行具有相同的输出。任何指导都将非常感谢。

修改:添加了更多完整版本信息

2 个答案:

答案 0 :(得分:2)

作为您一直使用的指南的作者,我很抱歉您遇到了这个问题,并且觉得这里的一些评论和回复的语气过于刺耳。

您发布的的代码适用于支持它的XML :: LibXML版本,OVERLOADING section of the XML::LibXML::Element docs中涵盖 。与调用getAttribute()方法相比,这种“绑定哈希”接口是访问属性值的更“Perlish”方式。一个优点是散列访问在双引号字符串内部工作,而显式方法调用则不起作用。

从我对ChangeLog的阅读中,这个重载行为被添加到2012-02-21发布的版本1.91中的Element类中,尽管AttributeHash接口至少从2009年开始提供。

我更新了tutorial section,提到旧版本的XML :: LibXML上没有此功能。我最初考虑包含该警告,但是由于该功能已经在XML :: LibXML中存在了很长时间,所以我决定反对它。

作为一般规则,如果您正在使用Perl对象,那么假设该对象是一个hashref并在其内部进行访问以访问哈希值将被视为非常糟糕的做法。然而,这并不是在这种情况下发生的情况,并且您正在访问的哈希已经提供并记录在那个目的。

如果我打算使用方法调用来获取值,我可能会使用:

$entry->findvalue('./@atr1')

因为这可以很容易地适应从嵌套元素访问文本或属性内容。

答案 1 :(得分:2)

使用

的能力
$entry->{'atr1'}

在版本1.91中添加到XML :: LibXML中。它相当于

$entry->getAttributeHash()->{$name}

您必须拥有旧版本的XML :: LibXML。您可以升级XML :: LibXML,但您也可以使用

$entry->getAttribute('atr1')