mods 0.0.23 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NDEwMWE1MTQ2NzZiZWY5N2U4NDg0MDAyZjdlZDVhYmQ1M2I2ZWVmZA==
5
- data.tar.gz: !binary |-
6
- YTc1MTZhZjg2MWI1MmVhNmJlYjdmODU0N2M5OTg3MDNmM2I4ZTZhMA==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- ZjE1N2RmMmI3YTZkYWU1ZTU4ZDg4MWM3MzUzMDQ4N2RiZjEzNDAzNDE2NmFm
10
- ZWFlZDllMTcyNWU0MzlkM2FjNjE1YmM3ODllYTlkMDMyMzg0MjI2OWY2N2My
11
- YzVjODkwMDJiNDExOGJhMTZjODBiYzc5YzFmOWY2MGNhZDU5ODc=
12
- data.tar.gz: !binary |-
13
- ZWNkYjNkZTQxMmZjNzI4NDhhODFmNGNmMjMxOGFjOTc1MjNiYTIyNGYyOThj
14
- MmE0NTNmOTEwNWU4YjY1MzIzNTEyZWU5MGNkMTkzODU5NDg3MjYyNDUwNjYz
15
- Mzc5YmZkZjI0YWMwMjVkZDA2OGVkNTUzYjVhNTA1NTU1OTExNGQ=
2
+ SHA1:
3
+ metadata.gz: 4fe75882ef2b666a42f3ad2ed28beb3535c19145
4
+ data.tar.gz: 7c772c0a8ac2336a7590399dc4f8811bc58d8df7
5
+ SHA512:
6
+ metadata.gz: d72061a466439b824e8a003656cb115b9f8be14a531efa0b9cf9f67e4fbd195058ddc25ec6c9f5ccb5950038b86165ab5783c7d9e05affc14d89256aa0daff48
7
+ data.tar.gz: 594347b7fbd0608009614bfe0a546ab7ec28a14bb98a2e8bec7d8f1d56d9a84fe6f6416862175bfe6a1f9ff6092bc47b24e65a67574873776ab36cce9e3e7e45
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.travis.yml CHANGED
@@ -1,11 +1,18 @@
1
1
  language: ruby
2
2
  script: rake rspec
3
3
  rvm:
4
+ - 2.2.0
5
+ - 2.1.5
6
+ - 2.1.1
7
+ - 2.0.0
4
8
  - 1.9.3
5
- - 1.9.2
6
- - jruby-19mode
9
+ - ruby-head
10
+ - jruby-1.7.9-d19 # fails after 1.7.10 for some reason
11
+ # - jruby-19mode # JRuby in 1.9 mode
12
+ # - jruby-head
7
13
  notifications:
8
14
  email:
9
15
  - ndushay@stanford.edu
16
+ - laneymcg@stanford.edu
10
17
  - jkeck@stanford.edu
11
18
  - bess@stanford.edu
data/Gemfile CHANGED
@@ -2,3 +2,7 @@ source 'https://rubygems.org'
2
2
 
3
3
  # See mods.gemspec for this gem's dependencies
4
4
  gemspec
5
+
6
+ group :test do
7
+ gem 'coveralls', require: false
8
+ end
data/README.rdoc CHANGED
@@ -1,7 +1,6 @@
1
1
  = Mods
