【问题标题】:XML::LibXML unexpected error accessing attribute values访问属性值的 XML::LibXML 意外错误
【发布时间】:2017-01-15 14:46:41
【问题描述】:

我正在通过Perl XML::LibXML by ExampleXML::LibXML 的温和介绍,并且似乎无法使哈希属性正常工作。比如下面的代码有什么问题?

#!/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 行具有相同的输出。任何指导将不胜感激。

编辑:添加了更完整的版本信息

【问题讨论】:

  • 脚本在我的系统上工作,但如果$entry-&gt;getAttribute('atr1') 工作,你为什么关心$entry-&gt;{'atr1'}
  • 如果你也加入 $XML::LibXML::VERSION 就好了。
  • XML::LibXML::LIBXML_DOTTED_VERSION 是一个返回底层 libxml 库版本的函数。显示标量$XML::LibXML::VERSION 的值更有用,它是Perl 库的版本。当前可用的版本是 2.0128,我已经确定您的代码可以在 2.0124 上正常工作。但请注意ikegami's words below,您尝试使用的功能未记录在案,因此应视为不可用。我很想知道您是如何认为它会起作用的?
  • 您必须运行 非常 旧版本的 XML::LibXML。尽管您没有显示模块的版本,但您的输出显示它基于 libxml 2.7.6,于 7 年前于 2009 年 10 月发布。
  • 感谢大家的回复。我无法访问$XML::LibXML::VERSION 函数,但能够找到XML::LibXML::LIBXML_VERSION,所以我认为这就是您的意思。然而,这些版本号似乎并不那么旧。您能否详细说明我应该查看哪个版本号?

标签: xml perl hash attributes libxml2


【解决方案1】:

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

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

根据我对ChangeLog 的阅读,这种重载行为是在 2012 年 2 月 21 日发布的 1.91 版中添加到 Element 类中的,尽管 AttributeHash 接口至少从 2009 年就已经可用。

我更新了tutorial section 提到该功能在旧版本的 XML::LibXML 上不可用。我最初确实考虑过包含该警告,但由于该功能已在 XML::LibXML 中存在很长时间,因此决定反对。

作为一般规则,如果您使用的是 Perl 对象,则认为该对象是一个 hashref 并在其中四处探查以访问哈希值将被认为是非常糟糕的做法。但是,在这种情况下,情况并非如此,并且您正在访问的哈希已被提供并记录在案。

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

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

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

【讨论】:

  • “我可能会使用$entry-&gt;findvalue('./@atr1')”。除非你关心性能。捆绑散列也非常慢。不幸的是,即使 getAttribute 在 1.61 中也有一个 Perl 包装器,出于可疑的原因,这让我在性能关键代码中切换到 _getAttribute。当然,这是一种无证且不好的做法,但这是避免严重性能下降的唯一方法。
  • 我喜欢这个指南。好工作。 :)
  • @nwellnhof,关于“绑定哈希也非常慢”,主要是因为它们转换为 Perl 方法调用。因此,与实际的 Perl 子/方法调用相比,它们并没有那么慢。但是,在这种情况下,我们在对绑定方法的子调用之上有获取绑定哈希的方法调用,所以它应该仍然很慢。
【解决方案2】:

使用能力

$entry->{'atr1'}

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

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

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

$entry->getAttribute('atr1')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 2011-01-21
    • 2012-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多