2016-09-07 2 views
0

Я бег через осторожное введение к XML::LibXML в Perl XML::LibXML by Example и не могу показаться, чтобы получить хэш атрибутов работает. Например, что случилось с следующим кодом?XML :: 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, чтобы иметь тот же результат. Любое руководство будет высоко оценено.

Edit: Добавлено более полная информация о версии

+0

работы скрипта на моей системе, но если '$ entry-> GetAttribute («ATR1»)' работает, почему вы заботитесь о '$ запись -> { 'ATR1'} '? – redneb

+1

Было бы неплохо, если бы вы включили '$ XML :: LibXML :: VERSION' тоже. – ikegami

+0

'XML :: LibXML :: LIBXML_DOTTED_VERSION' - это функция, которая возвращает версию базовой библиотеки libxml. Полезнее показать значение скалярного '$ XML :: LibXML :: VERSION', которое является версией библиотеки Perl. В настоящее время доступна версия 2.0128, и я установил, что ваш код отлично работает с 2.0124. Но, пожалуйста, обратите внимание на слова [икегами ниже] (http://stackoverflow.com/a/39378246/622310), что функция, которую вы пытаетесь использовать, недокументирована и поэтому должна считаться недоступной. Мне было бы интересно узнать, как вы пришли к мысли, что это будет работать вообще? – Borodin

ответ

2

Как автор руководства, которые вы использовали, мне очень жаль, что вы столкнулись с этой проблемой и считаю, что тон некоторых замечаний и ответы здесь были чрезмерно суровыми.

кода вы вывесили делает работы по версии XML :: Libxml, которые поддерживают его и является охваченной в OVERLOADING section of the XML::LibXML::Element docs. Этот «привязанный хэш» интерфейс является более «Perlish» способом доступа к значениям атрибутов, чем вызов метода getAttribute(). Одно из преимуществ заключается в том, что хеш-доступ работает внутри строки с двумя кавычками, тогда как явный вызов метода не будет.

Из моего чтения ChangeLog, это перегрузка поведения было добавлено к классу элементов в версии 1.91 выпущен на 2012-02-21, хотя интерфейс AttributeHash был доступен по крайней мере с 2009 годом

Я обновил tutorial section, чтобы упомянуть, что эта функция недоступна в старых версиях XML :: LibXML. Первоначально я рассматривал включение этого предупреждения, но решил отказаться от него, так как функция долгое время находилась в XML :: LibXML.

Как правило, если вы используете объект Perl, было бы очень плохой практикой предположить, что объект был hashref и ткнул внутри него, чтобы получить доступ к хеш-значениям. Однако это не то, что происходит в этом случае, и хеш, к которому вы обращаетесь, был предоставлен и задокументирован именно для этой цели.

Если бы я собирался использовать вызов метода, чтобы получить значение, я бы, вероятно, использовать:

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

, так как это может быть легко адаптировано для доступа текста или атрибутов контента из вложенных элементов, а также.

+0

«Я бы, вероятно, использовал' $ entry-> findvalue ('./@ atr1') '. Если вы не заботитесь о производительности. Связанные хэши также невероятно медленны. К сожалению, даже 'getAttribute' получил оболочку Perl в 1,61 по сомнительным причинам, что заставило меня переключиться на' _getAttribute' в критическом по производительности коде. Конечно, это недокументированная и плохая практика, но это был единственный способ избежать серьезных регрессий производительности. – nwellnhof

+0

Мне нравится гид. Отличная работа. :) – simbabque

+0

@nwellnhof, Re "* Связанные хэши также невероятно медленны *", главным образом потому, что они переходят на вызовы метода Perl. Таким образом, они не так медленны, когда сравниваются с фактическим вызовом sub/method Perl. Однако в этом случае у нас есть вызов метода, чтобы получить связанный хеш в верхней части подзаголовка с связанным методом, поэтому он все равно должен быть очень медленным. – ikegami

2

Возможность использования

$entry->{'atr1'} 

был добавлен в XML :: Libxml в версии 1.91. Это эквивалентно

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

У вас должна быть старая версия XML :: LibXML. Вы можете обновить XML :: LibXML, но вы можете также использовать

$entry->getAttribute('atr1') 
Смежные вопросы