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


Hi,

how can i read the value of an attribute in an XPath? Say i have an XPath doc/a/b/c which has an attribute d. How do i read the value of d?


  • Comment on Reading attrbiutes of an XPath using XML::XPath module...

Replies are listed 'Best First'.
Re: Reading attrbiutes of an XPath using XML::XPath module...
by ikegami (Patriarch) on Oct 14, 2009 at 05:34 UTC

    If the query matches element nodes, then surely the method returns XML::XPath::Node::Element objects. These have a getAttribute attribute.

    Since you appear to be just getting started, might I suggest using XML::LibXML instead of XML::XPath? It's insanely faster than anything else I timed, it has the most complete API I've seen, it's interface follows a standard (DOM), and it's one of the only parsers that does everything correctly.

    Update: Looks like XML::Path doesn't handle namespaces correctly.

    use strict; use warnings; use Test::More tests => 2; use XML::XPath qw( ); use XML::LibXML qw( ); my $xml = <<'__EOI__'; <?xml version="1.0" ?> <root> <ele /> <ele xmlns="http://www.example.com/" /> </root> __EOI__ { my $doc = XML::XPath->new( xml => $xml ); my @nodes = $doc->findnodes('/root/ele'); is(0+@nodes, 1, 'XML::XPath'); } { my $doc = XML::LibXML->new()->parse_string( $xml ); my @nodes = $doc->findnodes('/root/ele'); is(0+@nodes, 1, 'XML::LibXML'); } __END__ 1..2 not ok 1 - XML::XPath # Failed test 'XML::XPath' # at 801019.pl line 20. # got: '2' # expected: '1' ok 2 - XML::LibXML # Looks like you failed 1 test of 2.
Re: Reading attrbiutes of an XPath using XML::XPath module...
by derby (Abbot) on Oct 14, 2009 at 13:27 UTC

    The XPATH expression (if your at the root) would be '/doc/a/b/c/@d'. Using XML::LibXML something like this should work:

    #!/usr/bin/perl use strict; use warnings; use XML::LibXML; my $xml = <<_XML; <doc> <a> <b> <c d="foo"/> </b> </a> </doc> _XML my $parser = XML::LibXML->new(); my $doc = $parser->parse_string( $xml ); my $val = $doc->findvalue( '/doc/a/b/c/@d' ); print $val, "\n";
    But that's only going to work if there's one a, b, and c element. If you think you'll have multiple elements, you'll have to collect them and then iterate the nodes.

    -derby