Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

XPath with node names and attributes...

by biswanath_c (Beadle)
on Oct 16, 2009 at 15:43 UTC ( #801578=perlquestion: print w/ replies, xml ) Need Help??
biswanath_c has asked for the wisdom of the Perl Monks concerning the following question:


I am using XML::LibXML to parse an XML doc. I would like to use XPaths to get values of different nodes and attributes. findnodes(...) API seems to work for nodes (ex: root/head/node1 ) but it gives an error "invalid expression" for XPaths with attrbiutes (ex: root/head/node1/@att1 where att1 is an attribute of node node1).

I'd like to use a "common" API that would "find" AND "get the value of" XPaths irrespective of whether the XPath is pointing to a node or an attribute. Could someone give me an API that'd work generically both for nodes AND attributes without having to handle them separately in my code?

Comment on XPath with node names and attributes...
Replies are listed 'Best First'.
Re: XPath with node names and attributes...
by Corion (Pope) on Oct 16, 2009 at 15:58 UTC

    Just give the XPath engine properly formatted XPath queries and all will work.

    In your case, that likely means using:


    instead of


      There must be something I am missing here. root/head/node1@att1 is invalid, while root/head/node1/@att1 works just fine. I tested that with several tools, including XML::LibXML.

      I would actually had the starting slash: /root/head/node1@att1.

      I tried using the XPath that you suggested (root/head/node1@att1). But in that case, i call findnodes(<XPath with attribute>) and iterate thru the resulting array and call findValue(".") on the array elements, it returns nothing! i tried calling nodeValue() also, that too returned nothing! i tried textContent(), it returned value of the node but not the value of the attribute!

      What do i do?

        Actually, I am wrong and you are right - queries for attributes also need / as the separator. I thought the @ would separate a element node from an attribute node, as the documentation seems to suggest to me in //title[@lang], but upon actually trying it, I find that only node/@attribute works for me, and likely is the correct query to use.

Re: XPath with node names and attributes...
by thunders (Priest) on Oct 16, 2009 at 16:56 UTC
    Perhaps It would help if you provide some example code and xml that demonstrates the problem you are having.

      okay! here we go. I am just giving an example here that I tested and which demonstrates my problem:

      The XML:
      <root> <head> <node1 attr1="Node1 Attribute"> Node1 Value </node1> </head> </root>

      The PERL script that tries to read the attribute:

      use XML::LibXML; $inp = $ARGV[0]; # create object my $parser = XML::LibXML->new(); # read input XML file my $inp_tree = $parser->parse_file($inp); my $inp_root = $inp_tree->getDocumentElement; my $root_text = $inp_root->toString(); $rule_source = "head/node1@attr1"; my @inp_search_nodes = $inp_root->findnodes($rule_source); my $inp_search_results = scalar @inp_search_nodes; if ( 0 == $inp_search_results ) { print "XPath $rule_source not found! \n"; } else { my $path_text = $inp_search_nodes[ 0 ]->findvalue("."); print "Xpath ->: $path_text\n"; my $val = $inp_search_nodes[ 0 ]->textContent(); + print "Value of XPath $rule_source : $val \n"; }

      If i search for XPath head/node1@attr1 , the code works fine and fetches the value of the node.

      If i use XPath XPath /head/node1@attr1 , the program gives the error :
       "/head/node1 not found!"

      If i use the Xpath, i get this error:
       Invalid expression

      If I use the XPath "/head/node1/@attr1", I get this error:
       Invalid expression

        Didn't have a chance to test your example, but I think this is the problem:

        $rule_source = "head/node1@attr1";

        Perl thinks you want to insert the contents of an array called @attr1 into the string because you used double quotes. Since there is no such array your $rule_source ends up with just "head/node1". Either escape the '@' or use a single quoted string as in the examples below:

        $rule_source = "head/node1\@attr1"; # or $rule_source = 'head/node1@attr1';

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://801578]
Approved by wfsp
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2016-05-05 06:03 GMT
Find Nodes?
    Voting Booth?