File Coverage

blib/lib/XML/RSS/LibXML/V1_0.pm
Criterion Covered Total %
statement 18 136 13.2
branch 0 30 0.0
condition 0 16 0.0
subroutine 6 15 40.0
pod 0 9 0.0
total 24 206 11.6


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