mods 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -37,6 +37,7 @@ TODO: Write usage instructions here
37
37
 
38
38
  == Releases
39
39
 
40
+ 0.0.5 implement subject, change a few constants
40
41
  0.0.4 implement language, location, origin_info, physical_description
41
42
  0.0.3 use nom-xml gem and make this more nokogiri-ish; implement name, title, and simple top level elements with no subelements
42
43
  0.0.2 Set up rake tasks, publishing rdoc, and continuous integration.
@@ -1,9 +1,10 @@
1
1
  require 'mods/constants'
2
+ require 'mods/nom_terminology'
2
3
  require 'mods/marc_relator_codes'
3
4
  require 'mods/name'
4
- require 'mods/nom_terminology'
5
5
  require 'mods/reader'
6
6
  require 'mods/record'
7
+ require 'mods/subject'
7
8
  require 'mods/title_info'
8
9
  require 'mods/version'
9
10
 
@@ -2,11 +2,10 @@ module Mods
2
2
 
3
3
  class Name
4
4
 
5
- NS_HASH = {'m' => MODS_NS_V3}
6
- SUBELEMENTS = ['namePart', 'displayForm', 'affiliation', 'role', 'description']
5
+ CHILD_ELEMENTS = ['namePart', 'displayForm', 'affiliation', 'role', 'description']
7
6
 
8
7
  # attributes on name node
9
- ATTRIBUTES = ['type', 'authority', 'authorityURI', 'valueURI', 'displayLabel', 'usage', 'altRepGroup', 'nameTitleGroup']
8
+ ATTRIBUTES = Mods::AUTHORITY_ATTRIBS + ['type', 'displayLabel', 'usage', 'altRepGroup', 'nameTitleGroup']
10
9
 
11
10
  # valid values for type attribute on name node <name type="val"/>
12
11
  TYPES = ['personal', 'corporate', 'conference', 'family']
@@ -1,5 +1,19 @@
1
1
  module Mods
2
2
 
3
+ # from: http://www.loc.gov/standards/mods/v3/mods-userguide-generalapp.html
4
+
5
+ LANG_ATTRIBS = ['lang', 'xml:lang', 'script', 'transliteration']
6
+
7
+ LINKING_ATTRIBS = ['xlink', 'ID']
8
+
9
+ DATE_ATTRIBS = ['encoding', 'point', 'keyDate', 'qualifier']
10
+ ENCODING_ATTRIB_VALUES = ['w3cdtf', 'iso8601', 'marc']
11
+ POINT_ATTRIB_VALUES = ['start', 'end']
12
+ KEY_DATE_ATTRIB_VALUEs = ['yes']
13
+ QUALIFIER_ATTRIB_VALUES = ['approximate', 'inferred', 'questionable']
14
+
15
+ AUTHORITY_ATTRIBS = ['authority', 'authorityURI', 'valueURI']
16
+
3
17
  class Record
4
18
 
5
19
  # set the NOM terminology; do NOT use namespaces
@@ -18,15 +32,23 @@ module Mods
18
32
  # note - titleInfo can be a top level element or a sub-element of relatedItem
19
33
  # (<titleInfo> as subelement of <subject> is not part of the MODS namespace)
20
34
 
21
- t.title_info :path => '/mods/titleInfo' do |n|
22
- n.type_at :path => '@type'
35
+ t.title_info :path => '/mods/titleInfo'
36
+
37
+ t._title_info :path => '//titleInfo' do |n|
38
+ Mods::TitleInfo::ATTRIBUTES.each { |attr_name|
39
+ if attr_name != 'type'
40
+ n.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
41
+ else
42
+ n.type_at :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
43
+ end
44
+ }
23
45
  n.title :path => 'title'
24
46
  n.subTitle :path => 'subTitle'
25
47
  n.nonSort :path => 'nonSort'
26
48
  n.partNumber :path => 'partNumber'
27
49
  n.partName :path => 'partName'
28
50
  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)
51
+ if node.type_at != "alternative" || (node.type_at == "alternative" && mods_ng_xml.xpath('/mods/titleInfo').size == 1)
30
52
  node.title.text + (!node.subTitle.text.empty? ? "#{@title_delimiter}#{node.subTitle.text}" : "" )
31
53
  end
32
54
  }
@@ -36,13 +58,13 @@ module Mods
36
58
  (!node.subTitle.text.empty? ? "#{@title_delimiter}#{node.subTitle.text}" : "" )
37
59
  }
38
60
  n.short_title :path => '.', :accessor => lambda { |node|
39
- if node.type_at.text != "alternative"
61
+ if node.type_at != "alternative"
40
62
  (!node.nonSort.text.empty? ? "#{node.nonSort.text} " : "" ) +
41
63
  node.title.text
42
64
  end
43
65
  }
