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

This never ending project I am working on needs a new function; sorting and filtering responses. The web gui is a RoR app that I hardly know how it works, but trying to learn cause I think it's neat. :) Basically, When a parameter is passed to the perl script, it builds an XML response on the fly and pushes it back, where the ruby builds a table to display in a web browser. Some of the responses can be huge, so I would like the script to write the data to a cache, and allow the ruby to read from the cache instead of the XML response. Which perl mod would I want to use? I would use something like this in conjunction with some sort of caching? And if they re-run the report, new parameter(s) would be passed back to the perl script saying "hey let's sort this column, let's only display results where the data in this column starts with a T, and make sure we read from this file cache" Basically I create XML like this:
while LOOP{ BUNCH OF MATH STUFF .... .... push @output, $xml->cdr( $xml->Date($date_time), $xml->IngressTG($orig_gw), $xml->EgressTG($term_gw), $xml->Dialed($call_dtmf), $xml->DUR($duration), $xml->PDD($hold_time), $xml->ISDN($isdn), $xml->CallType($call_type), $xml->Link( "../cgi-bin/rpt.pl?name=CDRDETAIL&begdate=$begindate&enddate=$enddate& +interval=$interval&item2=$call_id" ) ); } print "<dataset name=\"$hdr\">\n"; print @output; print "</dataset>";
So instead of just printing it, writing it to a file cache. More than one person uses this app at a time, so I would imagine the cache it writes to would have to have some kind of identifier so we know what session it belongs to. Does this make sense? What would you use?

Replies are listed 'Best First'.
Re: Cache, sort, and filter XML response
by hallikpapa (Scribe) on Oct 16, 2007 at 02:30 UTC
    So I was going to start off by sorting the hash based on different parameters passed, and move onto the caching and filtering when I get this part done. I try and sort like this
    while LOOP { push @output, $xml->cdr( $xml->$label1( $hold_col_val . " " . $hold_col_val +2 ), $xml->$label2($total_cdr_count), $xml->$label3($total_call_count), $xml->$label4($total_error_count), $xml->$label5($formatMin), $xml->$label6($formatASR), $xml->$label7($formatPDD), $xml->$label8($formatDUR), $xml->$label9($hold_min_date), $xml->$label10($hold_max_date), $xml->$label11($link)); } my %sort_xml = @output; foreach my $key ( sort { $sort_xml{$a} <=> $sort_xml{$b} } ( keys(%sor +t_xml) ) ) { print $key $sort_xml{$key}; }
    But I get this error:
    Odd number of elements in hash assignment at rpt.pl line 960. Operation "<=>": no method found, left argument in overloaded package XML::Generator::pretty, right argument in overloaded package XML::Generator::pretty at rpt +.pl line 961.
    I am guessing I need to somehow adjust it to tell it which label 1-11 to sort on? What's that syntax? I want the order of the XML elements to be the same, but to print to screen in an ASC or DESC order based on the value of the element
      my %sort_xml = @output;

      You are coercing an array to a hash here. That hash is a structure in which every odd element of the original array is a key, and every even element a value. So if you have an odd number of elements in an array, perl warns you that there's no value for the last key.

      I guess this is not what you want.

      <update>

      Having a second look, your array contains alternatingly just the results of $xml->cdr() and $xml->Link(). At some point in the loop processing, one of these calls seems to return just an empty list, which is why you get an odd element count.

      </update>

      foreach my $key ( sort { $sort_xml{$a} <=> $sort_xml{$b} } ( keys(%sor +t_xml) ) )

      Apart from the fact that the thingies you are trying to sort live in a package that makes use of overload, you are trying to sort them numerically. Again not what you want...

      I have no idea of what each element in @out looks like (is each of them a hash? an inside-out object?), so I can only give some general advice on how to sort them:

      @sorted = sort { $a->attr_method cmp $b->attr_method } @out;

      where attr_method is the method to look up the attribute after which you want to sort those elements.

      --shmem

      _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                    /\_¯/(q    /
      ----------------------------  \__(m.====·.(_("always off the crowd"))."·
      ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}