From 188446d938862bf91c27b41e3bfb63e0396e23a3 Mon Sep 17 00:00:00 2001 From: Alexander Wagner Date: Thu, 18 Jul 2024 16:03:20 +0200 Subject: [PATCH] Bug 37196: Add automatic punctuation for Marc title fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new MARC filter to automatically inject punctuation for MARC fields 245, 246 and 246 if the MARC Leader 18 is set to `c` or `n`. Otherwise assume the punctuation exists and use the subfield data _as is_. Hook in this filter before any XSL tranformations happen, so all subsequent processing can assume that punctuation _exists_. The following subfields are handled: - 245: bcdefghknps - 246/247: bfghinqrt Note: some special cases (like title translations that should get an `=` instead of a `:`) can not be handled fully automatically. Testplan: 1. Start `ktd` 2. Check a record with additional title fields. Examples: - biblionumber 55: DÃ in do Eimhir = Poems to Eimhir / Somhairle MacGill-Eain = Sorley MacLean ; edited by Christopher Whyte. - biblionumber 58 'More fruitful than the soil' : army, empire and the Scottish Highlands, 1715-1815 / Andrew Mackillop. Those should display correctly, as they hold all punctuations _in_ the record. (Marc Leader 18 set to `a`). 3. Apply the patch 4. Call up the records again They should display unchanged as the Leader 18 is still set to `a` => no automatic punctuation is applied 5. Edit both records and only set the Leader 18 to either `c` or `n`. (Note: this is _incorrect_ wrt the record semantic.) All punctuation chars appear _twice_ as Koha adds them automatically as instructed even though they are there. The title display like - DÃ in do Eimhir = : Poems to Eimhir / / Somhairle MacGill-Eain = Sorley MacLean ; edited by Christopher Whyte. - 'More fruitful than the soil' : : army, empire and the Scottish Highlands, 1715-1815 / / Andrew Mackillop. Note that for biblionumber 55 Koha displays `= :` as it is not possible to know automatically that there should be an `=` instad of the `:`. Sponsored-by: Deutsches Elektronen-Synchrotron DESY, Library --- C4/XSLT.pm | 2 +- Koha/Filter/MARC/Punctuation.pm | 201 ++++++++++++++++++++++++++++++++ 2 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 Koha/Filter/MARC/Punctuation.pm diff --git a/C4/XSLT.pm b/C4/XSLT.pm index 458d732d23..64db41bc82 100644 --- a/C4/XSLT.pm +++ b/C4/XSLT.pm @@ -191,7 +191,7 @@ sub XSLTParse4Display { my $frameworkcode = GetFrameworkCode($biblionumber) || ''; my $record_processor = Koha::RecordProcessor->new( { - filters => [ 'ExpandCodedFields' ], + filters => [ 'ExpandCodedFields', 'Punctuation' ], options => { interface => $interface, frameworkcode => $frameworkcode diff --git a/Koha/Filter/MARC/Punctuation.pm b/Koha/Filter/MARC/Punctuation.pm new file mode 100644 index 0000000000..f97478782e --- /dev/null +++ b/Koha/Filter/MARC/Punctuation.pm @@ -0,0 +1,201 @@ +package Koha::Filter::MARC::Punctuation; + +# Copyright 2024 join2 +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# Koha is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Koha; if not, see . + +=head1 NAME + +Koha::Filter::MARC::Punctuation - Automatically add punctuation to +Marc records if the leader specifies they were catalogued without it. + +Documentation for proper punctuation: +https://www.loc.gov/aba/pcc/documents/isbdmarc2016.pdf + +=head1 DESCRIPTION + +If the Marc leader 18 specifies, that the record was catalogued +without punctuation add the proper punctuation chars to the individual +fields before passing the record on to fruther processing. Once this +filter is applied it should be safe for further steps to assume that +the record holds Marc punctuation. (The records in the database are +_not_ changed.) + +Trigger to add punctuation: leader 18 is either `n` or `c`. + +Currently handled fields: + +- 245 +- 246 +- 247 + +=cut + +use strict; +use warnings; + +use base qw(Koha::RecordProcessor::Base); +our $NAME = 'Punctuation'; + +=head2 _decorate_245 + +Add punctuation to MARC field 245 (title statement). The function +assumes that it is only called if no punctuation is part of the +record. +=cut + +sub _decorate_245 { + + my ($field) = @_; + + # simple chars _preceeding_ a subfield + my %pchrs = ( + 'b' => ' : ', + 'c' => ' / ', + 'd' => ' ; ', + 'e' => '. ', + 'f' => ', ', + 'g' => ', ', + 'k' => ' : ', + 'n' => '. ', + 'p' => ', ', + 's' => '. ', + ); + + my @new_subfields = (); + foreach my $subfield ( $field->subfields ) { + my $sf = $subfield->[0]; + my $value = $subfield->[1]; + + if ( exists $pchrs{$sf} ) { + $value = $pchrs{$sf} . $value; + } + + # media type needs to be enclosed + if ( $sf eq 'h' ) { + $value = '[' . $value . ']'; + } + + push( @new_subfields, $sf, $value ); + + # TBD does titles always end with a `.`? + } + return @new_subfields; +} + +=head2 _decorate_246_247 + +Add punctuation to MARC field 246 (varying form title), 247 (former +title). The function assumes that it is only called if no punctuation +is part of the record. + +=cut + +sub _decorate_246_247 { + + my ($field) = @_; + + my %pchrs = ( + 'b' => ' : ', + 'f' => ', ', + 'n' => '. ', + 'q' => ', ', + 'r' => ' = ', + 't' => ' = ', + ); + + my @new_subfields = (); + foreach my $subfield ( $field->subfields ) { + my $sf = $subfield->[0]; + my $value = $subfield->[1]; + + if ( exists $pchrs{$sf} ) { + $value = $pchrs{$sf} . $value; + } + + if ( $sf eq 'i' ) { + + # _append_ a char to i + $value .= ': '; + } + if ( $sf eq 'g' ) { + $value = '(' . $value . ')'; + } + + # media type needs to be enclosed + if ( $sf eq 'h' ) { + $value = '[' . $value . ']'; + } + + push( @new_subfields, $sf, $value ); + + # TBD does titles always end with a `.`? + } + return @new_subfields; +} + +=head2 filter + + my $newrecord = $filter->filter($record); + +Return title fields with proper punctuation either as the record held +them already or as they were added. + +=cut + +sub filter { + my ( $self, $record ) = @_; + + return + unless $record and ref($record) eq 'MARC::Record'; + + my $leader = $record->leader(); + my $punctuation_omitted = + ( ( substr( $leader, 18, 1 ) eq 'c' ) or ( substr( $leader, 18, 1 ) eq 'n' ) ); + + if ($punctuation_omitted) { + my @new_subfields = (); + foreach my $field ( $record->fields ) { + @new_subfields = (); + + # decorate fields by individual functions: + if ( $field->tag() eq "245" ) { + @new_subfields = _decorate_245($field); + } + + if ( ( $field->tag() eq "246" ) + or ( $field->tag() eq "247" ) ) + { + @new_subfields = _decorate_246_247($field); + } + + # If filtered, replace the field content + if (@new_subfields) { + $field->replace_with( + MARC::Field->new( + $field->tag(), + $field->indicator(1), + $field->indicator(2), + @new_subfields + ) + ); + } + } + } + return $record; +} + +1; -- 2.39.5