2 |
# |
# |
3 |
# This script will try (hard) to convert database from |
# This script will try (hard) to convert database from |
4 |
# PhpMyLibrary (http://phpmylibrary.sourceforge.net/) back |
# PhpMyLibrary (http://phpmylibrary.sourceforge.net/) back |
5 |
# to MARC format |
# to MARC format (ISO 2709) |
6 |
# |
# |
7 |
# 2003-01-31 Dobrica Pavlinusic <dpavlin@rot13.org> |
# 2003-01-31 Dobrica Pavlinusic <dpavlin@rot13.org> |
8 |
# |
# |
24 |
my $passwd = ""; |
my $passwd = ""; |
25 |
|
|
26 |
my $usage = 0; |
my $usage = 0; |
27 |
|
my $debug = 0; |
28 |
|
my $quiet = 0; |
29 |
|
|
30 |
my $result = GetOptions( |
my $result = GetOptions( |
31 |
"database=s" => \$database, |
"database=s" => \$database, |
32 |
"host=s" => \$host, |
"host=s" => \$host, |
33 |
"user=s" => \$user, |
"user=s" => \$user, |
34 |
"password=s" => \$passwd, |
"password=s" => \$passwd, |
35 |
|
"debug!" => \$debug, |
36 |
|
"verbose!" => \$debug, |
37 |
|
"quiet!" => \$quiet, |
38 |
"help!" => \$usage, |
"help!" => \$usage, |
39 |
); |
); |
40 |
|
|
48 |
my $dbh = DBI->connect($dsn, $user, $passwd, {'RaiseError' => 1}); |
my $dbh = DBI->connect($dsn, $user, $passwd, {'RaiseError' => 1}); |
49 |
|
|
50 |
# UNIMARC leader format |
# UNIMARC leader format |
51 |
my $leader_fmt = qq{%05diam0 22%05d 45 }; |
#my $leader_fmt = qq{%05diam0 22%05d 45 }; |
52 |
|
# MARC leader format |
53 |
|
my $leader_fmt = qq{%05dcas 22%05d a 4500}; |
54 |
|
|
55 |
|
|
56 |
my $sth = $dbh->prepare("SELECT marc FROM tblbib"); |
my $sth = $dbh->prepare("SELECT marc FROM tblbib"); |
57 |
$sth->execute(); |
$sth->execute(); |
58 |
|
|
59 |
|
my $count = 0; |
60 |
|
my $rec_nr = 0; |
61 |
|
|
62 |
while (my $row = $sth->fetchrow_hashref()) { |
while (my $row = $sth->fetchrow_hashref()) { |
63 |
my $marc = $row->{'marc'}; |
my $marc = $row->{'marc'}; |
64 |
|
$rec_nr++; |
65 |
|
|
66 |
my $real_len = length($marc); |
my $real_len = length($marc); |
67 |
|
|
68 |
|
my $skip = 0; # skip this record? |
69 |
|
|
70 |
# fix PhpMyLibrary MARC (why do I have to do this? It's MARC, |
# fix PhpMyLibrary MARC (why do I have to do this? It's MARC, |
71 |
# for gaddem sake!!! |
# for gaddem sake!!! |
72 |
|
|
97 |
# (xxxxx)nam 22(.....) 450 <--- |
# (xxxxx)nam 22(.....) 450 <--- |
98 |
$marc =~ m/^(.....)......(.....)polerioj/ || die "record: '$marc' unparsable!"; |
$marc =~ m/^(.....)......(.....)polerioj/ || die "record: '$marc' unparsable!"; |
99 |
my ($reclen,$base_addr) = ($1,$2); |
my ($reclen,$base_addr) = ($1,$2); |
|
my $leader = sprintf($leader_fmt,length($marc)+1,$base_addr); |
|
100 |
|
|
101 |
print $leader . substr($marc,24).chr(29); |
my $directory = substr($marc,24,$base_addr-24); |
102 |
|
my $fields = substr($marc,$base_addr-1); |
103 |
|
|
104 |
|
print STDERR "# $rec_nr fields: '$fields'\n" if ($debug); |
105 |
|
print STDERR "# $rec_nr directory: [",length($directory),"]\n" if ($debug); |
106 |
|
|
107 |
|
# PhpMyLibrary MARC records don't have indicators, so we'll add them |
108 |
|
|
109 |
|
my $o = 0; # offset |
110 |
|
my $new_dictionary; |
111 |
|
my $new_fields; |
112 |
|
|
113 |
|
while (!$skip && $directory =~ s/(\d{3})(\d{4})(\d{5})//) { |
114 |
|
my ($tag,$len,$addr) = ($1,$2,$3); |
115 |
|
|
116 |
|
sub check_field($) { |
117 |
|
my $f = shift; |
118 |
|
my $del = substr($f,0,1); |
119 |
|
|
120 |
|
die "expected 0x1e, got '$del' (".ord($del)."): '$f'" if (ord($del) != 30); |
121 |
|
} |
122 |
|
|
123 |
|
if (($addr+$len) > length($fields)) { |
124 |
|
print STDERR "WARNING: error in dictionary on record $rec_nr skipping...\n" if (! $quiet); |
125 |
|
$skip = 1; |
126 |
|
next; |
127 |
|
} |
128 |
|
|
129 |
|
# take field |
130 |
|
my $f = substr($fields,$addr,$len); |
131 |
|
print STDERR "tag/len/addr $tag [$len] $addr: '$f'\n" if ($debug); |
132 |
|
|
133 |
|
my $del = substr($fields,$addr+$len,1); |
134 |
|
|
135 |
|
# check field delimiters... |
136 |
|
if ($del ne chr(30)) { |
137 |
|
print STDERR "WARNING: skipping record $rec_nr, can't find delimiters got: '$del'\n" if (! $quiet); |
138 |
|
$skip = 1; |
139 |
|
next; |
140 |
|
} |
141 |
|
|
142 |
|
check_field($f); |
143 |
|
|
144 |
|
if (length($f) < 2) { |
145 |
|
print STDERR "WARNING: skipping field $tag from record $rec_nr because it's too short!\n" if (! $quiet); |
146 |
|
next; |
147 |
|
} |
148 |
|
|
149 |
|
|
150 |
|
if ($tag =~ m/^00/) { |
151 |
|
# fields 001-008 doesn't have indicators |
152 |
|
$new_dictionary .= sprintf("%03d%04d%05d",$tag,$len,length($new_fields || '')); |
153 |
|
$new_fields.=$f; |
154 |
|
} else { |
155 |
|
$new_dictionary .= sprintf("%03d%04d%05d",$tag,($len+2),length($new_fields || '')); |
156 |
|
$new_fields.=chr(30)." ".substr($f,1); |
157 |
|
$o += 2; |
158 |
|
} |
159 |
|
} |
160 |
|
|
161 |
|
if (! $skip) { |
162 |
|
my $new_leader = sprintf($leader_fmt,24+length($new_dictionary.$new_fields)+2,length($new_dictionary)+25); |
163 |
|
my $new_marc = $new_leader . $new_dictionary . $new_fields . chr(30); |
164 |
|
$new_marc .= chr(29); # end of record |
165 |
|
|
166 |
|
print STDERR "original and new marc: [$rec_nr/$count]\n$marc\n$new_marc\n\n" if ($debug); |
167 |
|
print "$new_marc"; |
168 |
|
$count++; |
169 |
|
} |
170 |
|
|
171 |
|
# last if ($count > 100); |
172 |
|
|
173 |
} |
} |
174 |
$sth->finish(); |
$sth->finish(); |
175 |
$dbh->disconnect(); |
$dbh->disconnect(); |
176 |
|
|
177 |
|
print STDERR "$count records from database $database converted...\n"; |