mods 0.0.2 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,12 @@
1
1
  = Mods
2
2
 
3
- A Ruby 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.
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/gems/mods/
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
@@ -1,5 +1,15 @@
1
- require "mods/version"
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
- # Your code goes here...
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
+ }
@@ -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
+