http://qs321.pair.com?node_id=757368

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

Hi All,
I have a strange problem. Please inspect the following code:
use XML::Twig::XPath; my $t = XML::Twig->new( twig_roots => { 'BalancerStatus/WebServer/OverallConnectio +nPoolStatus' => \&section, }); $t->parsefile( 'localhost.xml'); # sub section { my ($t, $section) = @_; print $section->get_xpath( q{//OverallConnectionPoolStatus/FlowRat +er[Name='Total.IncomingReq']} ); $t->purge; }
When I run it on an xml file I receive:
error in xpath expression //OverallConnectionPoolStatus/FlowRater[Name= ...
I decided to check this exact expression in the XML::XPath itself, and there, I have no errors, I even get a desired result! I used the following code:
use XML::XPath; use XML::XPath::XMLParser; my $xp = XML::XPath->new(filename => 'chunk.xml'); my $nodeset = $xp->find( q{//OverallConnectionPoolStatus/FlowRater +[Name='Total.IncomingReq']} ); # find all paragraphs foreach my $node ($nodeset->get_nodelist) { print "FOUND\n\n", XML::XPath::XMLParser::as_string($node), "\n\n"; }
Strange! Can someone help ?

Replies are listed 'Best First'.
Re: Xml::Twig:Xpath Xpath expression error
by mirod (Canon) on Apr 14, 2009 at 11:33 UTC

    Without the XML it's a bit hard to figure out what you are trying to do here, or to test anything, but if Name is an attribute, you need to write @Name in the query.

    Updated: oops! I had '#' instead of '@', fixed now.

      Thank you.
      It didn't help. By adding @ to the Name I escaped the error message but didn't get a desired result! Why with the same expression XML:XPath get me good output?
      Portion of the xml this sub will process:
      <OverallConnectionPoolStatus> <FlowRater> <Name>Total.IncomingReq</Name> <Rate>0</Rate> <LastMinRate>0</LastMinRate> <Counter>209</Counter> </FlowRater><FlowRater> <Name>Total.RejectedReq</Name> <Rate>0</Rate> <LastMinRate>0</LastMinRate> <Counter>0</Counter> </FlowRater><FlowRater> <Name>Total.AcceptedReq</Name> <Rate>0</Rate> <LastMinRate>0</LastMinRate> <Counter>209</Counter> </FlowRater><FlowRater> <Name>Total.FailedSendResponse</Name> <Rate>0</Rate> <LastMinRate>0</LastMinRate> <Counter>0</Counter> </FlowRater><FlowRater> <Name>Total.RejectedRetry</Name> <Rate>0</Rate> <LastMinRate>0</LastMinRate> <Counter>0</Counter> </FlowRater><FlowRater> <Name>Total.IncomingRetry</Name> <Rate>0</Rate> <LastMinRate>0</LastMinRate> <Counter>0</Counter> </FlowRater><FlowRater> <Name>Total.RejectedLastRetry</Name> <Rate>0</Rate> <LastMinRate>0</LastMinRate> <Counter>0</Counter> </FlowRater></OverallConnectionPoolStatus>
        After reviewing your actual XML - it looks like your XPath is incorrect for your intentions. I don't see any attriubes in your XML.

        Try something more like //OverallConnectionPoolStatus/FlowRater/Name/text() to reference your information.

        The previous XPath's are attempting to search for attributes in the FlowRater node. What you actually have is a child node called Name with some information in it.

        As far as why this works in some modules, and not in others I would postulate that the designer included this as a "feature" to help others out. - Or maybe you found a bug.
Re: Xml::Twig:Xpath Xpath expression error
by ramrod (Curate) on Apr 14, 2009 at 13:42 UTC
    Try using @ in your Xpath statement to reference an attribute.

    For example . . .
    //OverallConnectionPoolStatus/FlowRater[@Name='Total.IncomingReq']
Re: Xml::Twig:Xpath Xpath expression error
by mirod (Canon) on Apr 14, 2009 at 15:20 UTC

    Er... after looking at it again... you are creating a plain XML::Twig object instead of an XML::Twig::XPath one. I'll have to update the error message in this case.

      Thank you, I changed it but I still having problems with running even simple expressions. like:
      //OverallConnectionPoolStatus/FlowRater/text()
      why? it appears in XML::XPath examples as valid syntax!

        The thing is, there is no direct textual content in any of the FlowRater elements, so text() is empty, hence //OverallConnectionPoolStatus/FlowRater/text() won't return much.

        //OverallConnectionPoolStatus/FlowRater/Name/text() OTOH, will indeed give you the contents of the Name elements, if you write, for example: print map { $_ } $section->findnodes( q{//OverallConnectionPoolStatus/FlowRater/Name/text()} );.