Reputation: 279
I would like your help in the following :
given the .xml file :
<network>
<netelement>
<node pwd="KOR-ASBG" func="describe_SBG_TGC">
<collection category="IMT" dir="Stream_statistics"></collection>
</node>
</netelement>
<netelement>
<node pwd="ADR-ASBG" func="describe_SBG_TGC">
<collection category="IMT" dir="Stream_statistics"></collection>
<collection category="IMT" dir="Proxy_registrar_statistics_ACCESS"></collection>
</node>
</netelement></network>
What I would like to do is to get the element with the attribute "KOR-ASBG", for example, but using only XPath.
I have written the following Perl code :
#!/usr/bin/perl -w
use strict ;
use warnings ;
use XML::LibXML ;
use Data::Dump qw(dump) ;
my $dump = "/some_path/_NETELEMENT_.xml" ;
my $parser = new XML::LibXML ; my $doc ;
eval{ $doc = $parser->parse_file($dump) ; } ;
if( !$doc ) { print "failed to parse $dump" ; next ; }
my $root = $doc->getDocumentElement ;
my $_demo = $root->find('/network/netelement/node[@pwd="KOR-ASBG"]') ;
print dump($_demo)."\n" ;
But, what it gets dispalyed is :
bless([bless(do{\(my $o = 155172440)}, "XML::LibXML::Element")], "XML::LibXML::NodeList")
So the question would be, how can I get the XML Element that contains the "pwd" attribute (that equals "KOR-ASBG"), using XPath ?
Thank you :)
PS. I have also tried :
my @_demo = $root->findnodes('/network/netelement/node[@pwd="KOR-ASBG"]') ;
print dump(@_demo)."\n" ;
and what it gets displayed is :
bless(do{\(my $o = 179552448)}, "XML::LibXML::Element")
Upvotes: 2
Views: 8313
Reputation: 29844
What you are seeing is what they call in Perl an "opaque object". It's not a hash, but a key to a set of lexical hashes in the the package which hold the fields for all the instances. It's Perl's way of implementing objects with security. The only way to get at their info is to call their get accessors.
The way to figure out how to deal with these is note the second argument to the bless
and look up this:
http://search.cpan.org/perldoc?<name-of-package>
Or in your case: http://search.cpan.org/perldoc?XML::LibXML::NodeList and
http://search.cpan.org/perldoc?XML::LibXML::Element
Now, I don't recommend this in all cases, but if you notice, the NodeList object is a blessed array reference. So you could just access the last node, like so:
my $nodes = $root->find('/network/netelement/node[@pwd="KOR-ASBG"]');
my $first_node = $nodes->[0];
my $last_node = $nodes->[-1];
Of course it often makes sense to make a list implementation behave like an array, either through blessed array or overloaded operators or tie
s. So, in this case, I don't think it's too big a violation of encapsulation.
Upvotes: 2
Reputation: 8406
Your dumper object is not lying to you; you are getting a node list. To access it you may either iterate through it or just access the first node:
print $_demo->get_node(0)->toString()
Of course, all DOM methods are available to you once you get the actual node:
print $_demo->get_node(0)->getAttribute('func');
Upvotes: 2
Reputation: 385496
There could technically be more than one element that matches, which is why a result set is being returned instead of single node. You could use
my ($ele) = $root->findnodes('/network/netelement/node[@pwd="KOR-ASBG"]');
That will place the first match into $ele.
Upvotes: 4