Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

XML::Xpath: How to get string from literal

by Anonymous Monk
on Jan 19, 2007 at 21:55 UTC ( #595610=perlquestion: print w/replies, xml ) Need Help??

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

I am trying to use XML::Xpath to parse output from Alexa. The response content looks like this

<?xml version="1.0"?> <aws:UrlInfoResponse xmlns:aws="http://alexa.amazonaws.com/doc/2005-10 +-05/"><aws:Response xmlns:aws="http://awis.amazonaws.com/doc/2005-07- +11"><aws:OperationRequest><aws:RequestId>ebd2abff-7c52-49ec-a7f3-7714 +dd3934ec</aws:RequestId></aws:OperationRequest><aws:UrlInfoResult><aw +s:Alexa> <aws:TrafficData> <aws:DataUrl type="canonical">look_again.blogspot.com/</aws:DataUr +l> <aws:Asin>B00006D9SV</aws:Asin> <aws:Rank>14</aws:Rank> </aws:TrafficData> </aws:Alexa></aws:UrlInfoResult><aws:ResponseStatus xmlns:aws="http:// +alexa.amazonaws.com/doc/2005-10-05/"><aws:StatusCode>Success</aws:Sta +tusCode></aws:ResponseStatus></aws:Response><aws:Response xmlns:aws=" +http://awis.amazonaws.com/doc/2005-07-11"><aws:OperationRequest><aws: +RequestId>ebd2abff-7c52-49ec-a7f3-7714dd3934ec</aws:RequestId></aws:O +perationRequest><aws:UrlInfoResult><aws:Alexa> <aws:TrafficData> <aws:DataUrl type="canonical">77708.blogspot.com/</aws:DataUrl> <aws:Asin>B00006D9SV</aws:Asin> <aws:Rank>14</aws:Rank> </aws:TrafficData> </aws:Alexa></aws:UrlInfoResult><aws:ResponseStatus xmlns:aws="http:// +alexa.amazonaws.com/doc/2005-10-05/"><aws:StatusCode>Success</aws:Sta +tusCode></aws:ResponseStatus></aws:Response><aws:Response xmlns:aws=" +http://awis.amazonaws.com/doc/2005-07-11"><aws:OperationRequest><aws: +RequestId>ebd2abff-7c52-49ec-a7f3-7714dd3934ec</aws:RequestId></aws:O +perationRequest><aws:UrlInfoResult><aws:Alexa> <aws:TrafficData> <aws:DataUrl type="canonical">ddig.blogspot.com/</aws:DataUrl> <aws:Asin>B000JFQRGM</aws:Asin> <aws:Rank>834337</aws:Rank> </aws:TrafficData> </aws:Alexa></aws:UrlInfoResult><aws:ResponseStatus xmlns:aws="http:// +alexa.amazonaws.com/doc/2005-10-05/"><aws:StatusCode>Success</aws:Sta +tusCode></aws:ResponseStatus></aws:Response><aws:Response xmlns:aws=" +http://awis.amazonaws.com/doc/2005-07-11"><aws:OperationRequest><aws: +RequestId>ebd2abff-7c52-49ec-a7f3-7714dd3934ec</aws:RequestId></aws:O +perationRequest><aws:UrlInfoResult><aws:Alexa> <aws:TrafficData> <aws:DataUrl type="canonical">blog66137.blogspot.com/</aws:DataUrl +> <aws:Asin>B00006D9SV</aws:Asin> <aws:Rank>14</aws:Rank> </aws:TrafficData> </aws:Alexa></aws:UrlInfoResult><aws:ResponseStatus xmlns:aws="http:// +alexa.amazonaws.com/doc/2005-10-05/"><aws:StatusCode>Success</aws:Sta +tusCode></aws:ResponseStatus></aws:Response><aws:Response xmlns:aws=" +http://awis.amazonaws.com/doc/2005-07-11"><aws:OperationRequest><aws: +RequestId>ebd2abff-7c52-49ec-a7f3-7714dd3934ec</aws:RequestId></aws:O +perationRequest><aws:UrlInfoResult><aws:Alexa> <aws:TrafficData> <aws:DataUrl type="canonical">webhostingservice-ka.blogspot.com/</ +aws:DataUrl> <aws:Asin>B00006D9SV</aws:Asin> <aws:Rank>14</aws:Rank> </aws:TrafficData> </aws:Alexa></aws:UrlInfoResult><aws:ResponseStatus xmlns:aws="http:// +alexa.amazonaws.com/doc/2005-10-05/"><aws:StatusCode>Success</aws:Sta +tusCode></aws:ResponseStatus></aws:Response></aws:UrlInfoResponse>

The relevant code I am using to look a the file (via the debugger) is
my $output = $response->content; my $xp = XML::XPath->new(xml => $output); my $nodeset = $xp->find('/aws:UrlInfoResponse/aws:Response'); my $nnodes = @{ $nodeset }; for my $i (0..$nnodes-1) { my $status = $nodeset[$i]->findvalue('/aws:ResponseStatus/aws:Sta +tusCode'); }
In this code $status comes back with five XML:Xpath::Node::Element objects like it should, but $status comes back as XML::Xpath::Literal which according to the docs is supposed to be a string, but I can't find a way to get a string out of it. XML::Xpath::Literal is supposed to have a method toString but when I try to apply that as in
my $string = $status->toString
I get error Can't locate object method "toString" via package "XML::XPath::Literal"

What am i doing wrong?

TIA...

Steve

readmore tags added by Arunbear

Replies are listed 'Best First'.
Re: XML::Xpath: How to get string from literal
by ikegami (Pope) on Jan 19, 2007 at 22:01 UTC

    According to XML::XPath::Literal, objects of that type are overloaded to return a string when needed.

    print $status; # Automatically gets converted to a string.

    The issue can be forced using interpolation, concatenation or the provided method.

    my $status_str1 = "$status"; # Auto converted to a string. my $status_str2 = '' . $status; # Auto converted to a string. my $status_str3 = $status->value();
      When I try that it prints nothing and/or $status_str1 is null. I thought to myself: Ok, maybe the object is not parsing, but when I try

      print $nodeset->[1]->string_value;

      I get

      ebd2abff-7c52-49ec-a7f3-7714dd3934ec look_again.blogspot.com/ B00006D9SV 14 Success

      So I'm a little baffled here...

Re: XML::Xpath: How to get string from literal
by jettero (Monsignor) on Jan 19, 2007 at 22:00 UTC

    I'm pretty sure the method you want is $string = $status->value(). That method is shown on this page XML::XPath::Literal. You were so close!!

    The auto string conversion from ikegami's post (below) is news to me. I'm going to use that from now on, where I don't need to be explicit.

    -Paul

Re: XML::Xpath: How to get string from literal
by Jenda (Abbot) on Feb 21, 2007 at 14:19 UTC

    Sorry, no XML::Xpath here. Here's what you might do using XML::Rules:

    use XML::Rules; my $parser = XML::Rules->new( namespaces => { 'http://alexa.amazonaws.com/doc/2005-10-05/' => '', 'http://awis.amazonaws.com/doc/2005-07-11' => '', }, rules => [ 'DataUrl,Asin,Rank,RequestId,StatusCode' => 'content', 'TrafficData,Alexa,UrlInfoResult,OperationRequest,ResponseStatus' +=> 'no content', 'Response' => sub { print <<"*END*" Do something with request $_[1]->{OperationRequest}{RequestId}, it was + a $_[1]->{ResponseStatus}{StatusCode} URL: $_[1]->{UrlInfoResult}{Alexa}{TrafficData}{DataUrl} Rank: $_[1]->{UrlInfoResult}{Alexa}{TrafficData}{Rank} *END* return; } ], ); # or, if you want to simplify the data as you parse them: my $parser = XML::Rules->new( namespaces => { 'http://alexa.amazonaws.com/doc/2005-10-05/' => '', 'http://awis.amazonaws.com/doc/2005-07-11' => '', }, rules => [ 'DataUrl,Asin,Rank,RequestId,StatusCode' => 'content', 'UrlInfoResult,OperationRequest' => 'no content', 'TrafficData,Alexa' => 'pass no content', 'ResponseStatus' => sub { return 'ResponseStatus' => $_[1]->{Statu +sCode}}, 'Response' => sub { print <<"*END*" Do something with request $_[1]->{OperationRequest}{RequestId}, it was + a $_[1]->{ResponseStatus} URL: $_[1]->{UrlInfoResult}{DataUrl} Rank: $_[1]->{UrlInfoResult}{Rank} *END* return; } ], );

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (7)
As of 2021-06-24 16:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What does the "s" stand for in "perls"? (Whence perls)












    Results (130 votes). Check out past polls.

    Notices?