onegative has asked for the wisdom of the Perl Monks concerning the following question:

I am trying to extract the attribute value of name but not sure what/how I am suppose to do so...can't find an actual real example.
Can someone help point me in the right direction?
Many Thanks..
file.xml
<HOSTNAME name='apple'> <PATROL> <ACL> <USERNAME name='ml3007'> <HOST>*</HOST> <PERMISSION>COPS</PERMISSION> </USERNAME> </ACL> </PATROL> </HOSTNAME>


use strict; use warnings; use XML::LibXML; my $filename = $ARGV[0]; my $parser = XML::LibXML->new(); my $doc = $parser->parse_file($filename); my $xc = XML::LibXML::XPathContext->new( $doc->documentElement() ); foreach my $sections ($xc->findnodes('/HOSTNAME/PATROL/ACL/USERNAME' +)) { my($username) = $sections->getAttribute('name'); my($permissions) = $sections->findnodes('./PERMISSION'); my($host) = $sections->findnodes('./HOST'); print $username->to_literal, "\n"; print $permissions->to_literal, "\n"; print $host->to_literal, "\n"; }

Replies are listed 'Best First'.
Re: How do you get attribute values using XML::LibXML
by PeterPeiGuo (Hermit) on Dec 15, 2010 at 01:11 UTC

    Take away that "->to_literal()" method call after $username:

    print $username, "\n"; print $permissions->to_literal, "\n"; print $host->to_literal(), "\n";

    Peter (Guo) Pei

Re: How do you get attribute values using XML::LibXML
by tofanikanudo (Initiate) on Dec 15, 2010 at 13:57 UTC

    Hi,
    Method findnodes of XML::LibXML::XPathContext will return an array of elements or a XML::LibXML::NodeList object in case of scalar context.

    So In above case, variable $section is a object of XML::LibXML::Element. Method getAttribute will return a scalar value if element has value of specified attribute.

    So in above example $username has string value, not an element.

    Thanks
    Dhaval Patel

Re: How do you get attribute values using XML::LibXML
by ikegami (Pope) on Dec 16, 2010 at 21:00 UTC

    In addition to what's been said, it makes no sense to use an xpc in one place and not the other.

    my $xc = XML::LibXML::XPathContext->new($root); $xc->findnodes('/HOSTNAME/PATROL/ACL/USERNAME') $sections->findnodes('./PERMISSION')

    should be

    $root->findnodes('/HOSTNAME/PATROL/ACL/USERNAME') $sections->findnodes('./PERMISSION')

    or

    my $xc = XML::LibXML::XPathContext->new( $root ); $xc->findnodes('/HOSTNAME/PATROL/ACL/USERNAME') $xc->findnodes('./PERMISSION', $sections)

    An xpc isn't needed here since your XML doesn't use namespaces, but there's no harm in using one. Just be consistent about it.

    Note that the leading to "./" is useless (whether an xpc is used or not). The following will do:

    $xc->findnodes('PERMISSION', $section)
Re: How do you get attribute values using XML::LibXML
by grantm (Parson) on Dec 16, 2010 at 20:30 UTC

    In the case where your XPath query will find only one node (e.g.: when referring to an attribute), instead of using findnodes, you could the findvalue method to get the text content of the matching node:

    #!/usr/bin/perl use strict; use warnings; use XML::LibXML; my $filename = $ARGV[0]; my $parser = XML::LibXML->new(); my $doc = $parser->parse_file($filename); my $xc = XML::LibXML::XPathContext->new( $doc->documentElement() ); foreach my $sections ($xc->findnodes('/HOSTNAME/PATROL/ACL/USERNAME')) + { my $username = $sections->findvalue('./@name'); my $permissions = $sections->findvalue('./PERMISSION'); my $host = $sections->findvalue('./HOST'); print "$username\n"; print "$permissions\n"; print "$host\n"; }

    Also, if your document doesn't actually use namespaces (which your example doesn't) then you might as well leave out XML::LibXML::XPathContext and call $doc->findnodes instead.

    However if your document does use namespaces then instead of doing this:

    $sections->findnodes('./PERMISSION');

    You need to do this for the namespace prefixes to work:

    $xc->findnodes('./PERMISSION', $sections);