3 # Copyright (C) 2015 Equinox Software, Inc.
5 # Initial author: Galen Charlton <gmc@esilibrary.com>
7 # This program is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU General Public License
9 # as published by the Free Software Foundation; either version 2
10 # of the License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
18 # Utility to convert a MARC tooltips XML file to an SQL script
19 # containing inserts into config.marc_field, config.marc_subfield,
20 # and, for indicator value lists, config.record_attr_definition
21 # and config.coded_value_map.
30 my ($infile, $outfile);
31 my $marctype = 'biblio';
34 'input:s' => \$infile,
35 'output:s' => \$outfile,
36 'type:s' => \$marctype,
39 unless(defined($infile) && defined($outfile)) {
40 print "Must specify an input file and an output file.\n\n";
45 unless($marctype eq 'biblio' or $marctype eq 'authority' or $marctype eq 'serial') {
46 print "Must specify a MARC type of 'biblio', 'authority', or 'serial'.\n\n";
51 open my $OUT, '>', $outfile or die "Cannot open output file $outfile: $!\n";
52 binmode $OUT, ':utf8';
54 open my $IN, '<', $infile or die "Cannot open input file $infile: $!\n";
55 binmode $IN; # per XML::LibXML doc, drop all PerlIO layers
58 $xml = XML::LibXML->load_xml(IO => $IN);
62 print "Failed to parse MARC tooltips file $infile: $e\n";
66 emit_sql($xml, $OUT, $marctype);
75 --input /path/to/marcedit-tooltips.xml \\
76 --outfile output.sql \\
77 [--type {biblio,authority,serial}]
82 my ($xml, $OUT, $marctype) = @_;
85 my @fields = $xml->findnodes('//field');
86 foreach my $field (@fields) {
87 emit_field_sql($field, $OUT, $marctype, $seen);
93 my ($field, $OUT, $marctype, $seen) = @_;
95 my $name = $field->find('name/text()');
96 my $description = $field->find('description/text()');
97 my $tag = $field->getAttribute('tag');
98 if ($tag !~ /^\d\d\d$/) {
99 print STDERR "Warning: tag $tag is not as expected; skipping.\n";
102 my $ff = $tag lt '010' ? 'TRUE' : 'FALSE';
103 my $repeatable = uc($field->getAttribute('repeatable'));
104 print $OUT <<_FIELD_;
105 INSERT INTO config.marc_field(marc_format, marc_record_type, tag, name, description,
106 fixed_field, repeatable, mandatory, hidden)
107 VALUES (1, '$marctype', '$tag', \$\$$name\$\$, \$\$$description\$\$,
108 $ff, $repeatable, FALSE, FALSE);
111 if (exists $seen->{$tag}) {
112 print STDERR "Warning: we've already seen $tag; skipping.\n";
117 if ($ff eq 'FALSE') {
118 emit_indicator_sql($tag, $field, $OUT, $marctype, $seen);
119 emit_subfield_sql($tag, $field, $OUT, $marctype, $seen);
123 sub emit_indicator_sql {
124 my ($tag, $field, $OUT, $marctype, $seen) = @_;
127 my @inds = $field->findnodes('indicator');
128 foreach my $ind (@inds) {
129 my $position = $ind->getAttribute('position');
130 my $value = $ind->getAttribute('value');
131 my $description = $ind->find('description/text()');
132 if ($position ne '1' and $position ne '2') {
133 print STDERR "Warning: indicator position $position for tag $tag is not expected. Skipping.\n";
136 if (length($value) != 1) {
137 print STDERR "Warning: value $value for indicator $tag.$position is not expected. Skipping.\n";
140 $indvalues{$position}->{$value} = $description;
143 foreach my $pos (sort keys %indvalues) {
144 my $ctype = "marc21_${marctype}_${tag}_ind_${pos}";
146 INSERT INTO config.record_attr_definition(name, label)
147 VALUES ('$ctype', 'MARC 21 $marctype field $tag indicator position $pos');
149 foreach my $code (sort keys %{ $indvalues{$pos} }) {
150 my $value = $indvalues{$pos}->{$code};
152 INSERT INTO config.coded_value_map(ctype, code, value, opac_visible, is_simple)
153 VALUES ('$ctype', '$code', \$\$$value\$\$, FALSE, TRUE);
159 sub emit_subfield_sql {
160 my ($tag, $field, $OUT, $marctype, $seen) = @_;
162 my @subfields = $field->findnodes('subfield');
163 foreach my $subfield (@subfields) {
164 my $code = $subfield->getAttribute('code');
165 if (exists $seen->{"$tag-$code"}) {
166 print STDERR "Warning: we've already seen $tag\$$code; skipping.\n";
169 $seen->{"$tag-$code"}++;
171 my $description = $subfield->find('description/text()');
172 my $repeatable = uc($subfield->getAttribute('repeatable'));
173 print $OUT <<_SUBFIELD_;
174 INSERT INTO config.marc_subfield(marc_format, marc_record_type, tag, code, description,
175 repeatable, mandatory, hidden)
176 VALUES (1, '$marctype', '$tag', '$code', \$\$$description\$\$,
177 $repeatable, FALSE, FALSE);