source: trunk/gsdl/perllib/docsave.pm@ 9838

Last change on this file since 9838 was 9838, checked in by davidb, 19 years ago

General improvements to saving files in DSpace format. Main additino is to
use extracted metadata values for dc.* values that are not present. For example
if there is no dc.Title then ex.Title is used instead.

  • Property svn:keywords set to Author Date Id Revision
File size: 20.1 KB
Line 
1###########################################################################
2#
3# docsave.pm
4# A component of the Greenstone digital library software
5# from the New Zealand Digital Library Project at the
6# University of Waikato, New Zealand.
7#
8# Copyright (C) 1999 New Zealand Digital Library Project
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation; either version 2 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program; if not, write to the Free Software
22# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23#
24###########################################################################
25
26# This document processor saves a document in the
27# archives directory of a collection (as xml)
28
29use strict;
30no strict 'refs';
31
32package docsave;
33
34eval {require bytes};
35
36use arcinfo;
37use expinfo;
38use docproc;
39use util;
40
41
42sub BEGIN {
43 @docsave::ISA = ('docproc');
44}
45
46sub new {
47 my ($class, $collection, $info, $verbosity,
48 $gzip, $groupsize, $outhandle, $service, $saveas) = @_;
49 my $self = new docproc ();
50
51 $groupsize=1 unless defined $groupsize;
52 $service="import" unless defined $service;
53
54 $self->{'collection'} = $collection;
55 if ($service eq "import"){
56 $self->{'archive_info'} = $info;
57 } elsif ($service eq "export"){
58 $self->{'export_info'} = $info;
59 } else {
60 return;
61 }
62
63 $self->{'verbosity'} = $verbosity;
64 $self->{'gzip'} = $gzip;
65 $self->{'keepimportstructure'} = 0;
66 $self->{'groupsize'} = $groupsize;
67 $self->{'gs_count'} = 0;
68
69 $self->{'outhandle'} = 'STDERR';
70 $self->{'outhandle'} = $outhandle if defined $outhandle;
71 $self->{'service'} = $service;
72 $self->{'saveas'} = $saveas;
73
74 # set a default for the archive directory
75 if ($service eq "import"){
76 $self->{'archive_dir'} = &util::filename_cat ($ENV{'GSDLCOLLECTDIR'}, "archives");
77 } elsif ($service eq "export") {
78 # set a default for the export directory
79 $self->{'export_dir'} = &util::filename_cat($ENV{'GSDLCOLLECTDIR'}, "export");
80 } else {
81 return;
82 }
83 $self->{'sortmeta'} = undef;
84
85 return bless $self, $class;
86}
87
88sub setarchivedir {
89 my $self = shift (@_);
90 my ($archive_dir) = @_;
91
92 &util::mk_all_dir ($archive_dir) unless -e $archive_dir;
93 $self->{'archive_dir'} = $archive_dir;
94}
95
96sub setexportdir {
97 my $self = shift (@_);
98 my ($export_dir) = @_;
99
100 &util::mk_all_dir ($export_dir) unless -e $export_dir;
101 $self->{'export_dir'} = $export_dir;
102}
103
104sub set_sortmeta {
105 my $self = shift (@_);
106 my ($sortmeta, $removeprefix, $removesuffix) = @_;
107
108 $self->{'sortmeta'} = $sortmeta;
109 if (defined ($removeprefix) && $removeprefix ) {
110 $removeprefix =~ s/^\^//; # don't need a leading ^
111 $self->{'removeprefix'} = $removeprefix;
112 }
113 if (defined ($removesuffix) && $removesuffix) {
114 $removesuffix =~ s/\$$//; # don't need a trailing $
115 $self->{'removesuffix'} = $removesuffix;
116 }
117}
118
119sub process {
120 my $self = shift (@_);
121 my ($doc_obj) = @_;
122
123 my $outhandle = $self->{'outhandle'};
124 my $service = $self->{'service'} || "import";
125
126 # Define the SaveAs Type
127 my $save_as = $self->{'saveas'} || "GA";
128 my $collection = $self->{'collection'};
129
130 if ($self->{'groupsize'} > 1) {
131 $self->group_process ($doc_obj);
132 return;
133 }
134
135 my $OID = $doc_obj->get_OID();
136 $OID = "NULL" unless defined $OID;
137
138 # get document's directory
139 my $doc_dir = $self->get_doc_dir ($OID, $doc_obj->get_source_filename());
140
141 # groupsize is 1 (i.e. one document per XML file) so sortmeta
142 # may be used
143
144 if ($service eq "import") {
145 my $archive_info = $self->{'archive_info'};
146 } elsif ($service eq "export") {
147 my $export_info = $self->{'export_info'};
148 } else {
149 return;
150 }
151
152 # copy all the associated files, add this information as metadata
153 # to the document
154 if ($service eq "export" && $save_as eq "DSpace") {
155 # create handle file based on doc_dir
156
157 my $doc_handle_file
158 = &util::filename_cat ($self->{'export_dir'},$doc_dir, "handle");
159
160 if (!open(OUTDOC_EXPORT_HANDLE,">$doc_handle_file")){
161 print $outhandle "docsave::process could not write collection handle to file $doc_handle_file\n";
162 return;
163 }
164
165 my ($handle) = ($doc_dir =~ m/^(.*)\.dir$/);
166 print OUTDOC_EXPORT_HANDLE "123456789/$handle\n";
167
168 close(OUTDOC_EXPORT_HANDLE);
169
170 # open contents file
171 my $doc_contents_file
172 = &util::filename_cat ($self->{'export_dir'},$doc_dir, "contents");
173
174 if (!open(OUTDOC_EXPORT_CONTENTS,">$doc_contents_file")){
175 print $outhandle "docsave::process could not write collection contents to file $doc_contents_file\n";
176 return;
177 }
178 $self->process_assoc_files ($doc_obj, $doc_dir, 'docsave::OUTDOC_EXPORT_CONTENTS');
179 } else {
180 $self->process_assoc_files ($doc_obj, $doc_dir, '');
181 }
182
183 my $doc_file;
184 my $doc_mets_file;
185 my $doc_txt_file;
186 my $short_doc_file;
187
188 # Save collection as either Greenstone Archive or METS format
189 if ($service eq "import") {
190 my $doc_file
191 = &util::filename_cat ($self->{'archive_dir'}, $doc_dir, "doc.xml");
192
193 # define doctxt.xml file
194 my $doc_txt_file
195 = &util::filename_cat ($self->{'archive_dir'}, $doc_dir,"doctxt.xml");
196
197 my $import_working_dir
198 =&util::filename_cat ($self->{'archive_dir'}, $doc_dir);
199
200 # define docmets.xml file
201 my $doc_mets_file
202 = &util::filename_cat ($self->{'archive_dir'},$doc_dir, "docmets.xml");
203
204 if ($save_as eq "GA") {
205 $short_doc_file = util::filename_cat ($doc_dir, "doc.xml");
206 } elsif ($save_as eq "METS") {
207 #my $short_txt_doc_file=&util::filename_cat ($doc_dir, "doctxt.xml");
208 $short_doc_file = &util::filename_cat ($doc_dir, "docmets.xml");
209 } else {
210 return;
211 }
212
213 if ($save_as eq "GA") {
214 if (!open (OUTDOC, ">$doc_file")) {
215 print $outhandle "docsave::process could not write to file $doc_file\n";
216 return;
217 }
218 # save this document
219 $self->output_xml_header('docsave::OUTDOC');
220 $doc_obj->output_section('docsave::OUTDOC',
221 $doc_obj->get_top_section());
222 $self->output_xml_footer('docsave::OUTDOC');
223
224 close OUTDOC;
225 } elsif ($save_as eq "METS") {
226 # save the document without metadata:doctxt.xml
227
228 if (!open(OUTDOC_TXT, ">$doc_txt_file")){
229 print $outhandle "docsave::process could not write to file $doc_txt_file\n";
230 return;
231 }
232
233 $self->output_txt_xml_header('docsave::OUTDOC_TXT');
234 $doc_obj->output_txt_section('docsave::OUTDOC_TXT', $doc_obj->get_top_section());
235 #$self->output_txt_xml_footer('docsave::OUTDOC_TXT');
236
237 # Convert doctxt.xml file to docmets.xml
238 if (!open(OUTDOC_METS,">$doc_mets_file")){
239 print $outhandle "docsave::process could not write to file $doc_mets_file\n";
240 return;
241 }
242
243 $self->output_mets_xml_header('docsave::OUTDOC_METS', $OID);
244 $doc_obj->output_mets_section('docsave::OUTDOC_METS',
245 $doc_obj->get_top_section());
246 $self->output_mets_xml_footer('docsave::OUTDOC_METS');
247
248 close OUTDOC_TXT;
249 close OUTDOC_METS;
250 } else { # save_as isn't GA or METS
251 print $outhandle "docsave::process unrecognised saveas type, $save_as\n";
252 return;
253 }
254 }
255
256 ## Export the collection to METs format or DSpace Archive Format into the export directory
257 if ($service eq "export") {
258 my $doc_dc_file;
259 my $doc_contents_file;
260
261 my $export_working_dir
262 =&util::filename_cat ($self->{'export_dir'}, $doc_dir);
263
264 if ($save_as eq "METS") {
265 $doc_mets_file
266 = &util::filename_cat ($self->{'export_dir'},$doc_dir, "docmets.xml");
267
268 $doc_txt_file
269 = &util::filename_cat ($self->{'export_dir'},$doc_dir, "doctxt.xml");
270
271 if (!open(OUTDOC_EXPORT_TXT, ">$doc_txt_file")){
272 print $outhandle "docsave::process could not write TXT to file $doc_txt_file\n";
273 return;
274 }
275
276 $self->output_txt_xml_header('docsave::OUTDOC_EXPORT_TXT');
277 $doc_obj->output_txt_section('docsave::OUTDOC_EXPORT_TXT', $doc_obj->get_top_section());
278
279 if (!open(OUTDOC_EXPORT_METS,">$doc_mets_file")){
280 print $outhandle "docsave::process could not write METS format to file $doc_mets_file\n";
281 return;
282 }
283 $self->output_mets_xml_header('docsave::OUTDOC_EXPORT_METS', $OID);
284 $doc_obj->output_mets_section('docsave::OUTDOC_EXPORT_METS',$doc_obj->get_top_section(), $export_working_dir);
285 $self->output_mets_xml_footer('docsave::OUTDOC_EXPORT_METS');
286
287 close OUTDOC_EXPORT_TXT;
288 close OUTDOC_EXPORT_METS;
289 } elsif ($save_as eq "DSpace") {
290
291 # Generate dublin_core.xml file
292 $doc_dc_file
293 = &util::filename_cat ($self->{'export_dir'},$doc_dir, "dublin_core.xml");
294
295 if (!open(OUTDOC_EXPORT_DC,">$doc_dc_file")){
296 print $outhandle "docsave::process could not write dublin core to file $doc_dc_file\n";
297 return;
298 }
299
300 $self->output_dc_xml_header('docsave::OUTDOC_EXPORT_DC', $OID);
301 $doc_obj->output_dc_section('docsave::OUTDOC_EXPORT_DC',$doc_obj->get_top_section(), $export_working_dir);
302 $self->output_dc_xml_footer('docsave::OUTDOC_EXPORT_DC');
303
304 close OUTDOC_EXPORT_DC;
305 close OUTDOC_EXPORT_CONTENTS;
306 } else { # save_as isn't METS or DSpace
307 print $outhandle "docsave::process unrecognised saveas type, $save_as\n";
308 return;
309 }
310
311 if ($save_as eq "METS") {
312 $short_doc_file = util::filename_cat ($doc_dir, "docmets.xml");
313 } elsif ($save_as eq "DSpace") {
314 #my $short_txt_doc_file=&util::filename_cat ($doc_dir, "doctxt.xml");
315 $short_doc_file=&util::filename_cat ($doc_dir, "dublin_core.xml");
316 } else {
317 return;
318 }
319
320 }
321 #save for later (for close_file_output())
322 $self->{'short_doc_file'} = $short_doc_file;
323
324 if ($self->{'gzip'}) {
325 my $doc_file = $self->{'gs_filename'};
326 `gzip $doc_file`;
327 $doc_file .= ".gz";
328 $short_doc_file .= ".gz";
329 if (!-e $doc_file) {
330 print $outhandle "error while gzipping: $doc_file doesn't exist\n";
331 return 0;
332 }
333 }
334
335 # do the sortmeta thing
336 my ($metadata);
337 if (defined ($self->{'sortmeta'})) {
338 $metadata = $doc_obj->get_metadata_element($doc_obj->get_top_section(),
339 $self->{'sortmeta'});
340 }
341 if (defined ($metadata) && $metadata) {
342 # do remove prefix/suffix
343 if (defined($self->{'removeprefix'})) {
344 $metadata =~ s/^$self->{'removeprefix'}//;
345 }
346 if (defined($self->{'removesuffix'})) {
347 $metadata =~ s/$self->{'removesuffix'}$//;
348 }
349 $metadata = &sorttools::format_metadata_for_sorting($self->{'sortmeta'}, $metadata, $doc_obj);
350 }
351 # store reference in the archive_info and export_info
352 if ($service eq "export") {
353 $self->{'export_info'}->add_info($OID, $short_doc_file, $metadata);
354 } elsif ($service eq "import") {
355 $self->{'archive_info'}->add_info($OID, $short_doc_file, $metadata);
356 }
357}
358
359
360sub group_process {
361 my $self = shift (@_);
362 my ($doc_obj) = @_;
363
364 my $outhandle = $self->{'outhandle'};
365
366 my $OID = $doc_obj->get_OID();
367 $OID = "NULL" unless defined $OID;
368
369 my $groupsize = $self->{'groupsize'};
370 my $gs_count = $self->{'gs_count'};
371 my $open_new_file = (($gs_count % $groupsize)==0);
372
373 # opening a new file, or document has assoicated files => directory needed
374 if (($open_new_file) || (scalar(@{$doc_obj->get_assoc_files()})>0)) {
375
376 # get document's directory
377 my $doc_dir = $self->get_doc_dir ($OID, $doc_obj->get_source_filename());
378
379 # copy all the associated files, add this information as metadata
380 # to the document
381 $self->process_assoc_files ($doc_obj, $doc_dir);
382
383
384 if ($open_new_file) {
385 # only if opening new file
386 my $doc_file
387 = &util::filename_cat ($self->{'archive_dir'}, $doc_dir, "doc.xml");
388 my $short_doc_file = &util::filename_cat ($doc_dir, "doc.xml");
389
390 if ($gs_count>0)
391 {
392 return if (!$self->close_file_output());
393 }
394
395 if (!open (OUTDOC, ">$doc_file")) {
396 print $outhandle "docsave::group_process could not write to file $doc_file\n";
397 return;
398 }
399 $self->{'gs_filename'} = $doc_file;
400 $self->{'gs_short_filename'} = $short_doc_file;
401 $self->{'gs_OID'} = $OID;
402
403 $self->output_xml_header('docsave::OUTDOC');
404 }
405 }
406
407 # save this document
408 $doc_obj->output_section('docsave::OUTDOC', $doc_obj->get_top_section());
409
410 $self->{'gs_count'}++;
411}
412
413sub get_doc_dir {
414 my $self = shift (@_);
415 my ($OID, $source_filename) = @_;
416 my $doc_info;
417 my $doc_dir = '';
418 my $service = $self-> {'service'};
419 my $working_dir;
420 my $working_info;
421
422 if ($service eq "import") {
423 $doc_info = $self->{'archive_info'}->get_info($OID);
424 $working_dir = $self->{'archive_dir'};
425 $working_info = $self->{'archive_info'};
426 } elsif ($service eq "export") {
427 $doc_info =$self->{'export_info'}->get_info($OID);
428 $working_dir = $self->{'export_dir'};
429 $working_info = $self->{'export_info'};
430 } else {
431 return;
432 }
433 if (defined $doc_info && scalar(@$doc_info) >= 1) {
434 # this OID already has an assigned directory, use the
435 # same one.
436 $doc_dir = $doc_info->[0];
437 $doc_dir =~ s/\/?((doc(mets)?)|(dublin_core))\.xml(\.gz)?$//;
438 } elsif ($self->{'keepimportstructure'}) {
439 $source_filename = &File::Basename::dirname($source_filename);
440 $source_filename =~ s/[\\\/]+/\//g;
441 $source_filename =~ s/\/$//;
442
443
444 #print STDERR "Source filename: $source_filename; \nImport dir:",$ENV{'GSDLIMPORTDIR'}, "\n";
445 $doc_dir = substr($source_filename, length($ENV{'GSDLIMPORTDIR'}) + 1);
446
447 }
448 if ($doc_dir eq "") {
449 # have to get a new document directory
450
451 if ($service eq "import") {
452 my $doc_dir_rest = $OID;
453 my $doc_dir_num = 0;
454
455 do {
456 $doc_dir .= "/" if $doc_dir_num > 0;
457 if ($doc_dir_rest =~ s/^(.{1,8})//) {
458 $doc_dir .= $1;
459 $doc_dir_num++;
460 }
461 } while ($doc_dir_rest ne "" &&
462 ((-d &util::filename_cat ($working_dir, "$doc_dir.dir")) ||
463 ($working_info->size() >= 1024 && $doc_dir_num < 2)));
464 }
465 else {
466 # Export formats such as DSpace need the directory structure to
467 # be flat. This is simple to arrange (set 'doc_dir' to bit the
468 # documents OID) but breaks Windows 3.1 file system compliance.
469 # Such a loss is not a bit thing in this situation as such
470 # systems don't run on Windows 3.1 anyway.
471
472 $doc_dir = $OID;
473 }
474
475
476 $doc_dir .= ".dir";
477 &util::mk_all_dir (&util::filename_cat ($working_dir, $doc_dir));
478 }
479 return $doc_dir;
480}
481
482sub process_assoc_files {
483 my $self = shift (@_);
484 my ($doc_obj, $doc_dir, $handle) = @_;
485
486 my $outhandle = $self->{'outhandle'};
487
488 my @assoc_files = ();
489 my $filename;;
490 my $working_dir;
491 my $service = $self->{'service'};
492 my $save_as = $self->{'saveas'};
493
494 if ($service eq "import") {
495 $working_dir = $self->{'archive_dir'};
496 } elsif ($service eq "export"){
497 $working_dir = $self->{'export_dir'};
498 } else {
499 return;
500 }
501
502 my $source_filename = $doc_obj->get_source_filename();
503
504 my $collect_dir = $ENV{'GSDLCOLLECTDIR'};
505
506 if (defined $collect_dir) {
507 my $dirsep = &util::get_dirsep();
508
509 if ($collect_dir !~ m/$dirsep$/) {
510 $collect_dir .= $dirsep; # ensure there is a slash at the end
511 }
512
513 if ($source_filename !~ /^$dirsep/) {
514 $source_filename
515 = &util::filename_cat($collect_dir,$source_filename);
516 }
517 }
518
519
520 if ($save_as eq "DSpace") {
521 my ($tail_filename) = ($source_filename =~ m/\/([^\/\\]*)$/);
522
523 print $handle "$tail_filename\n";
524
525 $filename = &util::filename_cat($working_dir, $doc_dir, $tail_filename);
526 &util::hard_link ($source_filename, $filename);
527 }
528
529 foreach my $assoc_file_rec (@{$doc_obj->get_assoc_files()}) {
530 my ($dir, $afile) = $assoc_file_rec->[1] =~ /^(.*?)([^\/\\]+)$/;
531 $dir = "" unless defined $dir;
532
533
534 my $real_filename = $assoc_file_rec->[0];
535 if (-e $real_filename) {
536
537
538 if ($save_as eq "DSpace") {
539 if ($real_filename =~ m/$source_filename$/) {
540 next;
541 }
542 else {
543 my $bundle = "bundle:ORIGINAL";
544
545 if ($afile =~ m/^thumbnail\./) {
546 $bundle = "bundle:THUMBNAIL";
547 }
548
549 # Store the associated file to the "contents" file
550 print $handle "$assoc_file_rec->[1]\t$bundle\n";
551 }
552 }
553
554 $filename = &util::filename_cat($working_dir, $doc_dir, $afile);
555
556
557 &util::hard_link ($real_filename, $filename);
558
559 $doc_obj->add_utf8_metadata ($doc_obj->get_top_section(),
560 "gsdlassocfile",
561 "$afile:$assoc_file_rec->[2]:$dir");
562 $doc_obj->set_utf8_metadata_element ($doc_obj->get_top_section(),
563 "assocfilepath",
564 "$doc_dir");
565 } elsif ($self->{'verbosity'} > 2) {
566 print $outhandle "docsave::process couldn't copy the associated file " .
567 "$real_filename to $afile\n";
568 }
569 }
570}
571
572
573sub close_file_output
574{
575 my ($self) = @_;
576 my $service =$self->{'service'};
577
578 # make sure that the handle has been opened - it won't be if we failed
579 # to import any documents...
580 if (defined(fileno(docsave::OUTDOC))) {
581 $self->output_xml_footer('docsave::OUTDOC');
582 close OUTDOC;
583 }
584
585 my $OID = $self->{'gs_OID'};
586 my $short_doc_file;
587 # can we use 'short_doc_file' for GA too?
588 if (exists($self->{'saveas'}) && $self->{'saveas'} eq "METS") {
589 $short_doc_file=$self->{'short_doc_file'};
590 } elsif ($self->{'saveas'} eq "GA") { # "GA"
591 $short_doc_file=$self->{'gs_short_filename'};
592 } else { # "DSpace"
593 }
594
595 if ($self->{'gzip'}) {
596 my $doc_file = $self->{'gs_filename'};
597 `gzip $doc_file`;
598 $doc_file .= ".gz";
599 $short_doc_file .= ".gz";
600 if (!-e $doc_file) {
601 my $outhandle = $self->{'outhandle'};
602 print $outhandle "error while gzipping: $doc_file doesn't exist\n";
603 return 0;
604 }
605 }
606
607 # store reference in the archive_info and export_infor
608 if ($service eq "import") {
609 $self->{'archive_info'}->add_info($OID, $short_doc_file);
610 } elsif ($service eq "export") {
611 $self->{'export_info'}->add_info($OID, $short_doc_file);
612 } else {
613 return;
614 }
615 return 1;
616}
617
618sub output_xml_header {
619 my $self = shift (@_);
620 my ($handle) = @_;
621
622 print $handle '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . "\n";
623
624 print $handle '<!DOCTYPE Archive SYSTEM "http://greenstone.org/dtd/Archive/1.0/Archive.dtd">' . "\n";
625 print $handle "<Archive>\n";
626}
627
628sub output_xml_footer {
629 my $self = shift (@_);
630 my ($handle) = @_;
631
632 print $handle "</Archive>\n";
633}
634
635sub output_txt_xml_header{
636 my $self = shift (@_);
637 my ($handle) = @_;
638 print $handle '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . "\n";
639 print $handle '<!DOCTYPE Archive SYSTEM "http://greenstone.org/dtd/Archive/1.0/Archive.dtd">' . "\n";
640}
641
642sub output_txt_xml_footer{
643 my $self = shift(@_);
644 my ($handle) = @_;
645 print $handle "<the end of the file>\n";
646}
647
648sub output_mets_xml_header(){
649 my $self = shift(@_);
650 my ($handle, $OID) = @_;
651
652 print $handle '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . "\n";
653 print $handle '<mets:mets xmlns:mets="http://www.loc.gov/METS/"' . "\n";
654 print $handle ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"' . "\n";
655 print $handle ' xmlns:gsdl3="http://www.greenstone.org/namespace/gsdlmetadata/1.0/"' . "\n";
656 print $handle ' xmlns:xlink="http://www.w3.org/TR/xlink"' ."\n";
657 print $handle ' xsi:schemaLocation="http://www.loc.gov/METS/' . "\n";
658 print $handle ' http://www.loc.gov/standards/mets/mets.xsd' . "\n";
659 print $handle ' http://www.greenstone.org/namespace/gsdlmetadata/1.0/' . "\n";
660 print $handle ' http://www.greenstone.org/namespace/gsdlmetadata/1.0/gsdl_metadata.xsd"' . "\n";
661 print $handle ' OBJID="'. $OID. ':2">' . "\n";
662}
663
664sub output_mets_xml_footer() {
665 my $self = shift(@_);
666 my ($handle) = @_;
667 print $handle '</mets:mets>' . "\n";
668}
669
670sub output_dc_xml_header(){
671 my $self = shift(@_);
672 my ($handle, $OID) = @_;
673
674 print $handle '<?xml version="1.0" encoding="UTF-8" standalone="no"?>' . "\n";
675# print $handle '<!DOCTYPE Archive SYSTEM "http://greenstone.org/dtd/Archive/1.0/Archive.dtd">'."\n";
676 print $handle '<dublin_core>' . "\n";
677}
678
679sub output_dc_xml_footer() {
680 my $self = shift(@_);
681 my ($handle) = @_;
682 print $handle '</dublin_core>' . "\n";
683}
6841;
Note: See TracBrowser for help on using the repository browser.