From 7cc5b20f6e52c43b722721ce85b61d4020a95955 Mon Sep 17 00:00:00 2001
From: miker
Date: Mon, 6 Mar 2006 20:17:26 +0000
Subject: [PATCH] refactoring to generic "feeds"; adding opensearch target
git-svn-id: svn://svn.open-ils.org/ILS/trunk@3271 dcc99617-32d9-48b4-a31d-7c20da2025e4
---
Open-ILS/src/perlmods/OpenILS/WWW/SuperCat.pm | 455 +++++-------------
.../src/perlmods/OpenILS/WWW/SuperCat/Feed.pm | 328 +++++++++++++
2 files changed, 447 insertions(+), 336 deletions(-)
create mode 100644 Open-ILS/src/perlmods/OpenILS/WWW/SuperCat/Feed.pm
diff --git a/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat.pm b/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat.pm
index da97a972de..2c5dbc0723 100644
--- a/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat.pm
+++ b/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat.pm
@@ -19,10 +19,11 @@ use XML::LibXML;
use Unicode::Normalize;
use OpenILS::Utils::Fieldmapper;
+use OpenILS::WWW::SuperCat::Feed;
# set the bootstrap config when this module is loaded
-my ($bootstrap, $supercat, $actor, $parser);
+my ($bootstrap, $supercat, $actor, $parser, $search);
sub import {
my $self = shift;
@@ -34,6 +35,7 @@ sub child_init {
OpenSRF::System->bootstrap_client( config_file => $bootstrap );
$supercat = OpenSRF::AppSession->create('open-ils.supercat');
$actor = OpenSRF::AppSession->create('open-ils.actor');
+ $search = OpenSRF::AppSession->create('open-ils.search');
$parser = new XML::LibXML;
}
@@ -289,6 +291,7 @@ sub bookbag_feed {
my $host = $cgi->virtual_host || $cgi->server_name;
my $path = $apache->path_info;
+ my $base = $cgi->url;
my ($id,$type) = reverse split '/', $path;
@@ -305,389 +308,169 @@ sub bookbag_feed {
$feed->creator($host);
$feed->update_ts(gmtime_ISO8601());
- $feed->link(atom => $id);
- $feed->link(rss2 => $id);
- $feed->link(html => $id);
+ $feed->link(atom => $base . "/bookbag/atom/$id");
+ $feed->link(rss2 => $base . "/bookbag/rss2/$id");
+ $feed->link(html => $base . "/bookbag/html/$id");
print entityize($feed->toString) . "\n";
return Apache2::Const::OK;
}
-sub create_record_feed {
- my $type = shift;
- my $records = shift;
- my $unapi = shift;
+sub opensearch_feed {
+ my $apache = shift;
+ return Apache2::Const::DECLINED if (-e $apache->filename);
+
+ print "Content-type: application/xml; charset=utf-8\n\n";
my $cgi = new CGI;
- my $base = $cgi->url;
- my $host = $cgi->virtual_host || $cgi->server_name;
+ (my $unapi = $cgi->url) =~ s{[^/]+/?$}{unapi};
my $year = (gmtime())[5];
- my $feed = new OpenILS::WWW::SuperCat::Feed ($type);
- $feed->base($base);
- $feed->unapi($unapi);
-
- for my $rec (@$records) {
- my $item_tag = "tag:$host,$year:biblio-record_entry/" . $rec;
-
- my $xml = $supercat->request(
- "open-ils.supercat.record.$type.retrieve",
- $rec
- )->gather(1);
-
- my $node = $feed->add_item($xml);
-
- $node->id($item_tag);
- $node->link(unapi => $item_tag);
- }
-
- return $feed;
-}
-
-sub entityize {
- my $stuff = NFC(shift());
- $stuff =~ s/([\x{0080}-\x{fffd}])/sprintf('%X;',ord($1))/sgoe;
- return $stuff;
-}
-
-package OpenILS::WWW::SuperCat::Feed;
-
-sub new {
- my $class = shift;
- my $type = shift;
- if ($type) {
- $class .= '::'.$type;
- return $class->new;
- }
- throw OpenSRF::EX::ERROR ("I need a feed type!") ;
-}
-
-sub build {
- my $class = shift;
- my $xml = shift;
-
- my $self = { doc => $parser->parse_string($xml), items => [] };
-
- return bless $self => $class;
-}
-
-sub base {
- my $self = shift;
- my $base = shift;
- $self->{base} = $base if ($base);
- return $self->{base};
-}
-
-sub unapi {
- my $self = shift;
- my $unapi = shift;
- $self->{unapi} = $unapi if ($unapi);
- return $self->{unapi};
-}
-
-sub push_item {
- my $self = shift;
- push @{ $self->{items} }, @_;
-}
-
-sub items {
- my $self = shift;
- return @{ $self->{items} } if (wantarray);
- return $self->{items};
-}
-
-sub _add_node {
- my $self = shift;
+ my $host = $cgi->virtual_host || $cgi->server_name;
+ my $base = $cgi->url;
+ my $path = $apache->path_info;
- my $xpath = shift;
- my $new = shift;
+ my $page = $cgi->param('startPage') || 1;
+ my $offset = $cgi->param('startIndex') || 1;
+ my $limit = $cgi->param('count') || 10;
- for my $node ($self->{doc}->findnodes($xpath)) {
- $node->appendChild($new);
- last;
+ if ($page > 1) {
+ $offset = ($page - 1) * $limit;
+ } else {
+ $offset -= 1;
}
-}
-sub _create_node {
- my $self = shift;
-
- my $xpath = shift;
- my $ns = shift;
- my $name = shift;
- my $text = shift;
- my $attrs = shift;
-
- for my $node ($self->{doc}->findnodes($xpath)) {
- my $new = $self->{doc}->createElement($name) if (!$ns);
- $new = $self->{doc}->createElementNS($ns,$name) if ($ns);
-
- $new->appendChild( $self->{doc}->createTextNode( $text ) )
- if ($text);
-
- if (ref($attrs)) {
- for my $key (keys %$attrs) {
- $new->setAttribute( $key => $$attrs{$key} );
- }
- }
-
- $node->appendChild( $new );
+ my ($terms,$class,$type,$version) = reverse split '/', $path;
- return $new;
+ if ($version eq '1.0') {
+ $type = 'rss2';
+ } elsif ($type eq '-') {
+ $type = 'atom';
}
-}
-sub add_item {
- my $self = shift;
- my $class = ref($self) || $self;
- $class .= '::item';
-
- my $item_xml = shift;
- my $entry = $class->new($item_xml);
+ $class = 'keyword' if ($class eq '-');
+ $terms =~ s/\+/ /go;
- $entry->base($self->base);
- $entry->unapi($self->unapi);
+ warn "searching for $class -> [$terms] via OS $version, response type $type";
- $self->push_item($entry);
- return $entry;
-}
-
-sub toString {
- my $self = shift;
- for my $root ( $self->{doc}->findnodes($self->{item_xpath}) ) {
- for my $item ( $self->items ) {
- $root->appendChild( $item->{doc}->documentElement );
+ my $recs = $search->request(
+ 'open-ils.search.biblio.record.class.search' => $class,
+ { term => $terms,
+ org_unit => 1,
+ limit => $limit,
+ offset => $offset,
}
- last;
- }
-
- return $self->{doc}->toString;
-}
-
-sub id {};
-sub link {};
-sub title {};
-sub update_ts {};
-sub creator {};
+ )->gather(1);
-#----------------------------------------------------------
-
-package OpenILS::WWW::SuperCat::Feed::atom;
-use base 'OpenILS::WWW::SuperCat::Feed';
-
-sub new {
- my $class = shift;
- my $self = $class->SUPER::build('');
- $self->{type} = 'atom';
- $self->{item_xpath} = '/atom:feed';
- return $self;
-}
-
-sub title {
- my $self = shift;
- my $text = shift;
- $self->_create_node('/atom:feed','http://www.w3.org/2005/Atom','atom:title', $text);
-}
-
-sub update_ts {
- my $self = shift;
- my $text = shift;
- $self->_create_node('/atom:feed','http://www.w3.org/2005/Atom','atom:updated', $text);
-}
-
-sub creator {
- my $self = shift;
- my $text = shift;
- $self->_create_node('/atom:feed','http://www.w3.org/2005/Atom','atom:author');
- $self->_create_node('/atom:feed/atom:author', 'http://www.w3.org/2005/Atom','atom:name', $text);
-}
-
-sub link {
- my $self = shift;
- my $type = shift;
- my $id = shift;
-
- $self->_create_node(
- '/atom:feed',
- 'http://www.w3.org/2005/Atom',
- 'atom:link',
- undef,
- { rel => $type,
- href => $self->base . '/' . $type . '/' . $id,
- type => "application/$type+xml",
- }
+ my $feed = create_record_feed(
+ $type,
+ [ map { $_->[0] } @{$recs->{ids}} ],
+ $unapi,
);
-}
-sub id {
- my $self = shift;
- my $id = shift;
-
- $self->_create_node( '/atom:feed', 'http://www.w3.org/2005/Atom', 'atom:id', $id );
-}
-
-package OpenILS::WWW::SuperCat::Feed::atom::item;
-use base 'OpenILS::WWW::SuperCat::Feed::atom';
-
-sub new {
- my $class = shift;
- my $xml = shift;
- my $self = $class->SUPER::build($xml);
- $self->{doc}->documentElement->setNamespace('http://www.w3.org/2005/Atom', 'atom');
- $self->{type} = 'atom::item';
- return $self;
-}
-
-sub link {
- my $self = shift;
- my $type = shift;
- my $id = shift;
-
- if ($type eq 'unapi') {
- $self->_create_node(
- 'atom:entry',
- 'http://www.w3.org/2005/Atom',
- 'atom:link',
- undef,
- { rel => $type,
- type => "application/xml",
- href => $self->unapi . '?uri=' . $id,
- }
- );
- }
-}
+=head
+ my $bucket = $actor->request("open-ils.actor.container.public.flesh", 'biblio', $id)->gather(1);
+ my $bucket_tag = "tag:$host,$year:record_bucket/$id";
+ my $feed = create_record_feed(
+ $type,
+ [ map { $_->target_biblio_record_entry } @{ $bucket->items } ],
+ $unapi,
+ );
-#----------------------------------------------------------
+ $feed->title("Items in Book Bag #".$bucket->id);
+ $feed->creator($host);
+ $feed->update_ts(gmtime_ISO8601());
-package OpenILS::WWW::SuperCat::Feed::rss2;
-use base 'OpenILS::WWW::SuperCat::Feed';
+ $feed->link(atom => $id);
+ $feed->link(rss2 => $id);
+ $feed->link(html => $id);
-sub new {
- my $class = shift;
- my $self = $class->SUPER::build('');
- $self->{type} = 'rss2';
- $self->{item_xpath} = '/rss/channel';
- return $self;
-}
+=cut
-sub title {
- my $self = shift;
- my $text = shift;
- $self->_create_node('/rss/channel',undef,'title', $text);
-}
+ $feed->_create_node(
+ $feed->{item_xpath},
+ 'http://a9.com/-/spec/opensearch/1.1/',
+ 'totalResults',
+ $recs->{count},
+ );
-sub update_ts {
- my $self = shift;
- my $text = shift;
- $self->_create_node('/rss/channel',undef,'lastBuildDate', $text);
-}
+ $feed->_create_node(
+ $feed->{item_xpath},
+ 'http://a9.com/-/spec/opensearch/1.1/',
+ 'startIndex',
+ $offset + 1,
+ );
-sub creator {
- my $self = shift;
- my $text = shift;
- $self->_create_node('/rss/channel', undef,'generator', $text);
-}
+ $feed->_create_node(
+ $feed->{item_xpath},
+ 'http://a9.com/-/spec/opensearch/1.1/',
+ 'itemsPerPage',
+ $limit,
+ );
-sub link {
- my $self = shift;
- my $type = shift;
- my $id = shift;
-
- $self->_create_node(
- '/rss/channel',
- undef,
- 'link',
- $self->base . '/' . $type . '/' . $id,
- { rel => $type }
+ $feed->link(
+ next =>
+ $base . $path . "?startIndex=" . int($offset + $limit + 1) . "&count=" . $limit =>
+ 'application/opensearch+xml'
+ ) if ($offset + $limit < $recs->{count});
+
+ $feed->link(
+ prev =>
+ $base . $path . "?startIndex=" . int(($offset - $limit) + 1) . "&count=" . $limit =>
+ 'application/opensearch+xml'
+ ) if ($offset);
+
+ $feed->link(
+ self =>
+ $base . $path =>
+ 'application/opensearch+xml'
);
-}
-package OpenILS::WWW::SuperCat::Feed::rss2::item;
-use base 'OpenILS::WWW::SuperCat::Feed::rss2';
-sub new {
- my $class = shift;
- my $xml = shift;
- my $self = $class->SUPER::build($xml);
- $self->{type} = 'atom::item';
- return $self;
+ print entityize($feed->toString) . "\n";
+ return Apache2::Const::OK;
}
-sub link {
- my $self = shift;
+sub create_record_feed {
my $type = shift;
- my $id = shift;
-
- $self->_create_node( item => undef, 'link' => $self->unapi . '?uri=' . $id )
- if ($type eq 'unapi');
-}
-
+ my $records = shift;
+ my $unapi = shift;
-#----------------------------------------------------------
+ my $cgi = new CGI;
+ my $base = $cgi->url;
+ my $host = $cgi->virtual_host || $cgi->server_name;
-package OpenILS::WWW::SuperCat::Feed::mods;
-use base 'OpenILS::WWW::SuperCat::Feed';
+ my $year = (gmtime())[5];
-sub new {
- my $class = shift;
- my $self = $class->SUPER::build('');
- $self->{type} = 'mods';
- $self->{item_xpath} = '/mods:modsCollection';
- return $self;
-}
+ my $feed = new OpenILS::WWW::SuperCat::Feed ($type);
+ $feed->base($base);
+ $feed->unapi($unapi);
-package OpenILS::WWW::SuperCat::Feed::mods::item;
-use base 'OpenILS::WWW::SuperCat::Feed::mods';
+ for my $rec (@$records) {
+ my $item_tag = "tag:$host,$year:biblio-record_entry/" . $rec;
-sub new {
- my $class = shift;
- my $xml = shift;
- my $self = $class->SUPER::build($xml);
- $self->{doc}->documentElement->setNamespace('http://www.loc.gov/mods/', 'mods');
- $self->{type} = 'mods::item';
- return $self;
-}
+ my $xml = $supercat->request(
+ "open-ils.supercat.record.$type.retrieve",
+ $rec
+ )->gather(1);
-my $linkid = 1;
+ my $node = $feed->add_item($xml);
-sub link {
- my $self = shift;
- my $type = shift;
- my $id = shift;
-
- if ($type eq 'unapi') {
- $self->_create_node(
- 'mods:mods',
- 'http://www.loc.gov/mods/',
- 'mods:relatedItem',
- undef,
- { type => 'otherFormat', id => 'link-'.$linkid }
- );
- $self->_create_node(
- "mods:mods/mods:relatedItem[\@id='link-$linkid']",
- 'http://www.loc.gov/mods/',
- 'mods:recordIdentifier',
- $self->unapi .'?uri=' . $id
- );
- $linkid++;
+ $node->id($item_tag);
+ $node->link(opac => $feed->unapi . "?uri=$item_tag&format=opac");
+ $node->link(unapi => $feed->unapi . "?uri=$item_tag");
}
-}
-
-#----------------------------------------------------------
-
-package OpenILS::WWW::SuperCat::Feed::html;
-use base 'OpenILS::WWW::SuperCat::Feed';
-
-sub new {
- my $class = shift;
- my $self = $class->SUPER::build('
');
- $self->{type} = 'html';
- $self->{item_xpath} = '/html/body';
- return $self;
+ return $feed;
}
+sub entityize {
+ my $stuff = NFC(shift());
+ $stuff =~ s/([\x{0080}-\x{fffd}])/sprintf('%X;',ord($1))/sgoe;
+ return $stuff;
+}
1;
diff --git a/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat/Feed.pm b/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat/Feed.pm
new file mode 100644
index 0000000000..6edae27ba5
--- /dev/null
+++ b/Open-ILS/src/perlmods/OpenILS/WWW/SuperCat/Feed.pm
@@ -0,0 +1,328 @@
+package OpenILS::WWW::SuperCat::Feed;
+use strict; use warnings;
+use vars qw/$parser/;
+use OpenSRF::EX qw(:try);
+use XML::LibXML;
+use CGI;
+
+sub new {
+ my $class = shift;
+ my $type = shift;
+ if ($type) {
+ $class .= '::'.$type;
+ return $class->new;
+ }
+ throw OpenSRF::EX::ERROR ("I need a feed type!") ;
+}
+
+sub build {
+ my $class = shift;
+ my $xml = shift;
+
+ $parser = new XML::LibXML if (!$parser);
+
+ my $self = { doc => $parser->parse_string($xml), items => [] };
+
+ return bless $self => $class;
+}
+
+sub base {
+ my $self = shift;
+ my $base = shift;
+ $self->{base} = $base if ($base);
+ return $self->{base};
+}
+
+sub unapi {
+ my $self = shift;
+ my $unapi = shift;
+ $self->{unapi} = $unapi if ($unapi);
+ return $self->{unapi};
+}
+
+sub push_item {
+ my $self = shift;
+ push @{ $self->{items} }, @_;
+}
+
+sub items {
+ my $self = shift;
+ return @{ $self->{items} } if (wantarray);
+ return $self->{items};
+}
+
+sub _add_node {
+ my $self = shift;
+
+ my $xpath = shift;
+ my $new = shift;
+
+ for my $node ($self->{doc}->findnodes($xpath)) {
+ $node->appendChild($new);
+ last;
+ }
+}
+
+sub _create_node {
+ my $self = shift;
+
+ my $xpath = shift;
+ my $ns = shift;
+ my $name = shift;
+ my $text = shift;
+ my $attrs = shift;
+
+ for my $node ($self->{doc}->findnodes($xpath)) {
+ my $new = $self->{doc}->createElement($name) if (!$ns);
+ $new = $self->{doc}->createElementNS($ns,$name) if ($ns);
+
+ $new->appendChild( $self->{doc}->createTextNode( $text ) )
+ if (defined $text);
+
+ if (ref($attrs)) {
+ for my $key (keys %$attrs) {
+ $new->setAttribute( $key => $$attrs{$key} );
+ }
+ }
+
+ $node->appendChild( $new );
+
+ return $new;
+ }
+}
+
+sub add_item {
+ my $self = shift;
+ my $class = ref($self) || $self;
+ $class .= '::item';
+
+ my $item_xml = shift;
+ my $entry = $class->new($item_xml);
+
+ $entry->base($self->base);
+ $entry->unapi($self->unapi);
+
+ $self->push_item($entry);
+ return $entry;
+}
+
+sub toString {
+ my $self = shift;
+ for my $root ( $self->{doc}->findnodes($self->{item_xpath}) ) {
+ for my $item ( $self->items ) {
+ $root->appendChild( $item->{doc}->documentElement );
+ }
+ last;
+ }
+
+ return $self->{doc}->toString(1);
+}
+
+sub id {};
+sub link {};
+sub title {};
+sub update_ts {};
+sub creator {};
+
+#----------------------------------------------------------
+
+package OpenILS::WWW::SuperCat::Feed::atom;
+use base 'OpenILS::WWW::SuperCat::Feed';
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::build('');
+ $self->{type} = 'atom';
+ $self->{item_xpath} = '/atom:feed';
+ return $self;
+}
+
+sub title {
+ my $self = shift;
+ my $text = shift;
+ $self->_create_node('/atom:feed','http://www.w3.org/2005/Atom','atom:title', $text);
+}
+
+sub update_ts {
+ my $self = shift;
+ my $text = shift;
+ $self->_create_node('/atom:feed','http://www.w3.org/2005/Atom','atom:updated', $text);
+}
+
+sub creator {
+ my $self = shift;
+ my $text = shift;
+ $self->_create_node('/atom:feed','http://www.w3.org/2005/Atom','atom:author');
+ $self->_create_node('/atom:feed/atom:author', 'http://www.w3.org/2005/Atom','atom:name', $text);
+}
+
+sub link {
+ my $self = shift;
+ my $type = shift;
+ my $id = shift;
+ my $mime = shift || "application/$type+xml";
+
+ $type = 'self' if ($type eq 'atom');
+
+ $self->_create_node(
+ $self->{item_xpath},
+ 'http://www.w3.org/2005/Atom',
+ 'atom:link',
+ undef,
+ { rel => $type,
+ href => $id,
+ type => $mime,
+ }
+ );
+}
+
+sub id {
+ my $self = shift;
+ my $id = shift;
+
+ $self->_create_node( '/atom:feed', 'http://www.w3.org/2005/Atom', 'atom:id', $id );
+}
+
+package OpenILS::WWW::SuperCat::Feed::atom::item;
+use base 'OpenILS::WWW::SuperCat::Feed::atom';
+
+sub new {
+ my $class = shift;
+ my $xml = shift;
+ my $self = $class->SUPER::build($xml);
+ $self->{doc}->documentElement->setNamespace('http://www.w3.org/2005/Atom', 'atom');
+ $self->{item_xpath} = '/atom:entry';
+ $self->{type} = 'atom::item';
+ return $self;
+}
+
+
+#----------------------------------------------------------
+
+package OpenILS::WWW::SuperCat::Feed::rss2;
+use base 'OpenILS::WWW::SuperCat::Feed';
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::build('');
+ $self->{type} = 'rss2';
+ $self->{item_xpath} = '/rss/channel';
+ return $self;
+}
+
+sub title {
+ my $self = shift;
+ my $text = shift;
+ $self->_create_node('/rss/channel',undef,'title', $text);
+}
+
+sub update_ts {
+ my $self = shift;
+ my $text = shift;
+ $self->_create_node('/rss/channel',undef,'lastBuildDate', $text);
+}
+
+sub creator {
+ my $self = shift;
+ my $text = shift;
+ $self->_create_node('/rss/channel', undef,'generator', $text);
+}
+
+sub link {
+ my $self = shift;
+ my $type = shift;
+ my $id = shift;
+ my $mime = shift || "application/$type+xml";
+
+ $type = 'self' if ($type eq 'rss2');
+
+ $self->_create_node(
+ $self->{item_xpath},
+ undef,
+ 'link',
+ $id,
+ { rel => $type,
+ type => $mime,
+ }
+ );
+}
+
+package OpenILS::WWW::SuperCat::Feed::rss2::item;
+use base 'OpenILS::WWW::SuperCat::Feed::rss2';
+
+sub new {
+ my $class = shift;
+ my $xml = shift;
+ my $self = $class->SUPER::build($xml);
+ $self->{type} = 'atom::item';
+ $self->{item_xpath} = '/item';
+ return $self;
+}
+
+
+#----------------------------------------------------------
+
+package OpenILS::WWW::SuperCat::Feed::mods;
+use base 'OpenILS::WWW::SuperCat::Feed';
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::build('');
+ $self->{type} = 'mods';
+ $self->{item_xpath} = '/mods:modsCollection';
+ return $self;
+}
+
+package OpenILS::WWW::SuperCat::Feed::mods::item;
+use base 'OpenILS::WWW::SuperCat::Feed::mods';
+
+sub new {
+ my $class = shift;
+ my $xml = shift;
+ my $self = $class->SUPER::build($xml);
+ $self->{doc}->documentElement->setNamespace('http://www.loc.gov/mods/', 'mods');
+ $self->{type} = 'mods::item';
+ return $self;
+}
+
+my $linkid = 1;
+
+sub link {
+ my $self = shift;
+ my $type = shift;
+ my $id = shift;
+
+ if ($type eq 'unapi' || $type eq 'opac') {
+ $self->_create_node(
+ 'mods:mods',
+ 'http://www.loc.gov/mods/',
+ 'mods:relatedItem',
+ undef,
+ { type => 'otherFormat', id => 'link-'.$linkid }
+ );
+ $self->_create_node(
+ "mods:mods/mods:relatedItem[\@id='link-$linkid']",
+ 'http://www.loc.gov/mods/',
+ 'mods:recordIdentifier',
+ $id
+ );
+ $linkid++;
+ }
+}
+
+
+#----------------------------------------------------------
+
+package OpenILS::WWW::SuperCat::Feed::html;
+use base 'OpenILS::WWW::SuperCat::Feed';
+
+sub new {
+ my $class = shift;
+ my $self = $class->SUPER::build('
');
+ $self->{type} = 'html';
+ $self->{item_xpath} = '/html/body';
+ return $self;
+}
+
+
+1;
--
2.43.2