From 06ea5ec9b641bb550db2ef4bb41aed5c9b6a51d7 Mon Sep 17 00:00:00 2001 From: Dan Scott Date: Wed, 5 Sep 2012 00:27:03 -0400 Subject: [PATCH] TPAC: Fine-grained credits in record details MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit For 7xx fields with $4 subfields containing relator codes, generate a relator code map from http://www.loc.gov/marc/relators/relacode.html that we can use in the record details to provide specific credits, rather than the generic (and often inappropriate) "Added author" label. For example: 700 1. ‡aMaley, Desmond, ‡d1954- ‡4prf. This now generates "Maley, Desmond, 1954- (Performer)" in the record details credit section. Signed-off-by: Dan Scott Signed-off-by: Ben Shum --- .../templates/opac/parts/record/authors.tt2 | 13 +- .../src/templates/opac/parts/relators.tt2 | 228 ++++++++++++++++++ build/tools/relator_map | 72 ++++++ 3 files changed, 308 insertions(+), 5 deletions(-) create mode 100644 Open-ILS/src/templates/opac/parts/relators.tt2 create mode 100644 build/tools/relator_map diff --git a/Open-ILS/src/templates/opac/parts/record/authors.tt2 b/Open-ILS/src/templates/opac/parts/record/authors.tt2 index 4a0419cfdf..bc61e48f2a 100644 --- a/Open-ILS/src/templates/opac/parts/record/authors.tt2 +++ b/Open-ILS/src/templates/opac/parts/record/authors.tt2 @@ -1,5 +1,7 @@ [%- +PROCESS "opac/parts/relators.tt2"; + authors = [ { type => 'author', @@ -9,10 +11,6 @@ authors = [ type => 'added', label => l('Added Author'), xpath => '//*[@tag="700"]|//*[@tag="710"]|//*[@tag="711"]' - }, { - type => 'credits', - label => l('Credited'), - xpath => '//*[@tag="100"]|//*[@tag="110"]|//*[@tag="111"]' }, { type => 'cast', label => l('Cast'), @@ -29,9 +27,14 @@ BLOCK build_author_links; term = ''; qterm = ''; iprop = ''; + tlabel = ''; FOR subfield IN node.childNodes; NEXT UNLESS subfield.nodeName == "subfield"; code = subfield.getAttribute('code'); + IF code == '4'; + relcode = subfield.textContent.substr(0,3); + tlabel = relators.$relcode || label; + END; NEXT UNLESS code.match('[a-z]'); sf_raw = subfield.textContent; sf = subfield.textContent | html; @@ -39,7 +42,7 @@ BLOCK build_author_links; qterm = qterm _ ' ' _ sf_raw; END; url = mkurl(ctx.opac_root _ '/results', {query => qterm, qtype => 'author'}, ['page', 'expand']); - author_type = label | html; + author_type = (tlabel || label) | html; # schema.org changes IF type == 'author'; diff --git a/Open-ILS/src/templates/opac/parts/relators.tt2 b/Open-ILS/src/templates/opac/parts/relators.tt2 new file mode 100644 index 0000000000..3fd4a93c46 --- /dev/null +++ b/Open-ILS/src/templates/opac/parts/relators.tt2 @@ -0,0 +1,228 @@ +[%- +# Generated from http://www.loc.gov/marc/relators/relacode.html +# using the build/tools/relator_map script +relators = { + 'acp' => l('Art copyist'), + 'act' => l('Actor'), + 'adp' => l('Adapter'), + 'aft' => l('Author of afterword, colophon, etc.'), + 'anl' => l('Analyst'), + 'anm' => l('Animator'), + 'ann' => l('Annotator'), + 'ant' => l('Bibliographic antecedent'), + 'app' => l('Applicant'), + 'aqt' => l('Author in quotations or text abstracts'), + 'arc' => l('Architect'), + 'ard' => l('Artistic director'), + 'arr' => l('Arranger'), + 'art' => l('Artist'), + 'asg' => l('Assignee'), + 'asn' => l('Associated name'), + 'att' => l('Attributed name'), + 'auc' => l('Auctioneer'), + 'aud' => l('Author of dialog'), + 'aui' => l('Author of introduction'), + 'aus' => l('Author of screenplay'), + 'aut' => l('Author'), + 'bdd' => l('Binding designer'), + 'bjd' => l('Bookjacket designer'), + 'bkd' => l('Book designer'), + 'bkp' => l('Book producer'), + 'blw' => l('Blurb writer'), + 'bnd' => l('Binder'), + 'bpd' => l('Bookplate designer'), + 'bsl' => l('Bookseller'), + 'ccp' => l('Conceptor'), + 'chr' => l('Choreographer'), + 'clb' => l('Collaborator'), + 'cli' => l('Client'), + 'cll' => l('Calligrapher'), + 'clr' => l('Colorist'), + 'clt' => l('Collotyper'), + 'cmm' => l('Commentator'), + 'cmp' => l('Composer'), + 'cmt' => l('Compositor'), + 'cnd' => l('Conductor'), + 'cng' => l('Cinematographer'), + 'cns' => l('Censor'), + 'coe' => l('Contestant -appellee'), + 'col' => l('Collector'), + 'com' => l('Compiler'), + 'con' => l('Conservator'), + 'cos' => l('Contestant'), + 'cot' => l('Contestant -appellant'), + 'cov' => l('Cover designer'), + 'cpc' => l('Copyright claimant'), + 'cpe' => l('Complainant-appellee'), + 'cph' => l('Copyright holder'), + 'cpl' => l('Complainant'), + 'cpt' => l('Complainant-appellant'), + 'cre' => l('Creator'), + 'crp' => l('Correspondent'), + 'crr' => l('Corrector'), + 'csl' => l('Consultant'), + 'csp' => l('Consultant to a project'), + 'cst' => l('Costume designer'), + 'ctb' => l('Contributor'), + 'cte' => l('Contestee-appellee'), + 'ctg' => l('Cartographer'), + 'ctr' => l('Contractor'), + 'cts' => l('Contestee'), + 'ctt' => l('Contestee-appellant'), + 'cur' => l('Curator'), + 'cwt' => l('Commentator for written text'), + 'dfd' => l('Defendant'), + 'dfe' => l('Defendant-appellee'), + 'dft' => l('Defendant-appellant'), + 'dgg' => l('Degree grantor'), + 'dis' => l('Dissertant'), + 'dln' => l('Delineator'), + 'dnc' => l('Dancer'), + 'dnr' => l('Donor'), + 'dpb' => l('Distribution place'), + 'dpc' => l('Depicted'), + 'dpt' => l('Depositor'), + 'drm' => l('Draftsman'), + 'drt' => l('Director'), + 'dsr' => l('Designer'), + 'dst' => l('Distributor'), + 'dtc' => l('Data contributor'), + 'dte' => l('Dedicatee'), + 'dtm' => l('Data manager'), + 'dto' => l('Dedicator'), + 'dub' => l('Dubious author'), + 'edt' => l('Editor'), + 'egr' => l('Engraver'), + 'elg' => l('Electrician'), + 'elt' => l('Electrotyper'), + 'eng' => l('Engineer'), + 'etr' => l('Etcher'), + 'evp' => l('Event place'), + 'exp' => l('Expert'), + 'fac' => l('Facsimilist'), + 'fld' => l('Field director'), + 'flm' => l('Film editor'), + 'fmo' => l('Former owner'), + 'fnd' => l('Funder'), + 'fpy' => l('First party'), + 'frg' => l('Forger'), + 'gis' => l('Geographic information specialist'), + 'grt' => l('Graphic technician'), + 'hnr' => l('Honoree'), + 'hst' => l('Host'), + 'ill' => l('Illustrator'), + 'ilu' => l('Illuminator'), + 'ins' => l('Inscriber'), + 'inv' => l('Inventor'), + 'itr' => l('Instrumentalist'), + 'ive' => l('Interviewee'), + 'ivr' => l('Interviewer'), + 'lbr' => l('Laboratory'), + 'lbt' => l('Librettist'), + 'ldr' => l('Laboratory director'), + 'led' => l('Lead'), + 'lee' => l('Libelee-appellee'), + 'lel' => l('Libelee'), + 'len' => l('Lender'), + 'let' => l('Libelee-appellant'), + 'lgd' => l('Lighting designer'), + 'lie' => l('Libelant-appellee'), + 'lil' => l('Libelant'), + 'lit' => l('Libelant-appellant'), + 'lsa' => l('Landscape architect'), + 'lse' => l('Licensee'), + 'lso' => l('Licensor'), + 'ltg' => l('Lithographer'), + 'lyr' => l('Lyricist'), + 'mcp' => l('Music copyist'), + 'mdc' => l('Metadata contact'), + 'mfp' => l('Manufacture place'), + 'mfr' => l('Manufacturer'), + 'mod' => l('Moderator'), + 'mon' => l('Monitor'), + 'mrb' => l('Marbler'), + 'mrk' => l('Markup editor'), + 'msd' => l('Musical director'), + 'mte' => l('Metal-engraver'), + 'mus' => l('Musician'), + 'nrt' => l('Narrator'), + 'opn' => l('Opponent'), + 'org' => l('Originator'), + 'orm' => l('Organizer of meeting'), + 'oth' => l('Other'), + 'own' => l('Owner'), + 'pat' => l('Patron'), + 'pbd' => l('Publishing director'), + 'pbl' => l('Publisher'), + 'pdr' => l('Project director'), + 'pfr' => l('Proofreader'), + 'pht' => l('Photographer'), + 'plt' => l('Platemaker'), + 'pma' => l('Permitting agency'), + 'pmn' => l('Production manager'), + 'pop' => l('Printer of plates'), + 'ppm' => l('Papermaker'), + 'ppt' => l('Puppeteer'), + 'prc' => l('Process contact'), + 'prd' => l('Production personnel'), + 'prf' => l('Performer'), + 'prg' => l('Programmer'), + 'prm' => l('Printmaker'), + 'pro' => l('Producer'), + 'prp' => l('Production place'), + 'prt' => l('Printer'), + 'pta' => l('Patent applicant'), + 'pte' => l('Plaintiff -appellee'), + 'ptf' => l('Plaintiff'), + 'pth' => l('Patent holder'), + 'ptt' => l('Plaintiff-appellant'), + 'pup' => l('Publication place'), + 'rbr' => l('Rubricator'), + 'rce' => l('Recording engineer'), + 'rcp' => l('Recipient'), + 'red' => l('Redactor'), + 'ren' => l('Renderer'), + 'res' => l('Researcher'), + 'rev' => l('Reviewer'), + 'rps' => l('Repository'), + 'rpt' => l('Reporter'), + 'rpy' => l('Responsible party'), + 'rse' => l('Respondent-appellee'), + 'rsg' => l('Restager'), + 'rsp' => l('Respondent'), + 'rst' => l('Respondent-appellant'), + 'rth' => l('Research team head'), + 'rtm' => l('Research team member'), + 'sad' => l('Scientific advisor'), + 'sce' => l('Scenarist'), + 'scl' => l('Sculptor'), + 'scr' => l('Scribe'), + 'sds' => l('Sound designer'), + 'sec' => l('Secretary'), + 'sgn' => l('Signer'), + 'sht' => l('Supporting host'), + 'sng' => l('Singer'), + 'spk' => l('Speaker'), + 'spn' => l('Sponsor'), + 'spy' => l('Second party'), + 'srv' => l('Surveyor'), + 'std' => l('Set designer'), + 'stl' => l('Storyteller'), + 'stm' => l('Stage manager'), + 'stn' => l('Standards body'), + 'str' => l('Stereotyper'), + 'tcd' => l('Technical director'), + 'tch' => l('Teacher'), + 'ths' => l('Thesis advisor'), + 'trc' => l('Transcriber'), + 'trl' => l('Translator'), + 'tyd' => l('Type designer'), + 'tyg' => l('Typographer'), + 'uvp' => l('University place'), + 'vdg' => l('Videographer'), + 'voc' => l('Vocalist'), + 'wam' => l('Writer of accompanying material'), + 'wdc' => l('Woodcutter'), + 'wde' => l('Wood-engraver'), + 'wit' => l('Witness'), +} -%] \ No newline at end of file diff --git a/build/tools/relator_map b/build/tools/relator_map new file mode 100644 index 0000000000..742348248f --- /dev/null +++ b/build/tools/relator_map @@ -0,0 +1,72 @@ +#!/usr/bin/perl +use strict; +use warnings; + +use XML::LibXML; +use XML::LibXML::Reader; +use LWP::Simple; +use Data::Dumper; + +my %relator; +my $code = 0; +my $fullname = 0; +my $code_v; + +my $content = get('http://www.loc.gov/marc/relators/relacode.html'); + +$content =~ s{^}{}s; +$content =~ s{.+?}{}s; +$content =~ s{.+?
}{}s; + +my $reader = XML::LibXML::Reader->new( + string => $content, + recover => 2, + load_ext_dtd => 0 +); + +$reader->nextElement('table'); +$reader->nextElement('tr'); +while($reader->read) { + processNode($reader); +} + +#print Dumper(\%relator); +generateRelatorMap(); + +sub processNode { + my $reader = shift; + if ($reader->nodeType == XML_READER_TYPE_ELEMENT && $reader->name eq 'td') { + if ($reader->getAttribute('class') && $reader->getAttribute('class') eq 'code') { + $code = 1; + } else { + $fullname = 1; + } + } + if ($reader->nodeType == XML_READER_TYPE_TEXT) { + if ($code) { + $code_v = $reader->value(); + + # Treat deprecated codes as valid + $code_v =~ s/^-//; + $code = 0; + } elsif ($fullname) { + $relator{$code_v} = $reader->value(); + $fullname = 0; + } + } +} + +sub generateRelatorMap { + print <<"HEAD"; +[%- +# Generated from http://www.loc.gov/marc/relators/relacode.html +# using the build/tools/relator_map script +HEAD + print 'relators = {' . "\n"; + foreach (sort keys %relator) { + print " '$_' => l('$relator{$_}'),\n"; + } + print '} -%]'; +} -- 2.43.2