44
66
  n.alternative_title :path => '.', :accessor => lambda { |node|
45
- if node.type_at.text == "alternative"
67
+ if node.type_at == "alternative"
46
68
  (!node.nonSort.text.empty? ? "#{node.nonSort.text} " : "" ) +
47
69
  node.title.text
48
70
  end
@@ -57,8 +79,9 @@ module Mods
57
79
 
58
80
 
59
81
  # NAME ------------------------------------------------------------------------------------
82
+ t.plain_name :path => '/mods/name'
60
83
 
61
- t.plain_name :path => '/mods/name' do |n|
84
+ t._plain_name :path => '//name' do |n|
62
85
 
63
86
  Mods::Name::ATTRIBUTES.each { |attr_name|
64
87
  if attr_name != 'type'
@@ -163,6 +186,77 @@ module Mods
163
186
  end
164
187
  end
165
188
 
189
+ # SUBJECT -----------------------------------------------------------------------------
190
+ t.subject :path => '/mods/subject' do |n|
191
+ Mods::AUTHORITY_ATTRIBS.each { |attr_name|
192
+ n.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
193
+ }
194
+ n.topic :path => 'topic' do |n|
195
+ Mods::AUTHORITY_ATTRIBS.each { |attr_name|
196
+ n.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
197
+ }
198
+ end
199
+ n.geographic :path => 'geographic' do |n|
200
+ Mods::AUTHORITY_ATTRIBS.each { |attr_name|
201
+ n.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
202
+ }
203
+ end
204
+ n.temporal :path => 'temporal' do |n|
205
+ n.encoding :path => 'encoding'
206
+ n.point :path => 'point'
207
+ n.keyDate :path => 'keyDate'
208
+ n.qualifier :path => 'qualifier'
209
+ Mods::AUTHORITY_ATTRIBS.each { |attr_name|
210
+ n.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
211
+ }
212
+ Mods::DATE_ATTRIBS.each { |attr_name|
213
+ n.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
214
+ }
215
+ end
216
+ n.titleInfo :path => 'titleInfo' do |t|
217
+ Mods::AUTHORITY_ATTRIBS.each { |attr_name|
218
+ t.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
219
+ }
220
+ end
221
+ # Note: 'name' is used by Nokogiri
222
+ n.name_ :path => 'name' do |t|
223
+ Mods::AUTHORITY_ATTRIBS.each { |attr_name|
224
+ t.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
225
+ }
226
+ end
227
+ n.geographicCode :path => 'geographicCode' do |g|
228
+ Mods::AUTHORITY_ATTRIBS.each { |attr_name|
229
+ g.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
230
+ }
231
+ end
232
+ n.genre :path => 'genre' do |n|
233
+ Mods::AUTHORITY_ATTRIBS.each { |attr_name|
234
+ n.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
235
+ }
236
+ end
237
+ n.hierarchicalGeographic :path => 'hierarchicalGeographic' do |n|
238
+ Mods::Subject::HIER_GEO_CHILD_ELEMENTS.each { |elname|
239
+ n.send elname, :path => "#{elname}"
240
+ }
241
+ Mods::AUTHORITY_ATTRIBS.each { |attr_name|
242
+ n.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
243
+ }
244
+ end
245
+ n.cartographics :path => 'cartographics' do |n|
246
+ n.scale :path => 'scale'
247
+ n.projection :path => 'projection'
248
+ n.coordinates :path => 'coordinates'
249
+ Mods::Subject::CARTOGRAPHICS_CHILD_ELEMENTS.each { |elname|
250
+ n.send elname, :path => "#{elname}"
251
+ }
252
+ end
253
+ n.occupation :path => 'occupation' do |n|
254
+ Mods::AUTHORITY_ATTRIBS.each { |attr_name|
255
+ n.send attr_name, :path => "@#{attr_name}", :accessor => lambda { |a| a.text }
256
+ }
257
+ end
258
+ end
259
+
166
260
  end # terminology
167
261
 
168
262
  mods_ng_xml.nom!
@@ -0,0 +1,18 @@
1
+ module Mods
2
+
3
+ class Subject
4
+
5
+ CHILD_ELEMENTS = ['topic', 'geographic', 'temporal', 'titleInfo', 'name', 'genre', 'hierarchicalGeographic', 'cartographics', 'geographicCode', 'occupation']
6
+
7
+ # attributes on subject node
8
+ ATTRIBUTES = Mods::LANG_ATTRIBS + Mods::LINKING_ATTRIBS + ['authority']
9
+
10
+ HIER_GEO_CHILD_ELEMENTS = ['continent', 'country', 'province', 'region', 'state', 'territory', 'county', 'city', 'citySection', 'island', 'area', 'extraterrestrialArea']
11
+
12
+ CARTOGRAPHICS_CHILD_ELEMENTS = ['coordinates', 'scale', 'projection']
13
+
14
+ GEO_CODE_AUTHORITIES = ['marcgac, marccountry, iso3166']
15
+
16
+ end
17
+
18
+ end
@@ -1,19 +1,19 @@
1
1
  module Mods
2
- # NAOMI_MUST_COMMENT_THIS_CLASS
2
+
3
3
  class TitleInfo
4
- # attr_reader :ng_node
5
4
 
6
- NS_HASH = {'m' => MODS_NS_V3}
7
- SUBELEMENTS = ['title', 'subTitle', 'partNumber', 'partName', 'nonSort']
5
+ CHILD_ELEMENTS = ['title', 'subTitle', 'partNumber', 'partName', 'nonSort']
8
6
 
9
7
  # attributes on titleInfo node
10
- ATTRIBUTES = ['type', 'authority', 'authorityURI', 'valueURI', 'displayLabel', 'supplied', 'usage', 'altRepGroup', 'nameTitleGroup']
8
+ ATTRIBUTES = Mods::AUTHORITY_ATTRIBS + ['type', 'displayLabel', 'supplied', 'usage', 'altRepGroup', 'nameTitleGroup']
11
9
 
12
10
  # valid values for type attribute on titleInfo node <titleInfo type="val">
13
11
  TYPES = ['abbreviated', 'translated', 'alternative', 'uniform']
14
12
 
15
13
  DEFAULT_TITLE_DELIM = ' '
16
14
 
15
+ # attr_reader :ng_node
16
+
17
17
  # @param (Nokogiri::XML::Node) mods:titleInfo node
18
18
  # def initialize(title_info_node)
19
19
  # @ng_node = title_info_node
@@ -1,4 +1,4 @@
1
1
  module Mods
2
2
  # this is the Ruby Gem version
3
- VERSION = "0.0.4"
3
+ VERSION = "0.0.5"
4
4
  end
@@ -27,7 +27,7 @@ describe "Mods <name> Element" do
27
27
  context "personal name" do
28
28
 
29
29
  it "should recognize child elements" do
30
- Mods::Name::SUBELEMENTS.reject{|e| e == "role"}.each { |e|
30
+ Mods::Name::CHILD_ELEMENTS.reject{|e| e == "role"}.each { |e|
31
31
  @mods_rec.from_str("<mods><name type='personal'><#{e}>oofda</#{e}></name></mods>")
32
32
  if e == 'description'
33
33
  @mods_rec.personal_name.description_el.text.should == 'oofda'
@@ -161,7 +161,7 @@ describe "Mods <name> Element" do
161
161
  end
162
162
 
163
163
  it "should recognize child elements" do
164
- Mods::Name::SUBELEMENTS.reject{|e| e == "role" }.each { |e|
164
+ Mods::Name::CHILD_ELEMENTS.reject{|e| e == "role" }.each { |e|
165
165
  @mods_rec.from_str("<mods><name type='corporate'><#{e}>oofda</#{e}></name></mods>")
166
166
  if e == 'description'
167
167
  @mods_rec.corporate_name.description_el.text.should == 'oofda'
@@ -204,7 +204,7 @@ describe "Mods <name> Element" do
204
204
  context "(plain) <name> element terminology pieces" do
205
205
 
206
206
  it "should recognize child elements" do
207
- Mods::Name::SUBELEMENTS.reject{|e| e == "role"}.each { |e|
207
+ Mods::Name::CHILD_ELEMENTS.reject{|e| e == "role"}.each { |e|
208
208
  @mods_rec.from_str("<mods><name><#{e}>oofda</#{e}></name></mods>")
209
209
  if e == 'description'
210
210
  @mods_rec.plain_name.description_el.text.should == 'oofda'
@@ -225,7 +225,7 @@ describe "Mods <name> Element" do
225
225
  }
226
226
  end
227
227
 
228
- context "namePart subelement" do
228
+ context "namePart child element" do
229
229
  it "should recognize type attribute on namePart element" do
230
230
  Mods::Name::NAME_PART_TYPES.each { |t|
231
231
  @mods_rec.from_str("<mods><name><namePart type='#{t}'>hi</namePart></name></mods>")
@@ -234,7 +234,7 @@ describe "Mods <name> Element" do
234
234
  end
235
235
  end
236
236
 
237
- context "role subelement" do
237
+ context "role child element" do
238
238
  it "should get role type" do
239
239
  @mods_rec.from_str(@mods_w_pers_name_role)
240
240
  @mods_rec.plain_name.role.type_at.should == ["text"]
@@ -0,0 +1,440 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Mods <subject> Element" do
4
+ before(:all) do
5
+ @mods_rec = Mods::Record.new
6
+ end
7
+
8
+ it "should do something intelligent with duplicate values" do
9
+ pending "to be implemented"
10
+ end
11
+
12
+ it "should do some date parsing of temporal element based on encoding" do
13
+ pending "to be implemented"
14
+ end
15
+
16
+ it "authority designation on the <subject> element should trickle down to child elements" do
17
+ pending "to be implemented"
18
+ end
19
+
20
+ it "should subject personal name dates should be cleaned up???" do
21
+ pending "to be implemented"
22
+ end
23
+
24
+ it "should translate the geographicCodes" do
25
+ pending "to be implemented"
26
+ end
27
+
28
+ context "names" do
29
+ before(:all) do
30
+ @both_types = @mods_rec.from_str('<mods><subject>
31
+ <name type="personal">
32
+ <namePart>Bridgens, R.P</namePart>
33
+ </name>
34
+ </subject><subject authority="lcsh">
35
+ <name type="corporate">
36
+ <namePart>Britton &amp; Rey.</namePart>
37
+ </name>
38
+ </subject></mods>').subject.name
39
+ @pers_name = @mods_rec.from_str('<mods><subject>
40
+ <name type="personal" authority="ingest">
41
+ <namePart type="family">Edward VI , king of England, </namePart>
42
+ <displayForm>Edward VI , king of England, 1537-1553</displayForm>
43
+ </name></subject></mods>').subject.name
44
+ @mult_pers_name = @mods_rec.from_str('<mods><subject authority="lcsh">
45
+ <name type="personal">
46
+ <namePart>Baker, George H</namePart>
47
+ <role>
48
+ <roleTerm type="text">lithographer.</roleTerm>
49
+ </role>
50
+ </name>
51
+ </subject><subject>
52
+ <name type="personal">
53
+ <namePart>Beach, Ghilion</namePart>
54
+ <role>
55
+ <roleTerm type="text">publisher.</roleTerm>
56
+ </role>
57
+ </name>
58
+ </subject><subject>
59
+ <name type="personal">
60
+ <namePart>Bridgens, R.P</namePart>
61
+ </name>
62
+ </subject><subject authority="lcsh">
63
+ <name type="personal">
64
+ <namePart>Couts, Cave Johnson</namePart>
65
+ <namePart type="date">1821-1874</namePart>
66
+ </name>
67
+ </subject><subject authority="lcsh">
68
+ <name type="personal">
69
+ <namePart>Kuchel, Charles Conrad</namePart>
70
+ <namePart type="date">b. 1820</namePart>
71
+ </name>
72
+ </subject><subject authority="lcsh">
73
+ <name type="personal">
74
+ <namePart>Nahl, Charles Christian</namePart>
75
+ <namePart type="date">1818-1878</namePart>
76
+ </name>
77
+ </subject><subject authority="lcsh">
78
+ <name type="personal">
79
+ <namePart>Swasey, W. F. (William F.)</namePart>
80
+ </name></subject></mods>').subject.name
81
+ @mult_corp_name = @mods_rec.from_str('<mods><subject authority="lcsh">
82
+ <name type="corporate">
83
+ <namePart>Britton &amp; Rey.</namePart>
84
+ </name>
85
+ </subject><subject>
86
+ <name type="corporate">
87
+ <namePart>Gray (W. Vallance) &amp; C.B. Gifford,</namePart>
88
+ <role>
89
+ <roleTerm type="text">lithographers.</roleTerm>
90
+ </role>
91
+ </name></subject></mods>').subject.name
92
+ end
93
+ it "should be able to identify corporate names" do
94
+ pending "to be implemented"
95
+ end
96
+ it "should be able to identify personal names" do
97
+ pending "to be implemented"
98
+ end
99
+ it "should be able to identify roles associated with a name" do
100
+ pending "to be implemented"
101
+ end
102
+ it "should be able to identify dates associated with a name" do
103
+ pending "to be implemented"
104
+ end
105
+ it "should do the appropriate thing with the role for the value of a name" do
106
+ pending "to be implemented"
107
+ end
108
+ it "should do the appropriate thing with the date for the value of a name" do
109
+ pending "to be implemented"
110
+ end
111
+ end
112
+
113
+ context "basic subject terminology pieces" do
114
+ before(:all) do
115
+ @four_subjects = @mods_rec.from_str('<mods><subject authority="lcsh">
116
+ <geographic>San Francisco (Calif.)</geographic>
117
+ <topic>History</topic>
118
+ <genre>Pictorial works</genre>
119
+ </subject>
120
+ <subject authority="lcsh">
121
+ <geographic>San Diego (Calif.)</geographic>
122
+ <topic>History</topic>
123
+ <genre>Pictorial works</genre>
124
+ </subject>
125
+ <subject authority="lcsh">
126
+ <topic>History</topic>
127
+ <genre>Pictorial works</genre>
128
+ </subject>
129
+ <subject authority="lcsh">
130
+ <geographic>San Luis Rey (Calif.)</geographic>
131
+ <genre>Pictorial works</genre>
132
+ </subject></mods>').subject
133
+ @geo_code_subject = @mods_rec.from_str('<mods><subject>
134
+ <geographicCode authority="marcgac">f------</geographicCode></subject></mods>').subject
135
+ @lcsh_subject = @mods_rec.from_str('<mods><subject authority="lcsh">
136
+ <geographic>Africa</geographic>
137
+ <genre>Maps</genre>
138
+ <temporal>500-1400</temporal></subject></mods>').subject
139
+ end
140
+
141
+ it "should be a NodeSet" do
142
+ @four_subjects.should be_an_instance_of(Nokogiri::XML::NodeSet)
143
+ @lcsh_subject.should be_an_instance_of(Nokogiri::XML::NodeSet)
144
+ end
145
+ it "should have as many members as there are <subject> elements in the xml" do
146
+ @four_subjects.size.should == 4
147
+ @lcsh_subject.size.should == 1
148
+ end
149
+ it "should recognize authority attribute on <subject> element" do
150
+ ['lcsh', 'ingest', 'lctgm'].each { |a|
151
+ @mods_rec.from_str("<mods><subject authority='#{a}'><topic>Ruler, English.</topic></subject></mods>").subject.authority.should == [a]
152
+ }
153
+ end
154
+
155
+ context "<topic> child element" do
156
+ before(:all) do
157
+ topic = '<mods><subject authority="lcsh"><topic>History</topic></subject></mods>'
158
+ @topic_simple = @mods_rec.from_str(topic).subject.topic
159
+ multi_topic = '<mods><subject>
160
+ <topic>California as an island--Maps--1662?</topic>
161
+ <topic>North America--Maps--To 1800</topic>
162
+ <topic>North America--Maps--1662?</topic>
163
+ </subject></mods>'
164
+ @multi_topic = @mods_rec.from_str(multi_topic).subject.topic
165
+ end
166
+ it "should be a NodeSet" do
167
+ @topic_simple.should be_an_instance_of(Nokogiri::XML::NodeSet)
168
+ @multi_topic.should be_an_instance_of(Nokogiri::XML::NodeSet)
169
+ end
170
+ it "topic NodeSet should have as many Nodes as there are <topic> elements in the xml" do
171
+ @topic_simple.size.should == 1
172
+ @multi_topic.size.should == 3
173
+ @four_subjects.topic.size.should == 3
174
+ @geo_code_subject.topic.size.should == 0
175
+ end
176
+ it "text should get element value" do
177
+ @topic_simple.text.should == "History"
178
+ @multi_topic.text.should include("California as an island--Maps--1662?")
179
+ @multi_topic.text.should include("North America--Maps--To 1800")
180
+ @multi_topic.text.should include("North America--Maps--1662?")
181
+ @four_subjects.topic.text.should include("History")
182
+ end
183
+ end # <topic>
184
+
185
+ context "<geographic> child element" do
186
+ it "should be a NodeSet" do
187
+ @four_subjects.geographic.should be_an_instance_of(Nokogiri::XML::NodeSet)
188
+ @lcsh_subject.geographic.should be_an_instance_of(Nokogiri::XML::NodeSet)
189
+ @geo_code_subject.geographic.should be_an_instance_of(Nokogiri::XML::NodeSet)
190
+ end
191
+ it "geographic NodeSet should have as many Nodes as there are <geographic> elements in the xml" do
192
+ @four_subjects.geographic.size.should == 3
193
+ @lcsh_subject.geographic.size.should == 1
194
+ @geo_code_subject.geographic.size.should == 0
195
+ end
196
+ it "text should get element value" do
197
+ @four_subjects.geographic.text.should include("San Francisco (Calif.)")
198
+ @four_subjects.geographic.text.should include("San Diego (Calif.)")
199
+ @four_subjects.geographic.text.should include("San Luis Rey (Calif.)")
200
+ end
201
+ it "should not include <geographicCode> element" do
202
+ @geo_code_subject.geographic.size.should == 0
203
+ end
204
+ end # <geographic>
205
+
206
+ context "<temporal> child element" do
207
+ before(:all) do
208
+ @temporal = @mods_rec.from_str('<mods><subject>
209
+ <temporal encoding="iso8601">20010203T040506+0700</temporal>
210
+ <!-- <temporal encoding="iso8601">197505</temporal> -->
211
+ </subject></mods>').subject.temporal
212
+ end
213
+
214
+ it "should recognize the date attributes" do
215
+ @temporal.encoding.should == ['iso8601']
216
+ Mods::DATE_ATTRIBS.each { |a|
217
+ @mods_rec.from_str("<mods><subject><temporal #{a}='val'>now</temporal></subject></mods>").subject.temporal.send(a.to_sym).should == ['val']
218
+ }
219
+ end
220
+ it "should be a NodeSet" do
221
+ @lcsh_subject.temporal.should be_an_instance_of(Nokogiri::XML::NodeSet)
222
+ @temporal.should be_an_instance_of(Nokogiri::XML::NodeSet)
223
+ end
224
+ it "temporal NodeSet should have as many Nodes as there are <temporal> elements in the xml" do
225
+ @lcsh_subject.temporal.size.should == 1
226
+ @temporal.size.should == 1
227
+ end
228
+ it "text should get element value" do
229
+ @lcsh_subject.temporal.map { |n| n.text }.should == ['500-1400']
230
+ @temporal.map { |n| n.text }.should == ['20010203T040506+0700']
231
+ end
232
+ end # <temporal>
233
+
234
+ context "<genre> child element" do
235
+ it "should be a NodeSet" do
236
+ @lcsh_subject.genre.should be_an_instance_of(Nokogiri::XML::NodeSet)
237
+ @four_subjects.genre.should be_an_instance_of(Nokogiri::XML::NodeSet)
238
+ end
239
+ it "genre NodeSet should have as many Nodes as there are <genre> elements in the xml" do
240
+ @lcsh_subject.genre.size.should == 1
241
+ @four_subjects.genre.size.should == 4
242
+ end
243
+ it "text should get element value" do
244
+ @lcsh_subject.genre.map { |n| n.text }.should == ['Maps']
245
+ @four_subjects.genre.map { |n| n.text }.should include("Pictorial works")
246
+ end
247
+ end # <genre>
248
+
249
+ context "<geographicCode> child element" do
250
+ it "should be a NodeSet" do
251
+ @geo_code_subject.geographicCode.should be_an_instance_of(Nokogiri::XML::NodeSet)
252
+ end
253
+ it "cartographics NodeSet should have as many Nodes as there are <geographicCode> elements in the xml" do
254
+ @geo_code_subject.geographicCode.size.should == 1
255
+ end
256
+ it "text should get element value" do
257
+ @geo_code_subject.geographicCode.map { |n| n.text }.should == ['f------']
258
+ end
259
+ it "should recognize authority attributes" do
260
+ Mods::AUTHORITY_ATTRIBS.each { |a|
261
+ @mods_rec.from_str("<mods><subject><geographicCode #{a}='attr_val'>f------</geographicCode></subject></mods>")
262
+ @mods_rec.subject.geographicCode.send(a.to_sym).should == ['attr_val']
263
+ }
264
+ end
265
+ it "should recognize the sanctioned authorities" do
266
+ Mods::Subject::GEO_CODE_AUTHORITIES.each { |a|
267
+ @mods_rec.from_str("<mods><subject><geographicCode authority='#{a}'>f------</geographicCode></subject></mods>")
268
+ @mods_rec.subject.geographicCode.authority.should == [a]
269
+ }
270
+ end
271
+ it "should not recognize unsanctioned authorities?" do
272
+ @mods_rec.from_str("<mods><subject><geographicCode authority='fake'>f------</geographicCode></subject></mods>")
273
+ pending "to be implemented"
274
+ expect { @mods_rec.subject.geographicCode.authority }.to raise_error(/no idea/)
275
+ end
276
+ end # <geographicCode>
277
+
278
+ context "<titleInfo> child element" do
279
+ before(:all) do
280
+ @title_info = @mods_rec.from_str('<mods><subject>
281
+ <titleInfo>
282
+ <nonSort>The</nonSort>
283
+ <title>Olympics</title>
284
+ <subTitle>a history</subTitle>
285
+ </titleInfo>
286
+ </subject></mods>').subject.titleInfo
287
+ end
288
+ it "should understand all attributes allowed on a <titleInfo> element" do
289
+ Mods::TitleInfo::ATTRIBUTES.each { |a|
290
+ ti = @mods_rec.from_str("<mods><subject><titleInfo #{a}='attr_val'>THE</titleInfo></subject></mods>").subject.titleInfo
291
+ if (a == 'type')
292
+ ti.type_at.should == ['attr_val']
293
+ else
294
+ ti.send(a.to_sym).should == ['attr_val']
295
+ end
296
+ }
297
+ end
298
+ it "should understand all immediate child elements allowed on a <titleInfo> element" do
299
+ Mods::TitleInfo::CHILD_ELEMENTS.each { |e|
300
+ @mods_rec.from_str("<mods><subject><titleInfo><#{e}>el_val</#{e}></titleInfo></subject></mods>").subject.titleInfo.send(e.to_sym).text.should == 'el_val'
301
+ }
302
+ @title_info.nonSort.map {|n| n.text}.should == ["The"]
303
+ end
304
+
305
+ it "should recognize authority attribute on the <titleInfo> element" do
306
+ @mods_rec.from_str('<mods><subject>
307
+ <titleInfo type="uniform" authority="naf">
308
+ <title>Missale Carnotense</title>
309
+ </titleInfo></subject></mods>').subject.titleInfo.authority.should == ["naf"]
310
+ end
311
+ end # <titleInfo>
312
+
313
+ context "<name> child element" do
314
+ it "should understand all attributes allowed on a <name> element" do
315
+ Mods::Name::ATTRIBUTES.each { |a|
316
+ name = @mods_rec.from_str("<mods><subject><name #{a}='attr_val'>Obadiah</name></subject></mods>").subject.name_
317
+ if (a == 'type')
318
+ name.type_at.should == ['attr_val']
319
+ else
320
+ name.send(a.to_sym).should == ['attr_val']
321
+ end
322
+ }
323
+ end
324
+ it "should understand all immediate child elements allowed on a <name> element" do
325
+ Mods::Name::CHILD_ELEMENTS.each { |e|
326
+ name = @mods_rec.from_str("<mods><subject><name><#{e}>el_val</#{e}></name></subject></mods>").subject.name_
327
+ if (e == 'description')
328
+ name.description_el.text.should == 'el_val'
329
+ elsif (e != 'role')
330
+ name.send(e.to_sym).text.should == 'el_val'
331
+ end
332
+ }
333
+ end
334
+ it "should recognize authority attribute on the <name> element" do
335
+ @mods_rec.from_str('<mods><subject>
336
+ <name type="personal" authority="lcsh">
337
+ <namePart>Nahl, Charles Christian</namePart>
338
+ <namePart type="date">1818-1878</namePart>
339
+ </name></mods>').subject.name_.authority.should == ["lcsh"]
340
+ end
341
+ end # <name>
342
+
343
+ context "<hiearchicalGeographic> child element" do
344
+ it "should recognize authority attributes" do
345
+ Mods::AUTHORITY_ATTRIBS.each { |a|
346
+ @mods_rec.from_str("<mods><subject><hierarchicalGeographic #{a}='attr_val'><country>Albania</country></hierarchicalGeographic></subject></mods>")
347
+ @mods_rec.subject.hierarchicalGeographic.send(a.to_sym).should == ['attr_val']
348
+ }
349
+ end
350
+ it "should recognize allowed child elements" do
351
+ Mods::Subject::HIER_GEO_CHILD_ELEMENTS.each { |e|
352
+ @mods_rec.from_str("<mods><subject><hierarchicalGeographic><#{e}>el_val</#{e}></hierarchicalGeographic></subject></mods>")
353
+ @mods_rec.subject.hierarchicalGeographic.send(e.to_sym).text.should == 'el_val'
354
+ }
355
+ Mods::Subject::HIER_GEO_CHILD_ELEMENTS.size.should == 12
356
+ end
357
+ end # <hierarchicalGeographic>
358
+
359
+ context "<cartographics> child element" do
360
+ before(:all) do
361
+ @carto_scale = @mods_rec.from_str('<mods><subject>
362
+ <cartographics>
363
+ <scale>[ca.1:90,000,000], [173</scale>
364
+ </cartographics>
365
+ </subject></mods>').subject.cartographics
366
+ @carto_empties = @mods_rec.from_str('<mods><subject authority="">
367
+ <cartographics>
368
+ <scale/>
369
+ <coordinates>W1730000 W0100000 N840000 N071000</coordinates>
370
+ <projection/>
371
+ </cartographics>
372
+ </subject></mods>').subject.cartographics
373
+ @multi_carto = @mods_rec.from_str('<mods><subject>
374
+ <cartographics>
375
+ <coordinates>W0180000 E0510000 N370000 S350000</coordinates>
376
+ </cartographics>
377
+ </subject><subject>
378
+ <cartographics>
379
+ <scale>Scale [ca. 1:50,000,000]</scale>
380
+ </cartographics>
381
+ <cartographics>
382
+ <coordinates>(W18&#xB0;--E51&#xB0;/N37&#xB0;--S35&#xB0;).</coordinates>
383
+ </cartographics>
384
+ </subject></mods>').subject.cartographics
385
+ end
386
+ it "should be a NodeSet" do
387
+ @carto_scale.should be_an_instance_of(Nokogiri::XML::NodeSet)
388
+ @carto_empties.should be_an_instance_of(Nokogiri::XML::NodeSet)
389
+ @multi_carto.should be_an_instance_of(Nokogiri::XML::NodeSet)
390
+ end
391
+ it "cartographics NodeSet should have as many Nodes as there are <cartographics> elements in the xml" do
392
+ @carto_scale.size.should == 1
393
+ @carto_empties.size.should == 1
394
+ @multi_carto.size.should == 3
395
+ end
396
+ it "should recognize allowed child elements" do
397
+ Mods::Subject::CARTOGRAPHICS_CHILD_ELEMENTS.each { |e|
398
+ @mods_rec.from_str("<mods><subject><cartographics><#{e}>el_val</#{e}></cartographics></subject></mods>")
399
+ @mods_rec.subject.cartographics.send(e.to_sym).text.should == 'el_val'
400
+ }
401
+ Mods::Subject::CARTOGRAPHICS_CHILD_ELEMENTS.size.should == 3
402
+ end
403
+ it "should get the number of populated <coordinates> elements for coordinates term" do
404
+ @multi_carto.coordinates.size == 2
405
+ end
406
+ it "should be able to get the value of populated elements" do
407
+ @carto_scale.scale.map { |n| n.text }.should == ['[ca.1:90,000,000], [173']
408
+ @carto_empties.coordinates.map { |n| n.text }.should == ['W1730000 W0100000 N840000 N071000']
409
+ end
410
+ it "should get the empty string for empty elements?" do
411
+ @carto_empties.projection.map { |n| n.text }.should == ['']
412
+ end
413
+ end # <cartographics>
414
+
415
+ context "<occupation> child element" do
416
+ before(:all) do
417
+ @occupation = @mods_rec.from_str('<mods><subject><occupation>Migrant laborers</occupation></mods>').subject.occupation
418
+ end
419
+ it "should be a NodeSet" do
420
+ @occupation.should be_an_instance_of(Nokogiri::XML::NodeSet)
421
+ end
422
+ it "occupation NodeSet should have as many Nodes as there are <occupation> elements in the xml" do
423
+ @occupation.size.should == 1
424
+ end
425
+ it "text should get element value" do
426
+ @occupation.map { |n| n.text }.should == ['Migrant laborers']
427
+ end
428
+ it "should recognize authority attributes" do
429
+ Mods::AUTHORITY_ATTRIBS.each { |a|
430
+ @mods_rec.from_str("<mods><subject><occupation #{a}='attr_val'>Flunkie</occupation></subject></mods>")
431
+ @mods_rec.subject.occupation.send(a.to_sym).should == ['attr_val']
432
+ }
433
+ end
434
+
435
+ end # <occupation>
436
+
437
+
438
+ end # basic subject terminology
439
+
440
+ end
@@ -9,12 +9,12 @@ describe "Mods <titleInfo> element" do
9
9
  it "should recognize type attribute on titleInfo element" do
10
10
  Mods::TitleInfo::TYPES.each { |t|
11
11
  @mods_rec.from_str("<mods><titleInfo type='#{t}'>hi</titleInfo></mods>")
12
- @mods_rec.title_info.type_at.text.should == t
12
+ @mods_rec.title_info.type_at.should == [t]
13
13
  }
14
14
  end
15
15
 
16
16
  it "should recognize subelements" do
17
- Mods::TitleInfo::SUBELEMENTS.each { |e|
17
+ Mods::TitleInfo::CHILD_ELEMENTS.each { |e|
18
18
  @mods_rec.from_str("<mods><titleInfo><#{e}>oofda</#{e}></titleInfo></mods>")
19
19
  @mods_rec.title_info.send(e).text.should == 'oofda'
20
20
  }
@@ -29,4 +29,11 @@ describe "Mods Top Level Elements that do not have Child Elements" do
29
29
  pending "need to implement ruby style version of (element/attribute) method names"
30
30
  end
31
31
 
32
+ it "<genre> element should recognize authority attributes" do
33
+ pending "to be implemented"
34
+ Mods::AUTHORITY_ATTRIBS.each { |a|
35
+ @mods_rec.from_str("<mods><genre #{a}='attr_val'>Graphic Novels</genre></mods>").genre.send(a.to_sym).should == 'attr_val'
36
+ }
37
+ end
38
+
32
39
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mods
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-11-08 00:00:00.000000000 Z
13
+ date: 2012-11-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: nokogiri
@@ -182,6 +182,7 @@ files:
182
182
  - lib/mods/nom_terminology.rb
183
183
  - lib/mods/reader.rb
184
184
  - lib/mods/record.rb
185
+ - lib/mods/subject.rb
185
186
  - lib/mods/title_info.rb
186
187
  - lib/mods/version.rb
187
188
  - mods.gemspec
@@ -192,6 +193,7 @@ files:
192
193
  - spec/physical_description_spec.rb
193
194
  - spec/reader_spec.rb
194
195
  - spec/spec_helper.rb
196
+ - spec/subject_spec.rb
195
197
  - spec/title_spec.rb
196
198
  - spec/top_level_elmnts_simple_spec.rb
197
199
  homepage: https://github.com/sul-dlss/mods
@@ -208,7 +210,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
208
210
  version: '0'
209
211
  segments:
210
212
  - 0
211
- hash: 1304587137062887266
213
+ hash: -2903168770934676746
212
214
  required_rubygems_version: !ruby/object:Gem::Requirement
213
215
  none: false
214
216
  requirements:
@@ -217,7 +219,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
217
219
  version: '0'
218
220
  segments:
219
221
  - 0
220
- hash: 1304587137062887266
222
+ hash: -2903168770934676746
221
223
  requirements: []
222
224
  rubyforge_project:
223
225
  rubygems_version: 1.8.24
@@ -232,6 +234,7 @@ test_files:
232
234
  - spec/physical_description_spec.rb
233
235
  - spec/reader_spec.rb
234
236
  - spec/spec_helper.rb
237
+ - spec/subject_spec.rb
235
238
  - spec/title_spec.rb
236
239
  - spec/top_level_elmnts_simple_spec.rb
237
240
  has_rdoc: