mods 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +6 -2
- data/lib/mods.rb +12 -2
- data/lib/mods/constants.rb +60 -0
- data/lib/mods/marc_relator_codes.rb +228 -0
- data/lib/mods/name.rb +18 -0
- data/lib/mods/nom_terminology.rb +221 -0
- data/lib/mods/reader.rb +41 -0
- data/lib/mods/record.rb +145 -0
- data/lib/mods/title_info.rb +24 -0
- data/lib/mods/version.rb +2 -1
- data/mods.gemspec +12 -6
- data/spec/language_spec.rb +69 -0
- data/spec/location_spec.rb +148 -0
- data/spec/name_spec.rb +257 -0
- data/spec/origin_info_spec.rb +311 -0
- data/spec/physical_description_spec.rb +79 -0
- data/spec/reader_spec.rb +50 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/title_spec.rb +111 -0
- data/spec/top_level_elmnts_simple_spec.rb +32 -0
- metadata +69 -10
data/README.rdoc
CHANGED
@@ -1,10 +1,12 @@
|
|
1
1
|
= Mods
|
2
2
|
|
3
|
-
|
3
|
+
{<img src="https://secure.travis-ci.org/sul-dlss/mods.png?branch=master" alt="Build Status" />}[http://travis-ci.org/sul-dlss/mods]
|
4
|
+
|
5
|
+
A Gem to parse MODS (Metadata Object Description Schema) records. More information about MODS can be found at http://www.loc.gov/standards/mods/registry.php.
|
4
6
|
|
5
7
|
Source code at https://github.com/sul-dlss/mods/
|
6
8
|
|
7
|
-
Generated API docs at http://rubydoc.info/
|
9
|
+
Generated API docs at http://rubydoc.info/github/sul-dlss/mods/
|
8
10
|
|
9
11
|
== Installation
|
10
12
|
|
@@ -35,5 +37,7 @@ TODO: Write usage instructions here
|
|
35
37
|
|
36
38
|
== Releases
|
37
39
|
|
40
|
+
0.0.4 implement language, location, origin_info, physical_description
|
41
|
+
0.0.3 use nom-xml gem and make this more nokogiri-ish; implement name, title, and simple top level elements with no subelements
|
38
42
|
0.0.2 Set up rake tasks, publishing rdoc, and continuous integration.
|
39
43
|
0.0.1 Grab the name
|
data/lib/mods.rb
CHANGED
@@ -1,5 +1,15 @@
|
|
1
|
-
require
|
1
|
+
require 'mods/constants'
|
2
|
+
require 'mods/marc_relator_codes'
|
3
|
+
require 'mods/name'
|
4
|
+
require 'mods/nom_terminology'
|
5
|
+
require 'mods/reader'
|
6
|
+
require 'mods/record'
|
7
|
+
require 'mods/title_info'
|
8
|
+
require 'mods/version'
|
9
|
+
|
10
|
+
require 'nokogiri'
|
11
|
+
require 'nom/xml'
|
2
12
|
|
3
13
|
module Mods
|
4
|
-
|
14
|
+
|
5
15
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Mods
|
2
|
+
# the version of MODS supported by this gem
|
3
|
+
MODS_VERSION = '3.4'
|
4
|
+
|
5
|
+
MODS_NS_V3 = "http://www.loc.gov/mods/v3"
|
6
|
+
MODS_NS = MODS_NS_V3
|
7
|
+
MODS_XSD = "http://www.loc.gov/standards/mods/mods.xsd"
|
8
|
+
|
9
|
+
DOC_URL = "http://www.loc.gov/standards/mods/"
|
10
|
+
|
11
|
+
# top level elements that cannot have subelement children
|
12
|
+
TOP_LEVEL_ELEMENTS_SIMPLE = [
|
13
|
+
'abstract',
|
14
|
+
'accessCondition',
|
15
|
+
'classification',
|
16
|
+
'extension',
|
17
|
+
'genre',
|
18
|
+
'identifier',
|
19
|
+
'note',
|
20
|
+
'tableOfContents',
|
21
|
+
'targetAudience',
|
22
|
+
'typeOfResource',
|
23
|
+
]
|
24
|
+
|
25
|
+
# top level elements that can have subelement children
|
26
|
+
TOP_LEVEL_ELEMENTS_COMPLEX = [
|
27
|
+
'language',
|
28
|
+
'location',
|
29
|
+
'name',
|
30
|
+
'originInfo',
|
31
|
+
'part',
|
32
|
+
'physicalDescription',
|
33
|
+
'recordInfo',
|
34
|
+
'relatedItem',
|
35
|
+
'subject',
|
36
|
+
'titleInfo' ]
|
37
|
+
|
38
|
+
TOP_LEVEL_ELEMENTS = Array.new(TOP_LEVEL_ELEMENTS_SIMPLE).concat(TOP_LEVEL_ELEMENTS_COMPLEX)
|
39
|
+
|
40
|
+
# enumerated attribute values
|
41
|
+
TITLE_INFO_TYPES = ['abbreviated', 'translated', 'alternative', 'uniform']
|
42
|
+
RELATED_ITEM_TYPES = [
|
43
|
+
'preceding', 'succeeding', 'original', 'host', 'constituent', 'series',
|
44
|
+
'otherVersion', 'otherFormat', 'isReferencedBy', 'references', 'reviewOf'
|
45
|
+
]
|
46
|
+
|
47
|
+
# enumerated values
|
48
|
+
TYPE_OF_RESOURCE_VALUES = [
|
49
|
+
'text', 'cartographic', 'notated music', 'sound recording-musical', 'sound recording-nonmusical',
|
50
|
+
'sound recording',
|
51
|
+
'still image',
|
52
|
+
'moving image',
|
53
|
+
'three dimensional object',
|
54
|
+
'software',
|
55
|
+
'multimedia',
|
56
|
+
'mixed material']
|
57
|
+
|
58
|
+
ORIGIN_INFO_DATE_ELEMENTS = ['dateIssued', 'dateCreated', 'dateCaptured', 'dateValid', 'dateModified', 'copyrightDate', 'dateOther']
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,228 @@
|
|
1
|
+
# Represents the Marc Relator Codes mapped to Relators, from http://www.loc.gov/marc/relators/relacode.html
|
2
|
+
# key - Marc Relator code
|
3
|
+
# value - Marc Relator term
|
4
|
+
MARC_RELATOR = {
|
5
|
+
'acp' => 'Art copyist',
|
6
|
+
'act' => 'Actor',
|
7
|
+
'adp' => 'Adapter',
|
8
|
+
'aft' => 'Author of afterword, colophon, etc.',
|
9
|
+
'anl' => 'Analyst',
|
10
|
+
'anm' => 'Animator',
|
11
|
+
'ann' => 'Annotator',
|
12
|
+
'ant' => 'Bibliographic antecedent',
|
13
|
+
'app' => 'Applicant',
|
14
|
+
'aqt' => 'Author in quotations or text abstracts',
|
15
|
+
'arc' => 'Architect',
|
16
|
+
'ard' => 'Artistic director',
|
17
|
+
'arr' => 'Arranger',
|
18
|
+
'art' => 'Artist',
|
19
|
+
'asg' => 'Assignee',
|
20
|
+
'asn' => 'Associated name',
|
21
|
+
'att' => 'Attributed name',
|
22
|
+
'auc' => 'Auctioneer',
|
23
|
+
'aud' => 'Author of dialog',
|
24
|
+
'aui' => 'Author of introduction',
|
25
|
+
'aus' => 'Author of screenplay',
|
26
|
+
'aut' => 'Author',
|
27
|
+
'bdd' => 'Binding designer',
|
28
|
+
'bjd' => 'Bookjacket designer',
|
29
|
+
'bkd' => 'Book designer',
|
30
|
+
'bkp' => 'Book producer',
|
31
|
+
'blw' => 'Blurb writer',
|
32
|
+
'bnd' => 'Binder',
|
33
|
+
'bpd' => 'Bookplate designer',
|
34
|
+
'bsl' => 'Bookseller',
|
35
|
+
'ccp' => 'Conceptor',
|
36
|
+
'chr' => 'Choreographer',
|
37
|
+
'clb' => 'Collaborator',
|
38
|
+
'cli' => 'Client',
|
39
|
+
'cll' => 'Calligrapher',
|
40
|
+
'clr' => 'Colorist',
|
41
|
+
'clt' => 'Collotyper',
|
42
|
+
'cmm' => 'Commentator',
|
43
|
+
'cmp' => 'Composer',
|
44
|
+
'cmt' => 'Compositor',
|
45
|
+
'cng' => 'Cinematographer',
|
46
|
+
'cnd' => 'Conductor',
|
47
|
+
'cns' => 'Censor',
|
48
|
+
'coe' => 'Contestant -appellee',
|
49
|
+
'col' => 'Collector',
|
50
|
+
'com' => 'Compiler',
|
51
|
+
'con' => 'Conservator',
|
52
|
+
'cos' => 'Contestant',
|
53
|
+
'cot' => 'Contestant -appellant',
|
54
|
+
'cov' => 'Cover designer',
|
55
|
+
'cpc' => 'Copyright claimant',
|
56
|
+
'cpe' => 'Complainant-appellee',
|
57
|
+
'cph' => 'Copyright holder',
|
58
|
+
'cpl' => 'Complainant',
|
59
|
+
'cpt' => 'Complainant-appellant',
|
60
|
+
'cre' => 'Creator',
|
61
|
+
'crp' => 'Correspondent',
|
62
|
+
'crr' => 'Corrector',
|
63
|
+
'csl' => 'Consultant',
|
64
|
+
'csp' => 'Consultant to a project',
|
65
|
+
'cst' => 'Costume designer',
|
66
|
+
'ctb' => 'Contributor',
|
67
|
+
'cte' => 'Contestee-appellee',
|
68
|
+
'ctg' => 'Cartographer',
|
69
|
+
'ctr' => 'Contractor',
|
70
|
+
'cts' => 'Contestee',
|
71
|
+
'ctt' => 'Contestee-appellant',
|
72
|
+
'cur' => 'Curator',
|
73
|
+
'cwt' => 'Commentator for written text',
|
74
|
+
'dfd' => 'Defendant',
|
75
|
+
'dfe' => 'Defendant-appellee',
|
76
|
+
'dft' => 'Defendant-appellant',
|
77
|
+
'dgg' => 'Degree grantor',
|
78
|
+
'dis' => 'Dissertant',
|
79
|
+
'dln' => 'Delineator',
|
80
|
+
'dnc' => 'Dancer',
|
81
|
+
'dnr' => 'Donor',
|
82
|
+
'dpb' => 'Distribution place',
|
83
|
+
'dpc' => 'Depicted',
|
84
|
+
'dpt' => 'Depositor',
|
85
|
+
'drm' => 'Draftsman',
|
86
|
+
'drt' => 'Director',
|
87
|
+
'dsr' => 'Designer',
|
88
|
+
'dst' => 'Distributor',
|
89
|
+
'dtc' => 'Data contributor',
|
90
|
+
'dte' => 'Dedicatee',
|
91
|
+
'dtm' => 'Data manager',
|
92
|
+
'dto' => 'Dedicator',
|
93
|
+
'dub' => 'Dubious author',
|
94
|
+
'edt' => 'Editor',
|
95
|
+
'egr' => 'Engraver',
|
96
|
+
'elg' => 'Electrician',
|
97
|
+
'elt' => 'Electrotyper',
|
98
|
+
'eng' => 'Engineer',
|
99
|
+
'etr' => 'Etcher',
|
100
|
+
'evp' => 'Event place',
|
101
|
+
'exp' => 'Expert',
|
102
|
+
'fac' => 'Facsimilist',
|
103
|
+
'fld' => 'Field director',
|
104
|
+
'flm' => 'Film editor',
|
105
|
+
'fmo' => 'Former owner',
|
106
|
+
'fpy' => 'First party',
|
107
|
+
'fnd' => 'Funder',
|
108
|
+
'frg' => 'Forger',
|
109
|
+
'gis' => 'Geographic information specialist',
|
110
|
+
'grt' => 'Graphic technician',
|
111
|
+
'hnr' => 'Honoree',
|
112
|
+
'hst' => 'Host',
|
113
|
+
'ill' => 'Illustrator',
|
114
|
+
'ilu' => 'Illuminator',
|
115
|
+
'ins' => 'Inscriber',
|
116
|
+
'inv' => 'Inventor',
|
117
|
+
'itr' => 'Instrumentalist',
|
118
|
+
'ive' => 'Interviewee',
|
119
|
+
'ivr' => 'Interviewer',
|
120
|
+
'lbr' => 'Laboratory',
|
121
|
+
'lbt' => 'Librettist',
|
122
|
+
'ldr' => 'Laboratory director',
|
123
|
+
'led' => 'Lead',
|
124
|
+
'lee' => 'Libelee-appellee',
|
125
|
+
'lel' => 'Libelee',
|
126
|
+
'len' => 'Lender',
|
127
|
+
'let' => 'Libelee-appellant',
|
128
|
+
'lgd' => 'Lighting designer',
|
129
|
+
'lie' => 'Libelant-appellee',
|
130
|
+
'lil' => 'Libelant',
|
131
|
+
'lit' => 'Libelant-appellant',
|
132
|
+
'lsa' => 'Landscape architect',
|
133
|
+
'lse' => 'Licensee',
|
134
|
+
'lso' => 'Licensor',
|
135
|
+
'ltg' => 'Lithographer',
|
136
|
+
'lyr' => 'Lyricist',
|
137
|
+
'mcp' => 'Music copyist',
|
138
|
+
'mfp' => 'Manufacture place',
|
139
|
+
'mfr' => 'Manufacturer',
|
140
|
+
'mdc' => 'Metadata contact',
|
141
|
+
'mod' => 'Moderator',
|
142
|
+
'mon' => 'Monitor',
|
143
|
+
'mrb' => 'Marbler',
|
144
|
+
'mrk' => 'Markup editor',
|
145
|
+
'msd' => 'Musical director',
|
146
|
+
'mte' => 'Metal-engraver',
|
147
|
+
'mus' => 'Musician',
|
148
|
+
'nrt' => 'Narrator',
|
149
|
+
'opn' => 'Opponent',
|
150
|
+
'org' => 'Originator',
|
151
|
+
'orm' => 'Organizer of meeting',
|
152
|
+
'oth' => 'Other',
|
153
|
+
'own' => 'Owner',
|
154
|
+
'pat' => 'Patron',
|
155
|
+
'pbd' => 'Publishing director',
|
156
|
+
'pbl' => 'Publisher',
|
157
|
+
'pdr' => 'Project director',
|
158
|
+
'pfr' => 'Proofreader',
|
159
|
+
'pht' => 'Photographer',
|
160
|
+
'plt' => 'Platemaker',
|
161
|
+
'pma' => 'Permitting agency',
|
162
|
+
'pmn' => 'Production manager',
|
163
|
+
'pop' => 'Printer of plates',
|
164
|
+
'ppm' => 'Papermaker',
|
165
|
+
'ppt' => 'Puppeteer',
|
166
|
+
'prc' => 'Process contact',
|
167
|
+
'prd' => 'Production personnel',
|
168
|
+
'prf' => 'Performer',
|
169
|
+
'prg' => 'Programmer',
|
170
|
+
'prm' => 'Printmaker',
|
171
|
+
'pro' => 'Producer',
|
172
|
+
'prp' => 'Production place',
|
173
|
+
'prt' => 'Printer',
|
174
|
+
'pta' => 'Patent applicant',
|
175
|
+
'pte' => 'Plaintiff -appellee',
|
176
|
+
'ptf' => 'Plaintiff',
|
177
|
+
'pth' => 'Patent holder',
|
178
|
+
'ptt' => 'Plaintiff-appellant',
|
179
|
+
'pup' => 'Publication place',
|
180
|
+
'rbr' => 'Rubricator',
|
181
|
+
'rce' => 'Recording engineer',
|
182
|
+
'rcp' => 'Recipient',
|
183
|
+
'red' => 'Redactor',
|
184
|
+
'ren' => 'Renderer',
|
185
|
+
'res' => 'Researcher',
|
186
|
+
'rev' => 'Reviewer',
|
187
|
+
'rps' => 'Repository',
|
188
|
+
'rpt' => 'Reporter',
|
189
|
+
'rpy' => 'Responsible party',
|
190
|
+
'rse' => 'Respondent-appellee',
|
191
|
+
'rsg' => 'Restager',
|
192
|
+
'rsp' => 'Respondent',
|
193
|
+
'rst' => 'Respondent-appellant',
|
194
|
+
'rth' => 'Research team head',
|
195
|
+
'rtm' => 'Research team member',
|
196
|
+
'sad' => 'Scientific advisor',
|
197
|
+
'sce' => 'Scenarist',
|
198
|
+
'scl' => 'Sculptor',
|
199
|
+
'scr' => 'Scribe',
|
200
|
+
'sds' => 'Sound designer',
|
201
|
+
'sec' => 'Secretary',
|
202
|
+
'sgn' => 'Signer',
|
203
|
+
'sht' => 'Supporting host',
|
204
|
+
'sng' => 'Singer',
|
205
|
+
'spk' => 'Speaker',
|
206
|
+
'spn' => 'Sponsor',
|
207
|
+
'spy' => 'Second party',
|
208
|
+
'srv' => 'Surveyor',
|
209
|
+
'std' => 'Set designer',
|
210
|
+
'stl' => 'Storyteller',
|
211
|
+
'stm' => 'Stage manager',
|
212
|
+
'stn' => 'Standards body',
|
213
|
+
'str' => 'Stereotyper',
|
214
|
+
'tcd' => 'Technical director',
|
215
|
+
'tch' => 'Teacher',
|
216
|
+
'ths' => 'Thesis advisor',
|
217
|
+
'trc' => 'Transcriber',
|
218
|
+
'trl' => 'Translator',
|
219
|
+
'tyd' => 'Type designer',
|
220
|
+
'tyg' => 'Typographer',
|
221
|
+
'uvp' => 'University place',
|
222
|
+
'vdg' => 'Videographer',
|
223
|
+
'voc' => 'Vocalist',
|
224
|
+
'wam' => 'Writer of accompanying material',
|
225
|
+
'wdc' => 'Woodcutter',
|
226
|
+
'wde' => 'Wood-engraver',
|
227
|
+
'wit' => 'Witness'
|
228
|
+
}
|
data/lib/mods/name.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Mods
|
2
|
+
|
3
|
+
class Name
|
4
|
+
|
5
|
+
NS_HASH = {'m' => MODS_NS_V3}
|
6
|
+
SUBELEMENTS = ['namePart', 'displayForm', 'affiliation', 'role', 'description']
|
7
|
+
|
8
|
+
# attributes on name node
|
9
|
+
ATTRIBUTES = ['type', 'authority', 'authorityURI', 'valueURI', 'displayLabel', 'usage', 'altRepGroup', 'nameTitleGroup']
|
10
|
+
|
11
|
+
# valid values for type attribute on name node <name type="val"/>
|
12
|
+
TYPES = ['personal', 'corporate', 'conference', 'family']
|
13
|
+
# valid values for type attribute on namePart node <name><namePart type="val"/></name>
|
14
|
+
NAME_PART_TYPES = ['date', 'family', 'given', 'termsOfAddress']
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,221 @@
|
|
1
|
+
module Mods
|
2
|
+
|
3
|
+
class Record
|
4
|
+
|
5
|
+
# set the NOM terminology; do NOT use namespaces
|
6
|
+
# @param mods_ng_xml a Nokogiri::Xml::Document object containing MODS (without namespaces)
|
7
|
+
def set_terminology_no_ns(mods_ng_xml)
|
8
|
+
mods_ng_xml.set_terminology() do |t|
|
9
|
+
|
10
|
+
# FIXME: may want to deal with camelcase vs. underscore in method_missing
|
11
|
+
|
12
|
+
# These elements have no subelements - w00t!
|
13
|
+
Mods::TOP_LEVEL_ELEMENTS_SIMPLE.each { |elname|
|
14
|
+
t.send elname, :path => "/mods/#{elname}"
|
15
|
+
}
|
16
|
+
|
17
|
+
# TITLE_INFO ----------------------------------------------------------------------------
|
18
|
+
# note - titleInfo can be a top level element or a sub-element of relatedItem
|
19
|
+
# (<titleInfo> as subelement of <subject> is not part of the MODS namespace)
|
20
|
+
|
21
|
+
t.title_info :path => '/mods/titleInfo' do |n|
|
22
|
+
n.type_at :path => '@type'
|
23
|
+
n.title :path => 'title'
|
24
|
+
n.subTitle :path => 'subTitle'
|
25
|
+
n.nonSort :path => 'nonSort'
|
26
|
+
n.partNumber :path => 'partNumber'
|
27
|
+
n.partName :path => 'partName'
|
28
|
+
n.sort_title :path => '.', :accessor => lambda { |node|
|
29
|
+
if node.type_at.text != "alternative" || (node.type_at.text == "alternative" && mods_ng_xml.xpath('/mods/titleInfo').size == 1)
|
30
|
+
node.title.text + (!node.subTitle.text.empty? ? "#{@title_delimiter}#{node.subTitle.text}" : "" )
|
31
|
+
end
|
32
|
+
}
|
33
|
+
n.full_title :path => '.', :accessor => lambda { |node|
|
34
|
+
(!node.nonSort.text.empty? ? "#{node.nonSort.text} " : "" ) +
|
35
|
+
node.title.text +
|
36
|
+
(!node.subTitle.text.empty? ? "#{@title_delimiter}#{node.subTitle.text}" : "" )
|
37
|
+
}
|
38
|
+
n.short_title :path => '.', :accessor => lambda { |node|
|
39
|
+
if node.type_at.text != "alternative"
|
40
|
+
(!node.nonSort.text.empty? ? "#{node.nonSort.text} " : "" ) +
|
41
|
+
node.title.text
|
42
|
+
end
|
43
|
+
}
|
44
|
+
n.alternative_title :path => '.', :accessor => lambda { |node|
|
45
|
+
if node.type_at.text == "alternative"
|
46
|
+
(!node.nonSort.text.empty? ? "#{node.nonSort.text} " : "" ) +
|
47
|
+
node.title.text
|
48
|
+
end
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
# current way to do short_title correctly
|
53
|
+
# t.short_title :path => '/mods/titleInfo[not(@type=alternative)]', :accessor => lambda { |node|
|
54
|
+
# (!node.nonSort.text.empty? ? "#{node.nonSort.text} " : "" ) +
|
55
|
+
# node.title.text
|
56
|
+
# }
|
57
|
+
|
58
|
+
|
59
|
+
# NAME ------------------------------------------------------------------------------------
|
60
|
+
|
61
|
+
t.plain_name :path => '/mods/name' do |n|
|
62
|
+
|
63
|
+
Mods::Name::ATTRIBUTES.each { |attr_name|
|
64
|
+
if attr_name != 'type'
|
65
|
+
n.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
|
66
|
+
else
|
67
|
+
n.type_at :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
|
68
|
+
end
|
69
|
+
}
|
70
|
+
|
71
|
+
n.namePart :path => 'namePart' do |np|
|
72
|
+
np.type_at :path => '@type'
|
73
|
+
end
|
74
|
+
n.displayForm :path => 'displayForm'
|
75
|
+
n.affiliation :path => 'affiliation'
|
76
|
+
n.description_el :path => 'description' # description is used by Nokogiri
|
77
|
+
n.role :path => 'role/roleTerm' do |r|
|
78
|
+
r.type_at :path => "@type", :accessor => lambda { |a| a.text }
|
79
|
+
r.authority :path => "@authority", :accessor => lambda { |a| a.text }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
t.personal_name :path => '/mods/name[@type="personal"]' do |n|
|
84
|
+
n.family_name :path => 'namePart[@type="family"]'
|
85
|
+
n.given_name :path => 'namePart[@type="given"]'
|
86
|
+
n.termsOfAddress :path => 'namePart[@type="termsOfAddress"]'
|
87
|
+
n.date :path => 'namePart[@type="date"]'
|
88
|
+
end
|
89
|
+
|
90
|
+
t.corporate_name :path => '/mods/name[@type="corporate"]'
|
91
|
+
t.conference_name :path => '/mods/name[@type="conference"]'
|
92
|
+
|
93
|
+
# LANGUAGE -------------------------------------------------------------------------------
|
94
|
+
|
95
|
+
t.language :path => '/mods/language' do |n|
|
96
|
+
n.languageTerm :path => 'languageTerm' do |lt|
|
97
|
+
lt.type_at :path => '@type', :accessor => lambda { |a| a.text }
|
98
|
+
lt.authority :path => '@authority', :accessor => lambda { |a| a.text }
|
99
|
+
end
|
100
|
+
n.code_term :path => 'languageTerm[@type="code"]'
|
101
|
+
n.text_term :path => 'languageTerm[@type="text"]'
|
102
|
+
n.scriptTerm :path => 'scriptTerm'
|
103
|
+
end
|
104
|
+
|
105
|
+
# PHYSICAL_DESCRIPTION -------------------------------------------------------------------
|
106
|
+
t.physical_description :path => '/mods/physicalDescription' do |n|
|
107
|
+
n.digitalOrigin :path => 'digitalOrigin'
|
108
|
+
n.extent :path => 'extent'
|
109
|
+
n.form :path => 'form' do |f|
|
110
|
+
f.authority :path => '@authority', :accessor => lambda { |a| a.text }
|
111
|
+
f.type_at :path => '@type', :accessor => lambda { |a| a.text }
|
112
|
+
end
|
113
|
+
n.internetMediaType :path => 'internetMediaType'
|
114
|
+
n.note :path => 'note' do |nn|
|
115
|
+
nn.displayLabel :path => '@displayLabel', :accessor => lambda { |a| a.text }
|
116
|
+
nn.type_at :path => '@type', :accessor => lambda { |a| a.text }
|
117
|
+
end
|
118
|
+
n.reformattingQuality :path => 'reformattingQuality'
|
119
|
+
end
|
120
|
+
|
121
|
+
# LOCATION -------------------------------------------------------------------------------
|
122
|
+
t.location :path => '/mods/location' do |n|
|
123
|
+
n.physicalLocation :path => 'physicalLocation' do |e|
|
124
|
+
e.authority :path => '@authority', :accessor => lambda { |a| a.text }
|
125
|
+
e.displayLabel :path => '@displayLabel', :accessor => lambda { |a| a.text }
|
126
|
+
end
|
127
|
+
n.shelfLocator :path => 'shelfLocator'
|
128
|
+
n.url :path => 'url' do |e|
|
129
|
+
e.dateLastAccessed :path => '@dateLastAccessed', :accessor => lambda { |a| a.text }
|
130
|
+
e.displayLabel :path => '@displayLabel', :accessor => lambda { |a| a.text }
|
131
|
+
e.note :path => '@note', :accessor => lambda { |a| a.text }
|
132
|
+
e.access :path => '@access', :accessor => lambda { |a| a.text }
|
133
|
+
e.usage :path => '@usage', :accessor => lambda { |a| a.text }
|
134
|
+
end
|
135
|
+
n.holdingSimple :path => 'holdingSimple'
|
136
|
+
n.holdingExternal :path => 'holdingExternal'
|
137
|
+
end
|
138
|
+
|
139
|
+
# ORIGIN_INFO --------------------------------------------------------------------------
|
140
|
+
t.origin_info :path => '/mods/originInfo' do |n|
|
141
|
+
n.place :path => 'place' do |e|
|
142
|
+
e.placeTerm :path => 'placeTerm' do |ee|
|
143
|
+
ee.type_at :path => '@type', :accessor => lambda { |a| a.text }
|
144
|
+
ee.authority :path => '@authority', :accessor => lambda { |a| a.text }
|
145
|
+
end
|
146
|
+
end
|
147
|
+
n.publisher :path => 'publisher'
|
148
|
+
Mods::ORIGIN_INFO_DATE_ELEMENTS.each { |date_el|
|
149
|
+
n.send date_el, :path => "#{date_el}" do |d|
|
150
|
+
d.encoding :path => '@encoding', :accessor => lambda { |a| a.text }
|
151
|
+
d.point :path => '@point', :accessor => lambda { |a| a.text }
|
152
|
+
d.keyDate :path => '@keyDate', :accessor => lambda { |a| a.text }
|
153
|
+
d.qualifier :path => '@qualifier', :accessor => lambda { |a| a.text }
|
154
|
+
if date_el == 'dateOther'
|
155
|
+
d.type_at :path => '@type', :accessor => lambda { |a| a.text }
|
156
|
+
end
|
157
|
+
end
|
158
|
+
}
|
159
|
+
n.edition :path => 'edition'
|
160
|
+
n.issuance :path => 'issuance'
|
161
|
+
n.frequency :path => 'frequency' do |f|
|
162
|
+
f.authority :path => '@authority', :accessor => lambda { |a| a.text }
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end # terminology
|
167
|
+
|
168
|
+
mods_ng_xml.nom!
|
169
|
+
|
170
|
+
mods_ng_xml
|
171
|
+
end # set_terminology_no_ns
|
172
|
+
|
173
|
+
# TODO: common top level element attributes: ID; xlink; lang; xml:lang; script; transliteration
|
174
|
+
# authority, authorityURI, valueURI
|
175
|
+
# displayLabel, usage altRepGroup
|
176
|
+
# type
|
177
|
+
# TODO: common subelement attributes: lang, xml:lang, script, transliteration
|
178
|
+
# TODO: other common attribute: supplied
|
179
|
+
|
180
|
+
|
181
|
+
# set the NOM terminology, with namespaces
|
182
|
+
# @param mods_ng_xml a Nokogiri::Xml::Document object containing MODS (with namespaces)
|
183
|
+
def set_terminology_ns(mods_ng_xml)
|
184
|
+
mods_ng_xml.set_terminology(:namespaces => { 'm' => Mods::MODS_NS}) do |t|
|
185
|
+
|
186
|
+
# note - titleInfo can be a top level element or a sub-element of subject and relatedItem
|
187
|
+
t.title_info :path => '//m:titleInfo' do |n|
|
188
|
+
n.title :path => 'm:title'
|
189
|
+
n.subTitle :path => 'm:subTitle'
|
190
|
+
n.nonSort :path => 'm:nonSort'
|
191
|
+
n.partNumber :path => 'm:partNumber'
|
192
|
+
n.partName :path => 'm:partName'
|
193
|
+
n.type_at :path => '@type'
|
194
|
+
end
|
195
|
+
|
196
|
+
t.author :path => '//m:name' do |n|
|
197
|
+
n.valueURI :path => '@valueURI'
|
198
|
+
n.namePart :path => 'm:namePart', :single => true
|
199
|
+
end
|
200
|
+
|
201
|
+
t.corporate_authors :path => '//m:name[@type="corporate"]'
|
202
|
+
t.personal_authors :path => 'm:name[@type="personal"]' do |n|
|
203
|
+
n.roleTerm :path => 'm:role/m:roleTerm'
|
204
|
+
n.name_role_pair :path => '.', :accessor => lambda { |node| node.roleTerm.text + ": " + node.namePart.text }
|
205
|
+
end
|
206
|
+
|
207
|
+
t.language :path => 'm:language' do |n|
|
208
|
+
n.value :path => 'm:languageTerm', :accessor => :text
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
mods_ng_xml.nom!
|
214
|
+
|
215
|
+
mods_ng_xml
|
216
|
+
end # set_terminology_ns
|
217
|
+
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|