File Coverage

blib/lib/XML/RSS/LibXML/V0_9.pm
Criterion Covered Total %
statement 12 139 8.6
branch 0 32 0.0
condition 0 13 0.0
subroutine 4 17 23.5
pod 0 13 0.0
total 16 214 7.4


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_9;
7 1     1   2525 use strict;
  1         3  
  1         31  
8 1     1   5 use base qw(XML::RSS::LibXML::ImplBase);
  1         2  
  1         76  
9 1     1   5 use Carp qw(croak);
  1         2  
  1         60  
10 1     1   5 use XML::RSS::LibXML::Namespaces qw(NS_RSS09 NS_RDF);
  1         2  
  1         2067  
11              
12             my $format_dates = sub {
13             my $v = eval {
14             DateTime::Format::W3CDTF->format_datetime(
15             DateTime::Format::Mail->parse_datetime($_[0])
16             );
17             };
18             if ($v && ! $@) {
19             $_[0] = $v;
20             }
21             };
22              
23             my %DcElements = (
24             'dc:date' => {
25             candidates => [
26             { module => 'dc', element => 'date' },
27             'pubDate',
28             'lastBuildDate',
29             ],
30             callback => $format_dates
31             },
32             (map { ("dc:$_" => [ { module => 'dc', element => $_ } ]) }
33             qw(language rights publisher creator title subject description contributer type format identifier source relation coverage)),
34             );
35              
36             my %ImageElements = (
37             (map { ($_ => [$_]) } qw(title url link)),
38             %DcElements,
39             );
40              
41             my %TextInputElements = (
42             (map { ($_ => [$_]) } qw(title link description name)),
43             %DcElements
44             );
45              
46             sub definition
47             {
48             return {
49 0     0 0   channel => {
50             title => '',
51             description => '',
52             link => '',
53             },
54             image => bless({
55             title => undef,
56             url => undef,
57             link => undef,
58             }, 'XML::RSS::LibXML::ElementSpec'),
59             textinput => bless({
60             title => undef,
61             description => undef,
62             name => undef,
63             link => undef,
64             }, 'XML::RSS::LibXML::ElementSpec'),
65             },
66             }
67              
68             sub accessor_definition
69             {
70             return +{
71 0     0 0   channel => {
72             "title" => [1, 40],
73             "description" => [1, 500],
74             "link" => [1, 500]
75             },
76             image => {
77             "title" => [1, 40],
78             "url" => [1, 500],
79             "link" => [1, 500]
80             },
81             item => {
82             "title" => [1, 100],
83             "link" => [1, 500]
84             },
85             textinput => {
86             "title" => [1, 40],
87             "description" => [1, 100],
88             "name" => [1, 500],
89             "link" => [1, 500]
90             }
91             }
92             }
93              
94             sub parse_dom
95             {
96 0     0 0   my $self = shift;
97 0           my $c = shift;
98 0           my $dom = shift;
99              
100 0           $c->reset;
101 0           $c->version(0.9);
102 0           $c->encoding($dom->encoding);
103 0           $self->parse_namespaces($c, $dom);
104 0           $c->internal('prefix', 'rss09');
105             # Check if we have non-default RSS namespace
106 0           my $namespaces = $c->namespaces;
107 0           while (my($prefix, $uri) = each %$namespaces) {
108 0 0 0       if ($uri eq NS_RSS09 && $prefix ne '#default') {
109 0           $c->internal('prefix', $prefix);
110 0           last;
111             }
112             }
113              
114 0           $dom->getDocumentElement()->setNamespace(NS_RSS09, $c->internal('prefix'), 0);
115 0           $self->parse_channel($c, $dom);
116 0           $self->parse_items($c, $dom);
117 0           $self->parse_misc_simple($c, $dom);
118             }
119              
120             sub parse_namespaces
121             {
122 0     0 0   my ($self, $c, $dom) = @_;
123              
124 0           $self->SUPER::parse_namespaces($c, $dom);
125              
126 0           my $namespaces = $c->namespaces;
127 0           while (my($prefix, $uri) = each %$namespaces) {
128 0 0         if ($uri eq NS_RSS09) {
129            
130             }
131             }
132             }
133              
134             sub parse_channel
135             {
136 0     0 0   my ($self, $c, $dom) = @_;
137              
138 0           my $xc = $c->create_xpath_context($c->{namespaces});
139              
140 0           my ($root) = $xc->findnodes('/rdf:RDF/rss09:channel', $dom);
141 0           my %h = $self->parse_children($c, $root);
142 0           foreach my $field (qw(textinput image)) {
143 0           delete $h{$field};
144             # if (my $v = $h{$field}) {
145             # $c->$field(UNIVERSAL::isa($v, 'XML::RSS::LibXML::MagicElement') ? $v : %$v);
146             # }
147             }
148 0           $c->channel(%h);
149             }
150              
151             sub parse_items
152             {
153 0     0 0   my $self = shift;
154 0           my $c = shift;
155 0           my $dom = shift;
156              
157 0           my @items;
158              
159 0           my $version = $c->version;
160 0           my $xc = $c->create_xpath_context($c->{namespaces});
161 0           my $xpath = '/rdf:RDF/rss09:item';
162 0           foreach my $item ($xc->findnodes($xpath, $dom)) {
163 0           my $i = $self->parse_children($c, $item);
164 0           $self->add_item($c, $i);
165             }
166             }
167              
168             sub parse_misc_simple
169             {
170 0     0 0   my ($self, $c, $dom) = @_;
171              
172 0           my $xc = $c->create_xpath_context($c->{namespaces});
173 0           foreach my $node ($xc->findnodes('/rdf:RDF/*[name() != "channel" and name() != "item"]', $dom)) {
174 0           my $h = $self->parse_children($c, $node);
175 0           my $name = $node->localname;
176 0 0         $name = 'textinput' if $name eq 'textInput';
177 0           my $prefix = $node->getPrefix();
178 0 0         if ($prefix) {
179 0   0       $c->{$prefix} ||= {};
180 0           $self->store_element($c->{$prefix}, $name, $h);
181              
182             # XML::RSS requires us to allow access to elements both from
183             # the prefix and the namespace
184 0   0       $c->{$c->{namespaces}{$prefix}} ||= {};
185 0           $self->store_element($c->{$c->{namespaces}{$prefix}}, $name, $h);
186             } else {
187 0           $self->store_element($c, $name, $h);
188             }
189             }
190             }
191              
192             sub validate_item
193             {
194 0     0 0   my $self = shift;
195 0           my $c = shift;
196 0           my $h = shift;
197              
198             # make sure we have a title and link
199 0 0 0       croak "title and link elements are required"
200             unless (defined $h->{title} && defined $h->{'link'});
201              
202             # check string lengths
203 0 0         croak "title cannot exceed 100 characters in length"
204             if (length($h->{title}) > 100);
205 0 0         croak "link cannot exceed 500 characters in length"
206             if (length($h->{'link'}) > 500);
207 0 0 0       croak "description cannot exceed 500 characters in length"
208             if (exists($h->{description})
209             && length($h->{description}) > 500);
210              
211             # make sure there aren't already 15 items
212 0 0         croak "total items cannot exceed 15 " if (@{$c->items} >= 15);
  0            
213             }
214              
215             sub create_dom
216             {
217 0     0 0   my ($self, $c) = @_;
218              
219 0           my $dom = $self->SUPER::create_dom($c);
220 0           my $xc = $c->create_xpath_context($c->namespaces);
221 0           my ($channel) = $xc->findnodes('/rdf:RDF/channel', $dom);
222 0           my $root = $dom->getDocumentElement();
223 0 0         if (my $image = $c->image) {
224 0           my $inode;
225              
226 0           $inode = $dom->createElement('image');
227 0 0         $inode->setAttribute('rdf:resource', $image->{url}) if defined $image->{url};
228 0           $channel->appendChild($inode);
229              
230 0           $inode = $dom->createElement('image');
231 0 0         $inode->setAttribute('rdf:resource', $image->{url}) if defined $image->{url};
232 0           $self->create_element_from_spec($image, $dom, $inode, \%ImageElements);
233 0           $self->create_extra_modules($image, $dom, $inode, $c->namespaces);
234 0           $root->appendChild($inode);
235             }
236              
237 0 0         if (my $textinput = $c->textinput) {
238 0           my $inode;
239              
240 0           $inode = $dom->createElement('textinput');
241 0 0         $inode->setAttribute('rdf:resource', $textinput->{link}) if $textinput->{link};
242 0           $channel->appendChild($inode);
243              
244 0           $inode = $dom->createElement('textinput');
245 0 0         $inode->setAttribute('rdf:resource', $textinput->{link}) if $textinput->{link};
246 0           $self->create_element_from_spec($textinput, $dom, $inode, \%TextInputElements);
247 0           $self->create_extra_modules($textinput, $dom, $inode, $c->namespaces);
248 0           $root->appendChild($inode);
249             }
250              
251 0           return $dom;
252             }
253              
254             sub create_rootelement
255             {
256 0     0 0   my $self = shift;
257 0           my $c = shift;
258 0           my $dom = shift;
259              
260 0           my $e = $dom->createElementNS(NS_RSS09, 'RDF');
261 0           $dom->setDocumentElement($e);
262 0           $e->setNamespace(NS_RDF, 'rdf', 1);
263 0           $c->add_module(prefix => 'rdf', uri => NS_RDF);
264             }
265              
266             sub create_channel
267             {
268 0     0 0   my $self = shift;
269 0           my $c = shift;
270 0           my $dom = shift;
271 0           my $root = $dom->getDocumentElement();
272              
273 0           my $channel = $dom->createElement('channel');
274 0           $root->appendChild($channel);
275              
276 0           my $node;
277 0           foreach my $p (qw(title link description)) {
278 0           my $text = $c->{channel}{$p};
279 0 0         next unless defined $text;
280 0           $node = $dom->createElement($p);
281 0           $node->appendText($c->{channel}{$p});
282 0           $channel->appendChild($node);
283             }
284             }
285              
286             sub create_items
287             {
288 0     0 0   my $self = shift;
289 0           my $c = shift;
290 0           my $dom = shift;
291 0           my $root = $dom->getDocumentElement();
292              
293 0           foreach my $i ($c->items) {
294 0           my $item = $self->create_item($c, $dom, $i);
295 0           $root->appendChild($item);
296             }
297             }
298              
299             sub create_item
300             {
301 0     0 0   my $self = shift;
302 0           my $c = shift;
303 0           my $dom = shift;
304 0           my $i = shift;
305              
306 0           my $item = $dom->createElement('item');
307 0           my $node;
308 0           foreach my $e (qw(title link)) {
309 0           $node = $dom->createElement($e);
310 0           $node->appendText($i->{$e});
311 0           $item->addChild($node);
312             }
313 0           return $item;
314             }
315              
316             1;