# $Id: /mirror/perl/XML-RSS-LibXML/trunk/lib/XML/RSS/LibXML/V0_91.pm 2259 2007-05-07T14:41:59.593216Z daisuke $ # # Copyright (c) 2005-2007 Daisuke Maki # All rights reserved. package XML::RSS::LibXML::V0_91; use strict; use warnings; use base qw(XML::RSS::LibXML::ImplBase); use DateTime::Format::W3CDTF; use DateTime::Format::Mail; my %DcElements = ( (map { ("dc:$_" => [ { module => 'dc', element => $_ } ]) } qw(language rights date publisher creator title subject description contributer type format identifier source relation coverage)), ); my %SynElements = ( (map { ("syn:$_" => [ { module => 'syn', element => $_ } ]) } qw(updateBase updateFrequency updatePeriod)), ); my $format_dates = sub { my $v = eval { DateTime::Format::Mail->format_datetime( DateTime::Format::W3CDTF->parse_datetime($_[0]) ); }; if ($v && ! $@) { $_[0] = $v; } }; my %ChannelElements = ( %DcElements, %SynElements, (map { ($_ => [ $_ ]) } qw(title link description)), language => [ { module => 'dc', element => 'language' }, 'language' ], copyright => [ { module => 'dc', element => 'rights' }, 'copyright' ], pubDate => { candidates => [ 'pubDate', { module => 'dc', element => 'date' } ], callback => $format_dates, }, lastBuildDate => { candidates => [ { module => 'dc', element => 'date' }, 'lastBuildDate' ], callback => $format_dates, }, docs => [ 'docs' ], managingEditor => [ { module => 'dc', element => 'publisher' }, 'managingEditor' ], webMaster => [ { module => 'dc', element => 'creator' }, 'webMaster' ], category => [ { module => 'dc', element => 'category' }, 'category' ], generator => [ { module => 'dc', element => 'generator' }, 'generator' ], ttl => [ { module => 'dc', element => 'ttl' }, 'ttl' ], rating => [ 'rating' ], ); delete $ChannelElements{'dc:creator'}; my %ItemElements = ( %DcElements, map { ($_ => [$_]) } qw(title link description author category comments pubDate) ); my %ImageElements = ( (map { ($_ => [$_]) } qw(title url link description width height)), %DcElements, ); my %TextInputElements = ( (map { ($_ => [$_]) } qw(title link description name)), %DcElements ); sub definition { return +{ channel => { title => '', copyright => undef, description => '', docs => undef, language => undef, lastBuildDate => undef, 'link' => '', managingEditor => undef, pubDate => undef, rating => undef, webMaster => undef, }, image => bless({ title => undef, url => undef, 'link' => undef, width => undef, height => undef, description => undef, }, 'XML::RSS::LibXML::ElementSpec'), skipDays => {day => undef,}, skipHours => {hour => undef,}, textinput => bless({ title => undef, description => undef, name => undef, 'link' => undef, }, 'XML::RSS::LibXML::ElementSpec'), } } sub accessor_definition { return +{ channel => { "title" => [1, 100], "description" => [1, 500], "link" => [1, 500], "language" => [1, 5], "rating" => [0, 500], "copyright" => [0, 100], "pubDate" => [0, 100], "lastBuildDate" => [0, 100], "docs" => [0, 500], "managingEditor" => [0, 100], "webMaster" => [0, 100], }, image => { "title" => [1, 100], "url" => [1, 500], "link" => [0, 500], "width" => [0, 144], "height" => [0, 400], "description" => [0, 500] }, item => { "title" => [1, 100], "link" => [1, 500], "description" => [0, 500] }, textinput => { "title" => [1, 100], "description" => [1, 500], "name" => [1, 20], "link" => [1, 500] }, skipHours => {"hour" => [1, 23]}, skipDays => {"day" => [1, 10]} } } sub parse_dom { my $self = shift; my $c = shift; my $dom = shift; $c->reset; $c->version('0.91'); $self->parse_namespaces($c, $dom); $self->parse_channel($c, $dom); $self->parse_items($c, $dom); } sub parse_channel { my ($self, $c, $dom) = @_; my $xc = $c->create_xpath_context($c->{namespaces}); my ($root) = $xc->findnodes('/rss/channel', $dom); my %h = $self->parse_children($c, $root); foreach my $type qw(day hour) { my $field = 'skip' . ucfirst($type) . 's'; if (my $skip = delete $h{$field}) { $c->$field(%$skip); } } $c->channel(%h); } sub parse_items { my $self = shift; my $c = shift; my $dom = shift; my @items; my $version = $c->version; my $xc = $c->create_xpath_context($c->{namespaces}); my $xpath = '/rss/channel/item'; foreach my $item ($xc->findnodes($xpath, $dom)) { my $i = $self->parse_children($c, $item); $self->add_item($c, $i); } } sub create_dtd { my $self = shift; my $c = shift; my $dom = shift; my $dtd = $dom->createExternalSubset( 'rss', '-//Netscape Communications//DTD RSS 0.91//EN', 'http://my.netscape.com/publish/formats/rss-0.91.dtd' ); $dom->setInternalSubset($dtd); } sub create_rootelement { my ($self, $c, $dom) = @_; my $root = $dom->createElement('rss'); $root->setAttribute(version => '0.91'); $dom->setDocumentElement($root); } sub create_channel { my ($self, $c, $dom) = @_; my $root = $dom->getDocumentElement(); my $channel = $dom->createElement('channel'); $self->create_element_from_spec($c->channel, $dom, $channel, \%ChannelElements); if (my $image = $c->image) { if (! UNIVERSAL::isa($image, 'XML::RSS::LibXML::ElementSpec')) { my $inode; $inode = $dom->createElement('image'); $self->create_element_from_spec($image, $dom, $inode, \%ImageElements); $self->create_extra_modules($image, $dom, $inode, $c->namespaces); $channel->appendChild($inode); } } if (my $textinput = $c->textinput) { if (! UNIVERSAL::isa($textinput, 'XML::RSS::LibXML::ElementSpec')) { my $inode; $inode = $dom->createElement('textinput'); $self->create_element_from_spec($textinput, $dom, $inode, \%TextInputElements); $self->create_extra_modules($textinput, $dom, $inode, $c->namespaces); $channel->appendChild($inode); } } foreach my $type qw(day hour) { my $field = 'skip' . ucfirst($type) . 's'; my $skip = $c->$field; if ($skip && defined $skip->{$type}) { my $sd = $dom->createElement($field); my $d = $dom->createElement($type); $d->appendChild($dom->createTextNode($skip->{$type})); $sd->appendChild($d); $channel->appendChild($sd); } } $root->appendChild($channel); } sub create_items { my ($self, $c, $dom) = @_; my ($channel) = $dom->findnodes('/rss/channel'); foreach my $i ($c->items) { my $item = $dom->createElement('item'); $self->create_element_from_spec($i, $dom, $item, \%ItemElements); $channel->appendChild($item); } } 1;