mods 0.0.4 → 0.0.5

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.
@@ -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: