So, I spent some time this morning writing a SAX filter to read an OPML file and slurp "instant outlines". The short version is : you should be able to do this with exactly one data file and one parsing/munging widget. As it stands, you need two data files : the outline and a storage unit -- a table in Frontier, a Storable file in Perl -- to maintain the list of subscriptions and (I guess it's a six-of-one thing) their file size. What is aggravating about this approach is that all the necessary information for doing instant outlines can be stored in the outline file itself. The (unwritten) DTD for an OPML file is:



<!ELEMENT outline (outline?|outline*)>



<!ATTLIST outline text CDATA #REQUIRED



                  created CDATA #REQUIRED



                  type (link|foo|bar) #IMPLIED



                  url CDATA #IMPLIED>



Rewritten to accomodate "inline" instant outlines it would look like:



<!ELEMENT outline (outline?|outline*)>



<!ATTLIST outline text CDATA #REQUIRED



                  created CDATA #REQUIRED



                  modified CDATA #REQUIRED



                  type (link|subscription|foo|bar) #IMPLIED



                  url CDATA #IMPLIED>



Which would let you do something neat like:







# @ISA = qw (XML::SAX::Base)







sub start_element {



   my $self = shift;



   my $data = shift;







   if ($data->{Name} ne "outline") {



       $self->SUPER::start_element($data);



       return 1;



   }







   # This part of SAX2 really sucks...



   if ($data->{Attributes}->{'{}type'}->{Value} ne "subscription") {



       $self->SUPER::start_element($data);



       return 1;



   }







   # mmmm...suckiness



   my $uri = $data->{Attributes}->{'{}url'}->{Value};







   my $ua      = LWP::UserAgent->new();



   my $request = HTTP::Request->new(GET=>$uri);







   # I don't think Radio does this; it should.



   $ua->max_size(MAX_SIZE); 



  



   # The Yeastie Girls wrote a great song called "You Suck"



   $request->if_modified_since($data->{Attributes}->{'{}modified'}->{Value});







   my $outline = $ua->request($request);







   # Not modified. Move along, now.



   # Needs to carp unless return code is OK



   # or NOT_MODIFIED







   if (! $outline->is_success()) {



     $self->SUPER::start_element($data);



     return 1;



   }







   # Suck it hard, baby



   $data->{Attributes}->{'{}modified'}->{Value} = time;







   $self->SUPER::start_element($data);







   # Pass $outline->content() off to a secondary filter



   # and keep munging. Note to self: hooks to prevent



   # recursive instant-ness... 



}



Oh well.