2
2
 
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
- {<img src="https://gemnasium.com/sul-dlss/mods.png" alt="Dependency Status" />}[https://gemnasium.com/sul-dlss/mods]
3
+ {<img src="https://secure.travis-ci.org/sul-dlss/mods.png?branch=master" alt="Build Status" />}[http://travis-ci.org/sul-dlss/mods] {<img src="https://coveralls.io/repos/sul-dlss/mods/badge.png" alt="Coverage Status" />}[https://coveralls.io/r/sul-dlss/mods] {<img src="https://gemnasium.com/sul-dlss/mods.png" alt="Dependency Status" />}[https://gemnasium.com/sul-dlss/mods] {<img src="https://badge.fury.io/rb/mods.svg" alt="Gem Version" />}[http://badge.fury.io/rb/mods]
5
4
 
6
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.
7
6
 
@@ -25,7 +24,13 @@ Or install it yourself as:
25
24
 
26
25
  == Usage
27
26
 
28
- TODO: Write usage instructions here
27
+ Create a new Mods::Record from a url:
28
+
29
+ foo = Mods::Record.new.from_url('http://purl.stanford.edu/bb340tm8592.mods')
30
+
31
+ Create a new Mods::Record from a file:
32
+
33
+ foo = Mods::Record.new.from_file('/path/to/mods/file.xml')
29
34
 
30
35
  == Contributing
31
36
 
data/lib/mods/reader.rb CHANGED
@@ -2,18 +2,18 @@
2
2
 
3
3
  module Mods
4
4
  class Reader
5
-
5
+
6
6
  DEFAULT_NS_AWARE = true
7
7
 
8
- # true if the XML parsing should be strict about using namespaces.
8
+ # true if the XML parsing should be strict about using namespaces.
9
9
  attr_accessor :namespace_aware
10
10
  attr_reader :mods_ng_xml
11
-
11
+
12
12
  # @param ns_aware true if the XML parsing should be strict about using namespaces. Default is true
13
13
  def initialize(ns_aware = DEFAULT_NS_AWARE)
14
14
  @namespace_aware = ns_aware
15
15
  end
16
-
16
+
17
17
  # @param str - a string containing mods xml
18
18
  # @return Nokogiri::XML::Document
19
19
  def from_str(str)
@@ -21,16 +21,32 @@ module Mods
21
21
  normalize_mods
22
22
  @mods_ng_xml
23
23
  end
24
-
24
+
25
+ # Read in the contents of a Mods file from a url.
25
26
  # @param url (String) - url that has mods xml as its content
26
27
  # @return Nokogiri::XML::Document
28
+ # @example
29
+ # foo = Mods::Reader.new.from_url('http://purl.stanford.edu/bb340tm8592.mods')
27
30
  def from_url(url, encoding = nil, options = Nokogiri::XML::ParseOptions::DEFAULT_XML)
28
31
  require 'open-uri'
29
32
  @mods_ng_xml = Nokogiri::XML(open(url).read)
30
33
  normalize_mods
31
34
  @mods_ng_xml
32
35
  end
33
-
36
+
37
+ # Read in the contents of a Mods record from a file.
38
+ # @param filename (String) - path to file that has mods xml as its content
39
+ # @return Nokogiri::XML::Document
40
+ # @example
41
+ # foo = Mods::Reader.new.from_file('/path/to/mods/file.xml')
42
+ def from_file(filename, encoding = nil, options = Nokogiri::XML::ParseOptions::DEFAULT_XML)
43
+ file = File.open(filename)
44
+ @mods_ng_xml = Nokogiri::XML(file)
45
+ file.close
46
+ normalize_mods
47
+ @mods_ng_xml
48
+ end
49
+
34
50
  # @param node (Nokogiri::XML::Node) - Nokogiri::XML::Node that is the top level element of a mods record
35
51
  # @return Nokogiri::XML::Document
36
52
  def from_nk_node(node)
@@ -38,7 +54,7 @@ module Mods
38
54
  normalize_mods
39
55
  @mods_ng_xml
40
56
  end
41
-
57
+
42
58
  # Whatever we get, normalize it into a Nokogiri::XML::Document,
43
59
  def normalize_mods
44
60
  if !@namespace_aware
@@ -53,6 +69,6 @@ module Mods
53
69
  @mods_ng_xml = Nokogiri::XML(@mods_ng_xml.to_s, nil, @mods_ng_xml.encoding)
54
70
  end
55
71
  end
56
-
57
- end # class
58
- end # module
72
+
73
+ end # class
74
+ end # module
data/lib/mods/record.rb CHANGED
@@ -5,16 +5,16 @@ module Mods
5
5
  class Record
6
6
 
7
7
  attr_reader :mods_ng_xml
8
- # string to use when combining a title and subtitle, e.g.
8
+ # string to use when combining a title and subtitle, e.g.
9
9
  # for title "MODS" and subtitle "Metadata Odious Delimited Stuff" and delimiter " : "
10
10
  # we get "MODS : Metadata Odious Delimited Stuff"
11
11
  attr_accessor :title_delimiter
12
12
 
13
13
  NS_HASH = {'m' => MODS_NS_V3}
14
-
14
+
15
15
  ATTRIBUTES = ['id', 'version']
16
16
 
17
- # @param (String) title_delimiter what to use when combining a title and subtitle, e.g.
17
+ # @param (String) title_delimiter what to use when combining a title and subtitle, e.g.
18
18
  # for title "MODS" and subtitle "Metadata Odious Delimited Stuff" and delimiter " : "
19
19
  # we get "MODS : Metadata Odious Delimited Stuff"
20
20
  def initialize(title_delimiter = Mods::TitleInfo::DEFAULT_TITLE_DELIM)
@@ -33,9 +33,13 @@ module Mods
33
33
  end
34
34
  end
35
35
 
36
- # convenience method to call Mods::Reader.new.from_url and to nom
37
- # @param namespace_aware true if the XML parsing should be strict about using namespaces. Default is true
36
+ # Convenience method to call Mods::Reader.new.from_url and to nom.
37
+ # Returns a new instance of Mods::Record instantiated with the content from the given URL.
38
38
  # @param url (String) - url that has mods xml as its content
39
+ # @param namespace_aware true if the XML parsing should be strict about using namespaces. Default is true
40
+ # @return Mods::Record
41
+ # @example
42
+ # foo = Mods::Record.new.from_url('http://purl.stanford.edu/bb340tm8592.mods')
39
43
  def from_url(url, ns_aware = true)
40
44
  @mods_ng_xml = Mods::Reader.new(ns_aware).from_url(url)
41
45
  if ns_aware
@@ -43,6 +47,24 @@ module Mods
43
47
  else
44
48
  set_terminology_no_ns(@mods_ng_xml)
45
49
  end
50
+ return self
51
+ end
52
+
53
+ # Convenience method to call Mods::Reader.new.from_file.
54
+ # Returns a new instance of Mods::Record instantiated with the content from the given file.
55
+ # @param file (String) - path to file that has mods xml as its content
56
+ # @param namespace_aware true if the XML parsing should be strict about using namespaces. Default is true
57
+ # @return Mods::Record
58
+ # @example
59
+ # foo = Mods::Record.new.from_file('/path/to/file/bb340tm8592.mods')
60
+ def from_file(url, ns_aware = true)
61
+ @mods_ng_xml = Mods::Reader.new(ns_aware).from_file(url)
62
+ if ns_aware
63
+ set_terminology_ns(@mods_ng_xml)
64
+ else
65
+ set_terminology_no_ns(@mods_ng_xml)
66
+ end
67
+ return self
46
68
  end
47
69
 
48
70
  # convenience method to call Mods::Reader.new.from_nk_node and to nom
@@ -56,11 +78,11 @@ module Mods
56
78
  set_terminology_no_ns(@mods_ng_xml)
57
79
  end
58
80
  end
59
-
60
- # get the value for the terms, as a String. f there are multiple values, they will be joined with the separator.
81
+
82
+ # get the value for the terms, as a String. f there are multiple values, they will be joined with the separator.
61
83
  # If there are no values, the result will be nil.
62
84
  # @param [Symbol or String or Array<Symbol>] messages the single symbol of the message to send to the Stanford::Mods::Record object
63
- # (as a Symbol or a String), or an Array of (Symbols or Strings) to be sent as messages.
85
+ # (as a Symbol or a String), or an Array of (Symbols or Strings) to be sent as messages.
64
86
  # Messages will usually be terms from the nom-xml terminology defined in the mods gem.)
65
87
  # @param [String] sep - the separator string to insert between multiple values
66
88
  # @return [String] a String representing the value(s) or nil.
@@ -72,7 +94,7 @@ module Mods
72
94
 
73
95
  # get the values for the terms, as an Array. If there are no values, the result will be nil.
74
96
  # @param [Symbol or String or Array<Symbol>] messages the single symbol of the message to send to the Stanford::Mods::Record object
75
- # (as a Symbol or a String), or an Array of (Symbols or Strings) to be sent as messages.
97
+ # (as a Symbol or a String), or an Array of (Symbols or Strings) to be sent as messages.
76
98
  # Messages will usually be terms from the nom-xml terminology defined in the mods gem.)
77
99
  # @return [Array<String>] an Array with a String value for each result node's non-empty text, or nil if none
78
100
  def term_values messages
@@ -99,7 +121,7 @@ module Mods
99
121
 
100
122
  vals = []
101
123
  if nodes
102
- nodes.each { |n|
124
+ nodes.each { |n|
103
125
  vals << n.text unless n.text.empty?
104
126
  }
105
127
  end
@@ -108,7 +130,7 @@ module Mods
108
130
  rescue NoMethodError
109
131
  raise ArgumentError, "term_values called with unknown argument: #{messages.inspect}", caller
110
132
  end
111
-
133
+
112
134
 
113
135
  # @return Array of Strings, each containing the text contents of <mods><titleInfo> <nonSort> + ' ' + <title> elements
114
136
  # but not including any titleInfo elements with type="alternative"
@@ -120,17 +142,17 @@ module Mods
120
142
  def full_titles
121
143
  @mods_ng_xml.title_info.full_title.map { |n| n }
122
144
  end
123
-
145
+
124
146
  # @return Array of Strings, each containing the text contents of <mods><titleInfo @type="alternative"><title> elements
125
147
  def alternative_titles
126
148
  @mods_ng_xml.title_info.alternative_title.map { |n| n }
127
149
  end
128
-
150
+
129
151
  # @return String containing sortable title for this mods record
130
152
  def sort_title
131
153
  @mods_ng_xml.title_info.sort_title.find { |n| !n.nil? }
132
154
  end
133
-
155
+
134
156
  # @return Array of Strings, each containing the computed display value of a personal name
135
157
  # (see nom_terminology for algorithm)
136
158
  def personal_names
@@ -149,17 +171,17 @@ module Mods
149
171
  def corporate_names
150
172
  @mods_ng_xml.corporate_name.map { |n| n.display_value }
151
173
  end
152
-
174
+
153
175
  # Translates iso-639 language codes, and leaves everything else alone.
154
176
  # @return Array of Strings, each a (hopefully English) name of a language
155
177
  def languages
156
178
  result = []
157
- @mods_ng_xml.language.each { |n|
179
+ @mods_ng_xml.language.each { |n|
158
180
  # get languageTerm codes and add their translations to the result
159
- n.code_term.each { |ct|
181
+ n.code_term.each { |ct|
160
182
  if ct.authority.match(/^iso639/)
161
183
  begin
162
- vals = ct.text.split(/[,|\ ]/).reject {|x| x.strip.length == 0 }
184
+ vals = ct.text.split(/[,|\ ]/).reject {|x| x.strip.length == 0 }
163
185
  vals.each do |v|
164
186
  result << ISO_639.find(v.strip).english_name
165
187
  end
@@ -172,11 +194,11 @@ module Mods
172
194
  end
173
195
  }
174
196
  # add languageTerm text values
175
- n.text_term.each { |tt|
197
+ n.text_term.each { |tt|
176
198
  val = tt.text.strip
177
199
  result << val if val.length > 0
178
200
  }
179
-
201
+
180
202
  # add language values that aren't in languageTerm subelement
181
203
  if n.languageTerm.size == 0
182
204
  result << n.text
@@ -192,7 +214,7 @@ module Mods
192
214
  super.method_missing(method_name, *args)
193
215
  end
194
216
  end
195
-
217
+
196
218
  end # class Record
197
219
 
198
220
  end # module Mods
data/lib/mods/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Mods
2
2
  # this is the Ruby Gem version
3
- VERSION = "0.0.23"
3
+ VERSION = "1.0.0"
4
4
  end
data/mods.gemspec CHANGED
@@ -31,9 +31,8 @@ Gem::Specification.new do |gem|
31
31
  gem.add_development_dependency "rdoc"
32
32
  gem.add_development_dependency "yard"
33
33
  # tests
34
- gem.add_development_dependency 'rspec'
35
- gem.add_development_dependency 'simplecov'
36
- gem.add_development_dependency 'simplecov-rcov'
34
+ gem.add_development_dependency 'rspec', '~> 3.0'
35
+ # using coveralls with travis
37
36
  # gem.add_development_dependency 'ruby-debug19'
38
37
  gem.add_development_dependency 'equivalent-xml'
39
38
  end
@@ -0,0 +1,43 @@
1
+ <!--
2
+ Sample record from the Stanford Historical Photo Collection, house in the Stanford Digital Repository.
3
+ Also available at http://purl.stanford.edu/bb340tm8592.mods
4
+ -->
5
+ <mods xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.loc.gov/mods/v3" version="3.4" xsi:schemaLocation="http://www.loc.gov/mods/v3 http://www.loc.gov/standards/mods/v3/mods-3-4.xsd">
6
+ <titleInfo>
7
+ <title>Arboretum, road with oaks</title>
8
+ </titleInfo>
9
+ <name type="corporate" authority="naf" authorityURI="http://id.loc.gov/authorities/names/no98095678">
10
+ <namePart>PAHA (Palo Alto Historical Association</namePart>
11
+ <role>
12
+ <roleTerm type="text">donor</roleTerm>
13
+ </role>
14
+ </name>
15
+ <physicalDescription>
16
+ <form>black and white photographic print</form>
17
+ <internetMediaType>image/tiff</internetMediaType>
18
+ <note displayLabel="Dimensions">11 in. x 7 in.</note>
19
+ </physicalDescription>
20
+ <typeOfResource>still image</typeOfResource>
21
+ <language>
22
+ <languageTerm type="code" authority="iso639-2b">en</languageTerm>
23
+ </language>
24
+ <genre authority="ftamc">Photoprints.</genre>
25
+ <subject>
26
+ <topic>Arboretum</topic>
27
+ <topic>Trees</topic>
28
+ </subject>
29
+ <location>
30
+ <physicalLocation type="repository">Stanford University. Libraries. Dept. of Special Collections &amp; University Archives.</physicalLocation>
31
+ </location>
32
+ <identifier type="local" displayLabel="University Archives Photo ID">94</identifier>
33
+ <identifier type="local" displayLabel="Luna Object ID">1613</identifier>
34
+ <note>"PAHA 8/13/57" written on back.</note>
35
+ <relatedItem type="host">
36
+ <titleInfo>
37
+ <title>Stanford historical photograph collection, 1887-circa 1996</title>
38
+ </titleInfo>
39
+ <identifier type="uri">http://purl.stanford.edu/kx532cb7981</identifier>
40
+ <typeOfResource collection="yes"/>
41
+ </relatedItem>
42
+ <accessCondition type="useAndReproduction">Property rights reside with the repository. Literary rights reside with the creators of the documents or their heirs. To obtain permission to publish or reproduce, please contact the Special Collections Public Services Librarian at speccollref@stanford.edu.</accessCondition>
43
+ </mods>
@@ -146,62 +146,62 @@ describe "Mods <originInfo> Element" do
146
146
  <issuance>monographic</issuance>
147
147
  </originInfo>
148
148
  </mods>"
149
-
149
+
150
150
  xml = "<originInfo>
151
151
  <dateCreated encoding='w3cdtf' keyDate='yes' point='start' qualifier='approximate'>250 B.C.</dateCreated>
152
152
  <dateCreated encoding='w3cdtf' keyDate='yes' point='end' qualifier='approximate'>150 B.C.</dateCreated>
153
153
  </originInfo>"
154
-
154
+
155
155
  end
156
156
 
157
157
  context "parsing date values" do
158
158
  it "should cope with slop" do
159
- pending "to be implemented"
159
+ skip "to be implemented"
160
160
  end
161
161
  it "should know something about various date encodings: w3cdtf, iso8601, marc, edtf, temper" do
162
- pending "to be implemented"
162
+ skip "to be implemented"
163
163
  end
164
164
  it "should know the only valid values for point attribute are 'start' and 'end'" do
165
- pending "to be implemented"
165
+ skip "to be implemented"
166
166
  end
167
167
  it "should know the only valid value for keyDate attribute is 'yes" do
168
- pending "to be implemented"
168
+ skip "to be implemented"
169
169
  end
170
170
  it "should know the only valid values for qualifier attribute: approximate, inferred, questionable" do
171
- pending "to be implemented"
171
+ skip "to be implemented"
172
172
  end
173
173
  end
174
-
174
+
175
175
  context "parsing issuance" do
176
176
  it "should know the only valid values are: continuing, monographic, single unit, multipart monograph, serial, integrating resource" do
177
- pending "to be implemented"
177
+ skip "to be implemented"
178
178
  end
179
179
  end
180
-
180
+
181
181
  context "parsing publisher" do
182
182
  it "should ignore s.n. value (from MARC)" do
183
- pending "to be implemented"
183
+ skip "to be implemented"
184
184
  end
185
185
  it "should leave square brackets alone, except for s.n." do
186
- pending "to be implemented"
186
+ skip "to be implemented"
187
187
  end
188
188
  end
189
-
189
+
190
190
  context "parsing placeTerm" do
191
191
  it "should be able to translate marccountry codes" do
192
- pending "to be implemented"
192
+ skip "to be implemented"
193
193
  end
194
194
  it "should ignore s.l. value (from MARC)" do
195
- pending "to be implemented"
195
+ skip "to be implemented"
196
196
  end
197
197
  it "should be forgiving of square brackets (from MARC), matched or unmatched" do
198
- pending "to be implemented"
198
+ skip "to be implemented"
199
199
  end
200
200
  end
201
201
 
202
202
 
203
203
  context "basic <originInfo> terminology pieces" do
204
-
204
+
205
205
  context "WITH namespaces" do
206
206
  context "<place> child element" do
207
207
  before(:all) do
@@ -430,4 +430,4 @@ describe "Mods <originInfo> Element" do
430
430
 
431
431
  end # basic terminology
432
432
 
433
- end
433
+ end