1 package WebPAC::Input::Gutenberg;
7 use base qw/WebPAC::Common/;
9 use Data::Dump qw/dump/;
10 use Encode qw/encode_utf8/;
14 WebPAC::Input::Gutenberg - support for RDF catalog data from Project Gutenberg
22 our $VERSION = '0.01';
27 Read catalog data from Project Gutemberg (uncompressed!) and create
28 pseudo-MARC records from them.
30 my $ll_db = new WebPAC::Input::Gutenberg(
31 path => '/path/to/catalog.rdf',
38 Returns new low-level input API object
40 my $ll_db = new WebPAC::Input::Gutenberg(
41 path => '/path/to/catalog.rdf'
43 my ($l,$field_nr) = @_;
44 # do something with $l which is line of input file
55 path to Project Gutenberg RDF catalog file
68 my $log = $self->_get_logger();
70 $log->info("opening Project Gutenberg RDF catalog '$arg->{path}'");
72 my $parser = XML::LibXML->new ();
73 $parser->keep_blanks (0);
74 my $doc = $parser->parse_file( $arg->{path} );
76 $log->info("parsing over, finding book nodes");
77 my $booknodes = $doc->findnodes ('/rdf:RDF/pgterms:etext');
79 $log->logdie("can't find any book nodes in RDF '$arg->{path}'") unless ($booknodes->size > 0);
82 [ 'dc:title//text()', '200', 'a' ],
83 [ 'dc:creator//text()', '700', 'a' ],
84 [ 'dc:alternative//text()', '740', 'a' ],
85 [ 'dc:subject//text()', '650', 'a' ],
86 [ 'dc:contributor//text()', '700', 'a' ],
87 [ 'dc:created//text()', '533', 'd' ],
88 [ 'dc:description//text()', '500', 'a' ],
89 [ 'dc:language//text()', '041', 'a' ],
92 $log->info("found ", $booknodes->size, " book nodes, processing");
96 foreach my $booknode (@$booknodes) {
98 # this is a book description node
99 my $etext_no = $booknode->getAttribute ('ID');
100 $etext_no =~ s/^etext//;
103 '001' => [ $etext_no ],
106 foreach my $m ( @$mapping ) {
107 my ($xpath,$f,$sf) = @$m;
109 foreach my $v ($booknode->findnodes($xpath)) {
110 push @{ $row->{$f} }, '^' . $sf . encode_utf8( $v->textContent );
113 $log->debug("using $xpath to fill $f^$sf ==> ", dump( $row->{$f} )) if (defined( $row->{$f} ));
116 $self->{_rows}->{ $mfn } = $row;
117 $log->debug("created row $mfn ", dump( $row ));
121 $booknodes = undef; # release some memory
123 $self->{size} = $mfn - 1;
125 $log->info("created ", $self->{size}, " records for ", $arg->{path});
127 $self ? return $self : return undef;
132 Return record with ID C<$mfn> from database
134 my $rec = $ll_db->fetch_rec( $mfn, $filter_coderef );
141 my ($mfn, $filter_coderef) = @_;
143 my $rec = $self->_to_hash(
145 row => $self->{_rows}->{$mfn},
146 hash_filter => $filter_coderef,
149 my $log = $self->_get_logger();
150 $log->debug("fetch_rec($mfn) = ", dump($rec));
157 Return number of records in database
159 my $size = $ll_db->size;
165 return $self->{size};
170 Return hash from row. Taken from L<Biblio::Isis>
172 my $rec = $ll_db->_to_hash(
184 my $log = $self->_get_logger();
186 my $hash_filter = $arg->{hash_filter};
187 my $mfn = $arg->{mfn} || $log->logconfess("need mfn in arguments");
188 my $row = $arg->{row} || $log->logconfess("need row in arguments");
190 # init record to include MFN as field 000
191 my $rec = { '000' => [ $mfn ] };
193 foreach my $f_nr (keys %{$row}) {
194 foreach my $l (@{$row->{$f_nr}}) {
197 $l = $hash_filter->($l, $f_nr) if ($hash_filter);
198 next unless defined($l);
201 my $r_sf; # repeatable subfields in this record
205 foreach my $t (split(/\^/,$l)) {
207 my ($sf,$v) = (substr($t,0,1), substr($t,1));
208 next unless (defined($v) && $v ne '');
210 if (ref( $val->{$sf} ) eq 'ARRAY') {
212 push @{ $val->{$sf} }, $v;
214 # record repeatable subfield it it's offset
215 push @{ $val->{subfields} }, ( $sf, $#{ $val->{$sf} } );
218 } elsif (defined( $val->{$sf} )) {
220 # convert scalar field to array
221 $val->{$sf} = [ $val->{$sf}, $v ];
223 push @{ $val->{subfields} }, ( $sf, 1 );
228 push @{ $val->{subfields} }, ( $sf, 0 );
235 push @{$rec->{$f_nr}}, $val;
244 Dobrica Pavlinusic, C<< <dpavlin@rot13.org> >>
246 =head1 COPYRIGHT & LICENSE
248 Copyright 2006 Dobrica Pavlinusic, All Rights Reserved.
250 This program is free software; you can redistribute it and/or modify it
251 under the same terms as Perl itself.
255 1; # End of WebPAC::Input::Gutenberg