BEGIN; INSERT INTO config.upgrade_log (version) VALUES ('0316'); -- Function that takes, and returns, marcxml and compiles an embedded ruleset for you, and they applys it CREATE OR REPLACE FUNCTION vandelay.merge_record_xml ( target_marc TEXT, template_marc TEXT ) RETURNS TEXT AS $$ DECLARE dyn_profile vandelay.compile_profile%ROWTYPE; replace_rule TEXT; tmp_marc TEXT; trgt_marc TEXT; tmpl_marc TEXT; match_count INT; BEGIN IF target_marc IS NULL OR template_marc IS NULL THEN -- RAISE NOTICE 'no marc for target or template record'; RETURN NULL; END IF; dyn_profile := vandelay.compile_profile( template_marc ); IF dyn_profile.replace_rule <> '' AND dyn_profile.preserve_rule <> '' THEN -- RAISE NOTICE 'both replace [%] and preserve [%] specified', dyn_profile.replace_rule, dyn_profile.preserve_rule; RETURN NULL; END IF; IF dyn_profile.replace_rule <> '' THEN trgt_marc = target_marc; tmpl_marc = template_marc; replace_rule = dyn_profile.replace_rule; ELSE tmp_marc = target_marc; trgt_marc = template_marc; tmpl_marc = tmp_marc; replace_rule = dyn_profile.preserve_rule; END IF; RETURN vandelay.merge_record_xml( trgt_marc, tmpl_marc, dyn_profile.add_rule, replace_rule, dyn_profile.strip_rule ); END; $$ LANGUAGE PLPGSQL; -- Fix a bug in this, for subfield-specific additions CREATE OR REPLACE FUNCTION vandelay.add_field ( target_xml TEXT, source_xml TEXT, field TEXT ) RETURNS TEXT AS $_$ use MARC::Record; use MARC::File::XML; my $target_xml = shift; my $source_xml = shift; my $field_spec = shift; my $target_r = MARC::Record->new_from_xml( $target_xml ); my $source_r = MARC::Record->new_from_xml( $source_xml ); return $target_xml unless ($target_r && $source_r); my @field_list = split(',', $field_spec); my %fields; for my $f (@field_list) { $f =~ s/^\s*//; $f =~ s/\s*$//; if ($f =~ /^(.{3})(\w*)(?:\[([^]]*)\])?$/) { my $field = $1; $field =~ s/\s+//; my $sf = $2; $sf =~ s/\s+//; my $match = $3; $match =~ s/^\s*//; $match =~ s/\s*$//; $fields{$field} = { sf => [ split('', $sf) ] }; if ($match) { my ($msf,$mre) = split('~', $match); if (length($msf) > 0 and length($mre) > 0) { $msf =~ s/^\s*//; $msf =~ s/\s*$//; $mre =~ s/^\s*//; $mre =~ s/\s*$//; $fields{$field}{match} = { sf => $msf, re => qr/$mre/ }; } } } } for my $f ( keys %fields) { if ( @{$fields{$f}{sf}} ) { for my $from_field ($source_r->field( $f )) { for my $to_field ($target_r->field( $f )) { if (exists($fields{$f}{match})) { next unless (grep { $_ =~ $field{$f}{match}{re} } $to_field->subfield($field{$f}{match}{sf})); } my @new_sf = map { ($_ => $from_field->subfield($_)) } @{$fields{$f}}; $to_field->add_subfields( @new_sf ); } } } else { my @new_fields = map { $_->clone } $source_r->field( $f ); $target_r->insert_fields_ordered( @new_fields ); } } $target_xml = $target_r->as_xml_record; $target_xml =~ s/^<\?.+?\?>$//mo; $target_xml =~ s/\n//sgo; $target_xml =~ s/>\s+new_from_xml( $xml ); return undef unless ($r); my $id = shift() || $r->subfield( '035' => 'a' ) || $r->subfield( '901' => 'c' ); $id =~ s/^\s*(?:\([^)]+\))?\s*(.+)\s*?$/$1/; return undef unless ($id); # We need an ID! my $tmpl = MARC::Record->new(); my @rule_fields; for my $field ( $r->field( '1..' ) ) { # Get main entry fields from the authority record my $tag = $field->tag; my $i1 = $field->indicator(1); my $i2 = $field->indicator(2); my $sf = join '', map { $_->[0] } $field->subfields; my @data = map { @$_ } $field->subfields; my @replace_them; # Map the authority field to bib fields it can control. if ($tag >= 100 and $tag <= 111) { # names @replace_them = map { $tag + $_ } (0, 300, 500, 600, 700); } elsif ($tag eq '130') { # uniform title @replace_them = qw/130 240 440 730 830/; } elsif ($tag >= 150 and $tag <= 155) { # subjects @replace_them = ($tag + 500); } elsif ($tag >= 180 and $tag <= 185) { # floating subdivisions @replace_them = qw/100 400 600 700 800 110 410 610 710 810 111 411 611 711 811 130 240 440 730 830 650 651 655/; } else { next; } # Dummy up the bib-side data $tmpl->append_fields( map { MARC::Field->new( $_, $i1, $i2, @data ) } @replace_them ); # Construct some 'replace' rules push @rule_fields, map { $_ . $sf . '[0~\)' .$id . '$]' } @replace_them; } # Insert the replace rules into the template $tmpl->append_fields( MARC::Field->new( '905' => ' ' => ' ' => 'r' => join(',', @rule_fields ) ) ); $xml = $tmpl->as_xml_record; $xml =~ s/^<\?.+?\?>$//mo; # Leave formatting intact for now #$xml =~ s/\n//sgo; #$xml =~ s/>\s+