Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

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:


Hi,

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:

    root/head/node1@att1

    instead of

    root/head/node1/@att1

      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?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (8)
As of 2016-06-27 12:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My preferred method of making French fries (chips) is in a ...











    Results (337 votes). Check out past polls.