File Coverage

blib/lib/XML/RSS/LibXML/V0_91.pm
Criterion Covered Total %
statement 15 88 17.0
branch 0 12 0.0
condition 0 3 0.0
subroutine 5 14 35.7
pod 0 9 0.0
total 20 126 15.8


line stmt bran cond sub pod time code
1             # $Id$
2             #
3             # Copyright (c) 2005-2007 Daisuke Maki
4             # All rights reserved.
5              
6             package XML::RSS::LibXML::V0_91;
7 1     1   5 use strict;
  1         2  
  1         26  
8 1     1   5 use warnings;
  1         1  
  1         21  
9 1     1   4 use base qw(XML::RSS::LibXML::ImplBase);
  1         2  
  1         74  
10 1     1   5 use DateTime::Format::W3CDTF;
  1         1  
  1         9  
11 1     1   26 use DateTime::Format::Mail;
  1         1  
  1         6  
12              
13             my %DcElements = (
14             (map { ("dc:$_" => [ { module => 'dc', element => $_ } ]) }
15             qw(language rights date publisher creator title subject description contributer type format identifier source relation coverage)),
16             );
17            
18             my %SynElements = (
19             (map { ("syn:$_" => [ { module => 'syn', element => $_ } ]) }
20             qw(updateBase updateFrequency updatePeriod)),
21             );
22              
23             my $format_dates = sub {
24             my $v = eval {
25             DateTime::Format::Mail->format_datetime(
26             DateTime::Format::W3CDTF->parse_datetime($_[0])
27             );
28             };
29             if ($v && ! $@) {
30             $_[0] = $v;
31             }
32             };
33              
34             my %ChannelElements = (
35             %DcElements,
36             %SynElements,
37             (map { ($_ => [ $_ ]) } qw(title link description)),
38             language => [ { module => 'dc', element => 'language' }, 'language' ],
39             copyright => [ { module => 'dc', element => 'rights' }, 'copyright' ],
40             pubDate => {
41             candidates => [ 'pubDate', { module => 'dc', element => 'date' } ],
42             callback => $format_dates,
43             },
44             lastBuildDate => {
45             candidates => [ { module => 'dc', element => 'date' }, 'lastBuildDate' ],
46             callback => $format_dates,
47             },
48             docs => [ 'docs' ],
49             managingEditor => [ { module => 'dc', element => 'publisher' }, 'managingEditor' ],
50             webMaster => [ { module => 'dc', element => 'creator' }, 'webMaster' ],
51             category => [ { module => 'dc', element => 'category' }, 'category' ],
52             generator => [ { module => 'dc', element => 'generator' }, 'generator' ],
53             ttl => [ { module => 'dc', element => 'ttl' }, 'ttl' ],
54             rating => [ 'rating' ],
55             );
56             delete $ChannelElements{'dc:creator'};
57              
58             my %ItemElements = (
59             %DcElements,
60             map { ($_ => [$_]) }
61             qw(title link description author category comments pubDate)
62             );
63              
64             my %ImageElements = (
65             (map { ($_ => [$_]) } qw(title url link description width height)),
66             %DcElements,
67             );
68              
69             my %TextInputElements = (
70             (map { ($_ => [$_]) } qw(title link description name)),
71             %DcElements
72             );
73              
74             sub definition
75             {
76             return +{
77 0     0 0   channel => {
78             title => '',
79             copyright => undef,
80             description => '',
81             docs => undef,
82             language => undef,
83             lastBuildDate => undef,
84             'link' => '',
85             managingEditor => undef,
86             pubDate => undef,
87             rating => undef,
88             webMaster => undef,
89             },
90             image => bless({
91             title => undef,
92             url => undef,
93             'link' => undef,
94             width => undef,
95             height => undef,
96             description => undef,
97             }, 'XML::RSS::LibXML::ElementSpec'),
98             skipDays => {day => undef,},
99             skipHours => {hour => undef,},
100             textinput => bless({
101             title => undef,
102             description => undef,
103             name => undef,
104             'link' => undef,
105             }, 'XML::RSS::LibXML::ElementSpec'),
106             }
107             }
108              
109             sub accessor_definition
110             {
111             return +{
112 0     0 0   channel => {
113             "title" => [1, 100],
114             "description" => [1, 500],
115             "link" => [1, 500],
116             "language" => [1, 5],
117             "rating" => [0, 500],
118             "copyright" => [0, 100],
119             "pubDate" => [0, 100],
120             "lastBuildDate" => [0, 100],
121             "docs" => [0, 500],
122             "managingEditor" => [0, 100],
123             "webMaster" => [0, 100],
124             },
125             image => {
126             "title" => [1, 100],
127             "url" => [1, 500],
128             "link" => [0, 500],
129             "width" => [0, 144],
130             "height" => [0, 400],
131             "description" => [0, 500]
132             },
133             item => {
134             "title" => [1, 100],
135             "link" => [1, 500],
136             "description" => [0, 500]
137             },
138             textinput => {
139             "title" => [1, 100],
140             "description" => [1, 500],
141             "name" => [1, 20],
142             "link" => [1, 500]
143             },
144             skipHours => {"hour" => [1, 23]},
145             skipDays => {"day" => [1, 10]}
146             }
147             }
148              
149             sub parse_dom
150             {
151 0     0 0   my $self = shift;
152 0           my $c = shift;
153 0           my $dom = shift;
154              
155 0           $c->reset;
156 0           $c->version('0.91');
157 0           $c->encoding($dom->encoding);
158 0           $self->parse_namespaces($c, $dom);
159 0           $self->parse_channel($c, $dom);
160 0           $self->parse_items($c, $dom);
161             }
162              
163             sub parse_channel
164             {
165 0     0 0   my ($self, $c, $dom) = @_;
166              
167 0           my $xc = $c->create_xpath_context($c->{namespaces});
168              
169 0           my ($root) = $xc->findnodes('/rss/channel', $dom);
170 0           my %h = $self->parse_children($c, $root);
171              
172 0           foreach my $type (qw(day hour)) {
173 0           my $field = 'skip' . ucfirst($type) . 's';
174 0 0         if (my $skip = delete $h{$field}) {
175 0           $c->$field(%$skip);
176             }
177             }
178 0           $c->channel(%h);
179             }
180              
181             sub parse_items
182             {
183 0     0 0   my $self = shift;
184 0           my $c = shift;
185 0           my $dom = shift;
186              
187 0           my @items;
188              
189 0           my $version = $c->version;
190 0           my $xc = $c->create_xpath_context($c->{namespaces});
191 0           my $xpath = '/rss/channel/item';
192 0           foreach my $item ($xc->findnodes($xpath, $dom)) {
193 0           my $i = $self->parse_children($c, $item);
194 0           $self->add_item($c, $i);
195             }
196             }
197              
198             sub create_dtd
199             {
200 0     0 0   my $self = shift;
201 0           my $c = shift;
202 0           my $dom = shift;
203              
204 0           my $dtd = $dom->createExternalSubset(
205             'rss',
206             '-//Netscape Communications//DTD RSS 0.91//EN',
207             'http://my.netscape.com/publish/formats/rss-0.91.dtd'
208             );
209 0           $dom->setInternalSubset($dtd);
210             }
211              
212             sub create_rootelement
213             {
214 0     0 0   my ($self, $c, $dom) = @_;
215              
216 0           my $root = $dom->createElement('rss');
217 0           $root->setAttribute(version => '0.91');
218 0           $dom->setDocumentElement($root);
219             }
220              
221             sub create_channel
222             {
223 0     0 0   my ($self, $c, $dom) = @_;
224              
225 0           my $root = $dom->getDocumentElement();
226 0           my $channel = $dom->createElement('channel');
227 0           $self->create_element_from_spec($c->channel, $dom, $channel, \%ChannelElements);
228              
229 0 0         if (my $image = $c->image) {
230 0 0         if (! UNIVERSAL::isa($image, 'XML::RSS::LibXML::ElementSpec')) {
231 0           my $inode;
232              
233 0           $inode = $dom->createElement('image');
234 0           $self->create_element_from_spec($image, $dom, $inode, \%ImageElements);
235 0           $self->create_extra_modules($image, $dom, $inode, $c->namespaces);
236 0           $channel->appendChild($inode);
237             }
238             }
239              
240 0 0         if (my $textinput = $c->textinput) {
241 0 0         if (! UNIVERSAL::isa($textinput, 'XML::RSS::LibXML::ElementSpec')) {
242 0           my $inode;
243              
244 0           $inode = $dom->createElement('textinput');
245 0           $self->create_element_from_spec($textinput, $dom, $inode, \%TextInputElements);
246 0           $self->create_extra_modules($textinput, $dom, $inode, $c->namespaces);
247 0           $channel->appendChild($inode);
248             }
249             }
250              
251 0           foreach my $type (qw(day hour)) {
252 0           my $field = 'skip' . ucfirst($type) . 's';
253 0           my $skip = $c->$field;
254 0 0 0       if ($skip && defined $skip->{$type}) {
255 0           my $sd = $dom->createElement($field);
256 0           my $d = $dom->createElement($type);
257 0           $d->appendChild($dom->createTextNode($skip->{$type}));
258 0           $sd->appendChild($d);
259 0           $channel->appendChild($sd);
260             }
261             }
262 0           $root->appendChild($channel);
263             }
264              
265             sub create_items
266             {
267 0     0 0   my ($self, $c, $dom) = @_;
268              
269 0           my ($channel) = $dom->findnodes('/rss/channel');
270 0           foreach my $i ($c->items) {
271 0           my $item = $dom->createElement('item');
272 0           $self->create_element_from_spec($i, $dom, $item, \%ItemElements);
273              
274 0           $channel->appendChild($item);
275             }
276             }
277              
278             1;