Perl: получить значение из XML

Мне нужно получить значение из этого xml - http://pastebin.com/wkh7trd4. Вот мой код, но он ничего не возвращает:

my $xml = XML::LibXML->new('clean_namespaces' => 1)->parse_file("$tmp_dir/xml/$xml_file_name");
my $xc = XML::LibXML::XPathContext->new($xml);
my $val = $xc->findvalue('/ns2:export/ns2:bankGuarantee/docPublishDate');
print $val;

person Artem    schedule 28.08.2015    source источник
comment
Это может быть исключение, оберните его в eval{} и выгрузите $@, если оно существует.   -  person steve    schedule 29.08.2015
comment
было бы интересно увидеть ответ на этот вопрос, который объясняет проблему, поскольку из вашего кода это выглядит нормально.   -  person Chris Doyle    schedule 29.08.2015


Ответы (3)


Похоже, это связано с пространством имен по умолчанию. Не уверен, как работает xpath, но @miller, похоже, ответил на свой вопрос здесь: XML::LibXML, пространства имен и findvalue

Вы можете попробовать следующее, что, надеюсь, должно решить вашу проблему.

use strict;
use warnings;
use XML::LibXML;

open(my $xml_file, '<', "xml_to_parse.xml");
my $xml = new XML::LibXML->load_xml(IO => $xml_file);
print $xml->findvalue('/ns2:export/ns2:bankGuarantee/*[local-name()="docPublishDate"]'), "\n";
person Chris Doyle    schedule 29.08.2015

библиотеки часто выбрасывают исключения при сбое, если вы их не поймаете, они могут молча выйти из строя.

пытаться:

use strict;
use warnings FATAL => 'all';

eval
{
    my $xml = XML::LibXML->new('clean_namespaces' => 1)->parse_file("$tmp_dir/xml/$xml_file_name");
    my $xc = XML::LibXML::XPathContext->new($xml);
    my $val = $xc->findvalue('/ns2:export/ns2:bankGuarantee/docPublishDate');
    print $val;
}
if($@)
{
    print "ERROR: " . $@;
}

Если один из них не работает, он должен дать вам ошибку.

person steve    schedule 28.08.2015

Простое создание объекта XML::LibXML:XPathContext ничего не изменит, вам также необходимо зарегистрировать все пространства имен, которые вы хотите использовать в выражениях XPath. В этом случае вы использовали пространство имен ns2 вообще без регистрации каких-либо пространств имен.

Ваш код должен выглядеть примерно так

my $xml = XML::LibXML->new->parse_file("$tmp_dir/xml/$xml_file_name");

my $xc = XML::LibXML::XPathContext->new($xml);
$xc->RegisterNs( ns2 => 'http://example.com/ns2/uri/address');

my $val = $xc->findvalue('/ns2:export/ns2:bankGuarantee/docPublishDate');
print $val;

Обратите внимание, что URI, который вы регистрируете, должен совпадать с URI в

xmlns:ns2="http://example.com/ns2/uri/address"

атрибут в данных

Мне интересно, является ли опция парсера clean_namespaces вашей попыткой исправить это? clean_namespaces удалит только избыточные пространства имен, то есть те, которые нигде не используются в XML-документе. В этом мало смысла, так как у вас мало шансов столкнуться с конфликтом пространств имен, а сэкономленное время и память будут незначительными.

person Borodin    schedule 29.08.2015