Changeset 1500

Show
Ignore:
Timestamp:
08/20/06 18:38:27
Author:
miyagawa
Message:

rewrite OPML parser using XML::LibXML::SAX. YAY! Fixes #383

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/plagger/deps/Subscription-OPML.yaml

    r1206 r1500  
    33default: 1 
    44depends:  
    5   XML::OPML: 0 
     5  XML::LibXML::SAX: 0 
  • trunk/plagger/lib/Plagger/Plugin/Subscription/OPML.pm

    r1499 r1500  
    55use Plagger::Util; 
    66use URI; 
    7 use XML::OPML
     7use XML::LibXML::SAX
    88 
    99our $HAS_LIBERAL; 
     
    4040    } 
    4141 
    42     my $opml = XML::OPML->new; 
    43     $opml->parse($xml); 
    44     for my $outline (@{ $opml->outline }) { 
    45         $self->walk_down($outline, $context, 0, []); 
     42    my $handler = Plagger::Plugin::Subscription::OPML::SAXHandler->new( 
     43        callback => sub { $context->subscription->add(@_) }, 
     44    ); 
     45 
     46    my $parser  = XML::LibXML::SAX->new(Handler => $handler); 
     47       $parser->parse_string($xml); 
     48
     49 
     50package Plagger::Plugin::Subscription::OPML::SAXHandler; 
     51use base qw( XML::SAX::Base ); 
     52 
     53sub new { 
     54    my $class = shift; 
     55    bless { @_ }, $class; 
     56
     57 
     58sub start_element { 
     59    my $self = shift; 
     60    my($ref) = @_; 
     61 
     62    if ($ref->{LocalName} eq 'outline') { 
     63        if (_attr($ref, 'htmlUrl', 'xmlUrl')) { 
     64            my $feed = Plagger::Feed->new; 
     65            $feed->url(_attr($ref, 'xmlUrl')); 
     66            $feed->link(_attr($ref, 'htmlUrl')); 
     67            $feed->title(_attr($ref, 'title', 'text')); 
     68            $feed->tags([ grep { defined && $_ ne 'Subscriptions' } @{$self->{containers}} ]); 
     69            $self->{callback}->($feed); 
     70        } else { 
     71            my $tag = _attr($ref, 'title', 'text'); 
     72            push @{$self->{containers}}, $tag; 
     73        } 
    4674    } 
    4775} 
    4876 
    49 sub walk_down { 
    50     my($self, $outline, $context, $depth, $containers) = @_; 
     77sub end_element { 
     78    my $self = shift; 
     79    my($ref) = @_; 
    5180 
    52     if (delete $outline->{opmlvalue}) { 
    53         my $title = delete $outline->{title} || delete $outline->{text}; 
    54         push @$containers, $title if $title ne 'Subscriptions'; 
    55         for my $channel (values %$outline) { 
    56             $self->walk_down($channel, $context, $depth + 1, $containers); 
    57         } 
    58         pop @$containers if $title ne 'Subscriptions'; 
    59     } else { 
    60         my $feed = Plagger::Feed->new; 
    61         $feed->url($outline->{xmlUrl}); 
    62         $feed->link($outline->{htmlUrl}); 
    63         $feed->title($outline->{title} || $outline->{text}); 
    64         $feed->tags([ @$containers ]); 
    65         $context->subscription->add($feed); 
     81    if ($ref->{LocalName} eq 'outline') { 
     82        pop @{$self->{containers}}; 
    6683    } 
    6784} 
     85 
     86sub _attr { 
     87    my($ref, @attr) = @_; 
     88 
     89    for my $attr (@attr) { 
     90        return $ref->{Attributes}->{"{}$attr"}->{Value} 
     91            if defined $ref->{Attributes}->{"{}$attr"}; 
     92    } 
     93 
     94    return; 
     95} 
     96 
     97package Plagger::Plugin::Subscription::OPML; 
    6898 
    69991; 
     
    93123=head1 SEE ALSO 
    94124 
    95 L<Plagger>, L<XML::OPML
     125L<Plagger>, L<XML::LibXML::SAX
    96126 
    97127=cut 
  • trunk/plagger/t/plugins/Subscription-OPML/subscription.t

    r1499 r1500  
    44test_plugin_deps; 
    55plan 'no_plan'; 
    6  
    7 diag "This test will raise warnings due to XML::OPML internal, but it's harmless"; 
    86run_eval_expected; 
    97 
     
    4139is $feeds[1]->title, "Bulknews::Subtech"; 
    4240is_deeply $feeds[1]->tags, [ 'Bar', 'Baz' ]; 
    43  
  • trunk/plagger/t/plugins/Subscription-Odeo/subscription.t

    r1467 r1500  
    66test_plugin_deps; 
    77plan tests => 4; 
    8 diag "This test will raise warnings due to XML::OPML internal, but it's harmless"; 
    98run_eval_expected; 
    109