relaton-nist 2.0.0.pre.alpha.2 → 2.0.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0e1709e47734509d547b5a112f57b77ff68df5dec8b3f4c62350346faa5c411c
4
- data.tar.gz: 90d49b0829c2eaddca800b28fb2f82220d03b1c55935c2f80033511dc8d31dd9
3
+ metadata.gz: 44c34385848a8014460e7001487ae66c504889a55d4d43e7825436af1ed8b447
4
+ data.tar.gz: 5a8484fe85b73b539de8d247193359a0004586644163dea56c7d31aa67c15afd
5
5
  SHA512:
6
- metadata.gz: 9c0746c5faad3ff3742a92ec4cfad1f24f161f6908a3ae732653fe97384b32110016b95accbcb3af66aba7960f577bfec4fb8c0f4e63c6522f546fb0caec336a
7
- data.tar.gz: 2c638a164a26ccd2e3aba38dab34ee2aa2f178e7427dbc2eb8d755077f16a7e0bc95787da9a2aaf063c48d2c2636aed099dd99d1dff4e295d0242218a2443767
6
+ metadata.gz: 53e6e72ccf31a11324e4258bef3a0239820af979ecf415f366936f4c7a15cb1564d3a26dd91812bccba3b87c9163b2ce6e76f6a83342a1d017b48c0be4a6989d
7
+ data.tar.gz: a2c5b41f673d8c6efd526d57f5c12b79d9e2c36db3609bbdf9d4059baea2dd183914d5ea873d2524bed998e41837b605b51919e4f5bfeed3e4d2e93c37ced2aa
@@ -7,6 +7,7 @@ on:
7
7
  branches: [ master, main ]
8
8
  tags: [ v* ]
9
9
  pull_request:
10
+ workflow_dispatch:
10
11
 
11
12
  jobs:
12
13
  rake:
@@ -187,6 +187,15 @@ Applicable to modify and delete</a:documentation>
187
187
  <a:documentation>Optional caption of this block</a:documentation>
188
188
  </attribute>
189
189
  </optional>
190
+ <optional>
191
+ <attribute name="position">
192
+ <a:documentation>For an "add" change, whether the change is added before or after the location</a:documentation>
193
+ <choice>
194
+ <value>before</value>
195
+ <value>after</value>
196
+ </choice>
197
+ </attribute>
198
+ </optional>
190
199
  <optional>
191
200
  <element name="location">
192
201
  <a:documentation>The location(s) in the original document which have undergone the change described in this block</a:documentation>
@@ -208,11 +217,15 @@ Applicable to modify and delete</a:documentation>
208
217
  </zeroOrMore>
209
218
  <optional>
210
219
  <element name="newcontent">
211
- <a:documentation>New content to be added to the document; applicable to add and modify</a:documentation>
220
+ <a:documentation>New content to be added to the document; applicable to add and modify.
221
+ Can be blocks and/or sections</a:documentation>
212
222
  <ref name="OptionalId"/>
213
223
  <zeroOrMore>
214
224
  <ref name="BasicBlock"/>
215
225
  </zeroOrMore>
226
+ <zeroOrMore>
227
+ <ref name="section"/>
228
+ </zeroOrMore>
216
229
  </element>
217
230
  </optional>
218
231
  <zeroOrMore>
data/grammars/biblio.rng CHANGED
@@ -1142,11 +1142,11 @@ NOTE: This should preferably be encoded as a URI or short identifier, rather th
1142
1142
  <a:documentation>Information about how long the current description of the bibliographic item is valid for</a:documentation>
1143
1143
  </ref>
1144
1144
  </optional>
1145
- <optional>
1145
+ <zeroOrMore>
1146
1146
  <ref name="depiction">
1147
1147
  <a:documentation>Depiction of the bibliographic item, typically an image</a:documentation>
1148
1148
  </ref>
1149
- </optional>
1149
+ </zeroOrMore>
1150
1150
  </define>
1151
1151
  <define name="ReducedBibliographicItem">
1152
1152
  <a:documentation>Reduced description of a bibliographic resource, without mandatory title and docidentifier, used for document relations
@@ -1939,10 +1939,10 @@ Detailed in https://www.relaton.org/model/relations/</a:documentation>
1939
1939
  <value>hasAnnotation</value>
1940
1940
  <value>draftOf</value>
1941
1941
  <value>hasDraft</value>
1942
- <value>preliminaryDraftOf</value>
1943
- <value>hasPreliminaryDraft</value>
1944
- <value>revisionDraftOf</value>
1945
- <value>hasRevisionDraft</value>
1942
+ <value>predecessorDraftOf</value>
1943
+ <value>hasPredecessorDraft</value>
1944
+ <value>successorDraftOf</value>
1945
+ <value>hasSuccessorDraft</value>
1946
1946
  <value>editionOf</value>
1947
1947
  <value>hasEdition</value>
1948
1948
  <value>updates</value>
@@ -2063,13 +2063,13 @@ provided that it is not the entire bibliographic item that is so related</a:docu
2063
2063
  <ref name="LocalizedString"/>
2064
2064
  </element>
2065
2065
  </optional>
2066
- <oneOrMore>
2066
+ <zeroOrMore>
2067
2067
  <element name="taxon">
2068
2068
  <a:documentation>The keywords as a hierarchical taxonomy. For example, the sequence of `taxon` elements
2069
2069
  `pump`, `centrifugal pump`, `line shaft pump` represents a taxonomic classification</a:documentation>
2070
2070
  <ref name="LocalizedString"/>
2071
2071
  </element>
2072
- </oneOrMore>
2072
+ </zeroOrMore>
2073
2073
  <zeroOrMore>
2074
2074
  <ref name="vocabid">
2075
2075
  <a:documentation>Identifiers for the keyword as a controlled vocabulary</a:documentation>
@@ -16,12 +16,13 @@ module Relaton
16
16
  fetch_tech_pubs
17
17
  # add_static_files
18
18
  index.save
19
+ report_errors
19
20
  end
20
21
 
21
22
  def fetch_tech_pubs
22
23
  xml_data = Mechanize.new.get(URL).body
23
24
  docs = LocMods::Collection.from_xml xml_data
24
- docs.mods.each { |doc| write_file ModsParser.new(doc, series).parse }
25
+ docs.mods.each { |doc| write_file ModsParser.new(doc, series, @errors).parse }
25
26
  end
26
27
 
27
28
  def write_file(bib)
@@ -54,10 +55,6 @@ module Relaton
54
55
  bib.to_rfcxml
55
56
  end
56
57
 
57
- def gh_issue_channel
58
- ["relaton/relaton-data-nist", "Error fetching NIST documents"]
59
- end
60
-
61
58
  def log_error(msg)
62
59
  Util.error msg
63
60
  end
@@ -15,9 +15,10 @@ module Relaton
15
15
  ATTRS = %i[type docidentifier title source abstract date contributor
16
16
  relation place series].freeze
17
17
 
18
- def initialize(doc, series)
18
+ def initialize(doc, series, errors = {})
19
19
  @doc = doc
20
20
  @series = series
21
+ @errors = errors
21
22
  end
22
23
 
23
24
  # @return [Bib::ItemData]
@@ -29,24 +30,24 @@ module Relaton
29
30
  ItemData.new(**args)
30
31
  end
31
32
 
32
- def parse_type
33
- "standard"
34
- end
33
+ def parse_type = "standard"
35
34
 
36
35
  # @return [Array<Bib::Docidentifier>]
37
36
  def parse_docidentifier
38
- [
37
+ ids = [
39
38
  { type: "NIST", content: pub_id, primary: true },
40
39
  { type: "DOI", content: parse_doi },
41
- ].map { |id| Bib::Docidentifier.new(**id) }
40
+ ].reject { |id| id[:content].nil? || id[:content].empty? }
41
+ @errors[:docidentifier] &&= ids.empty?
42
+ ids.map { |id| Bib::Docidentifier.new(**id) }
42
43
  end
43
44
 
44
45
  # @return [String]
45
- def pub_id
46
- get_id_from_str parse_doi
47
- end
46
+ def pub_id = get_id_from_str parse_doi
48
47
 
49
48
  def get_id_from_str(str)
49
+ return if str.nil? || str.empty?
50
+
50
51
  ::Pubid::Nist::Identifier.parse(str).to_s
51
52
  rescue ::Pubid::Core::Errors::ParseError
52
53
  str.gsub(".", " ").sub(/^[\D]+/, &:upcase)
@@ -66,13 +67,15 @@ module Relaton
66
67
 
67
68
  def parse_doi
68
69
  url = @doc.location.reduce(nil) { |m, l| m || l.url.detect { |u| u.usage == "primary display" } }
70
+ return if url.nil?
71
+
69
72
  id = remove_doi_prefix(url.content)
73
+ return if id.nil?
74
+
70
75
  replace_wrong_doi(id)
71
76
  end
72
77
 
73
- def remove_doi_prefix(id)
74
- id.match(/10\.6028\/(.+)/)[1]
75
- end
78
+ def remove_doi_prefix(id) = id.match(/10\.6028\/(.+)/)&.send(:[], 1)
76
79
 
77
80
  # @return [Array<Bib::Title>]
78
81
  def parse_title
@@ -90,6 +93,7 @@ module Relaton
90
93
  elsif title.size == 1
91
94
  title[0].instance_variable_set :@type, "main"
92
95
  end
96
+ @errors[:title] &&= title.empty?
93
97
  title
94
98
  end
95
99
 
@@ -100,26 +104,31 @@ module Relaton
100
104
  end
101
105
 
102
106
  def parse_source
103
- @doc.location.map do |location|
107
+ source = @doc.location.map do |location|
104
108
  url = location.url.first
105
109
  type = url.usage == "primary display" ? "doi" : "src"
106
110
  Bib::Uri.new content: url.content, type: type
107
111
  end
112
+ @errors[:source] &&= source.empty?
113
+ source
108
114
  end
109
115
 
110
116
  def parse_abstract
111
- Array(@doc.abstract).map do |a|
117
+ abstract = Array(@doc.abstract).map do |a|
112
118
  content = a.content.gsub("\n", " ").squeeze(" ").strip
113
- Bib::LocalizedMarkedUpString.new content: content, language: "en",
119
+ Bib::Abstract.new content: content, language: "en",
114
120
  script: "Latn"
115
121
  end
122
+ @errors[:abstract] &&= abstract.empty?
123
+ abstract
116
124
  end
117
125
 
118
126
  def parse_date
119
127
  date = @doc.origin_info[0].date_issued.map do |di|
120
128
  create_date(di, "issued")
121
- end
122
- date.compact
129
+ end.compact
130
+ @errors[:date] &&= date.empty?
131
+ date
123
132
  end
124
133
 
125
134
  def create_date(date, type)
@@ -136,13 +145,11 @@ module Relaton
136
145
  end
137
146
  end
138
147
 
139
- def parse_doctype
140
- Doctype.new(content: "standard")
141
- end
148
+ def parse_doctype = Doctype.new(content: "standard")
142
149
 
143
150
  def parse_contributor
144
151
  # exclude primary contributors to avoid duplication
145
- @doc.name.reject { |n| n.usage == "primary" }.map do |name|
152
+ contributor = @doc.name.reject { |n| n.usage == "primary" }.map do |name|
146
153
  entity, default_role = create_entity(name)
147
154
  next unless entity
148
155
 
@@ -152,6 +159,8 @@ module Relaton
152
159
  role << Bib::Contributor::Role.new(type: default_role) if role.empty?
153
160
  create_contributor(entity, role)
154
161
  end.compact
162
+ @errors[:contributor] &&= contributor.empty?
163
+ contributor
155
164
  end
156
165
 
157
166
  def create_contributor(entity, role)
@@ -200,16 +209,21 @@ module Relaton
200
209
  end
201
210
 
202
211
  def parse_relation
203
- Array(@doc.related_item).reject { |ri| ri.type == "series" }.map do |ri|
212
+ relations = Array(@doc.related_item).reject { |ri| ri.type == "series" }.filter_map do |ri|
204
213
  type = RELATION_TYPES[ri.type]
205
- Relation.new(type: type, bibitem: create_related_item(ri))
214
+ bibitem = create_related_item(ri)
215
+ Relation.new(type: type, bibitem: bibitem) if bibitem
206
216
  end
217
+ @errors[:relation] &&= relations.empty?
218
+ relations
207
219
  end
208
220
 
209
221
  def create_related_item(item)
210
222
  item_id = get_id_from_str related_item_id(item)
223
+ return if item_id.nil? || item_id.empty?
224
+
211
225
  docid = Bib::Docidentifier.new(type: "NIST", content: item_id)
212
- fref = Bib::LocalizedMarkedUpString.new(content: item_id)
226
+ fref = Bib::Formattedref.new(content: item_id)
213
227
  ItemData.new(docidentifier: [docid], formattedref: fref)
214
228
  end
215
229
 
@@ -219,15 +233,20 @@ module Relaton
219
233
  else
220
234
  item.name[0].name_part[0].content
221
235
  end => id
222
- replace_wrong_doi remove_doi_prefix(id)
236
+ doi = remove_doi_prefix(id)
237
+ return if doi.nil?
238
+
239
+ replace_wrong_doi(doi)
223
240
  end
224
241
 
225
242
  def parse_place
226
- @doc.origin_info.select { |p| p.event_type == "publisher" }.map do |p|
227
- place = p.place[0].place_term[0].content
228
- /(?<city>\w+), (?<state>\w+)/ =~ place
243
+ place = @doc.origin_info.select { |p| p.event_type == "publisher" }.map do |p|
244
+ pl = p.place[0].place_term[0].content
245
+ /(?<city>\w+), (?<state>\w+)/ =~ pl
229
246
  Bib::Place.new(city: city, region: create_region(state))
230
247
  end
248
+ @errors[:place] &&= place.empty?
249
+ place
231
250
  end
232
251
 
233
252
  def create_region(state)
@@ -237,12 +256,14 @@ module Relaton
237
256
  end
238
257
 
239
258
  def parse_series
240
- Array(@doc.related_item).select { |ri| ri.type == "series" }.map do |ri|
259
+ series = Array(@doc.related_item).select { |ri| ri.type == "series" }.map do |ri|
241
260
  tinfo = ri.title_info[0]
242
261
  tcontent = tinfo.title[0].strip
243
262
  title = Bib::Title.new(content: tcontent)
244
263
  Bib::Series.new(title: [title], number: tinfo.part_number&.first)
245
264
  end
265
+ @errors[:series] &&= series.empty?
266
+ series
246
267
  end
247
268
  end
248
269
  end
@@ -264,7 +264,7 @@ module Relaton
264
264
  end
265
265
  ids = [Bib::Docidentifier.new(content: ref, type: "NIST", primary: true)]
266
266
  link = [Bib::Uri.new(type: "src", content: uri)]
267
- bib = ItemData.new(formattedref: ref, source: link, docidentifier: ids)
267
+ bib = ItemData.new(formattedref: Bib::Formattedref.new(content: ref), source: link, docidentifier: ids)
268
268
  Relation.new(type: t, description: descr, bibitem: bib)
269
269
  end
270
270
 
@@ -273,7 +273,7 @@ module Relaton
273
273
  def fetch_keywords(doc)
274
274
  doc["keywords"].map do |kw|
275
275
  text = kw.is_a?(String) ? kw : kw.text
276
- Bib::Keyword.new(taxon: [Bib::LocalizedString.new(content: text)])
276
+ Bib::Keyword.new(vocab: Bib::LocalizedString.new(content: text))
277
277
  end
278
278
  end
279
279
 
@@ -1,5 +1,5 @@
1
1
  module Relaton
2
2
  module Nist
3
- VERSION = "2.0.0-alpha.2".freeze
3
+ VERSION = "2.0.0".freeze
4
4
  end
5
5
  end
data/relaton_nist.gemspec CHANGED
@@ -27,8 +27,8 @@ Gem::Specification.new do |spec|
27
27
  spec.add_dependency "mechanize", "~> 2.0"
28
28
  spec.add_dependency "loc_mods", "~> 0.2.0"
29
29
  spec.add_dependency "pubid", "~> 1.15.6"
30
- spec.add_dependency "relaton-bib", "~> 2.0.0-alpha.4"
31
- spec.add_dependency "relaton-core", "~> 0.0.9"
30
+ spec.add_dependency "relaton-bib", "~> 2.0.0"
31
+ spec.add_dependency "relaton-core", "~> 0.0.13"
32
32
  spec.add_dependency "relaton-index", "~> 0.2.0"
33
33
  spec.add_dependency "rubyzip"
34
34
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: relaton-nist
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.pre.alpha.2
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ribose Inc.
@@ -71,28 +71,28 @@ dependencies:
71
71
  requirements:
72
72
  - - "~>"
73
73
  - !ruby/object:Gem::Version
74
- version: 2.0.0.pre.alpha.4
74
+ version: 2.0.0
75
75
  type: :runtime
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: 2.0.0.pre.alpha.4
81
+ version: 2.0.0
82
82
  - !ruby/object:Gem::Dependency
83
83
  name: relaton-core
84
84
  requirement: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: 0.0.9
88
+ version: 0.0.13
89
89
  type: :runtime
90
90
  prerelease: false
91
91
  version_requirements: !ruby/object:Gem::Requirement
92
92
  requirements:
93
93
  - - "~>"
94
94
  - !ruby/object:Gem::Version
95
- version: 0.0.9
95
+ version: 0.0.13
96
96
  - !ruby/object:Gem::Dependency
97
97
  name: relaton-index
98
98
  requirement: !ruby/object:Gem::Requirement
@@ -165,7 +165,6 @@ files:
165
165
  - lib/relaton/nist/relation.rb
166
166
  - lib/relaton/nist/scraper.rb
167
167
  - lib/relaton/nist/series.yaml
168
- - lib/relaton/nist/tech_pubs_parser.rb
169
168
  - lib/relaton/nist/util.rb
170
169
  - lib/relaton/nist/version.rb
171
170
  - relaton_nist.gemspec
@@ -1,321 +0,0 @@
1
- module Relaton
2
- module Nist
3
- class TechPubsParser
4
- RELATION_TYPES = {
5
- "replaces" => "obsoletes",
6
- "isVersionOf" => "editionOf",
7
- "hasTranslation" => "hasTranslation",
8
- "isTranslationOf" => "translatedFrom",
9
- "hasPreprint" => "hasReprint",
10
- "isPreprintOf" => "hasDraft",
11
- "isSupplementTo" => "complements",
12
- "isPartOf" => "partOf",
13
- "hasPart" => "hasPart",
14
- }.freeze
15
-
16
- ATTRS = %i[docidentifier title source abstract date edition contributor
17
- relation status place series].freeze
18
- NS = "http://www.crossref.org/relations.xsd".freeze
19
-
20
- def initialize(doc, series)
21
- @doc = doc
22
- @series = series
23
- end
24
-
25
- #
26
- # Parse XML document
27
- #
28
- # @param doc [Nokogiri::XML::Element] XML document
29
- # @param series [Hash] series hash map
30
- #
31
- # @return [Relaton::Nist::ItemData] bibliographic item
32
- #
33
- def self.parse(doc, series)
34
- new(doc, series).parse
35
- end
36
-
37
- #
38
- # Create document instance
39
- #
40
- # @return [Relaton::Nist::ItemData] bibliographic item
41
- #
42
- def parse
43
- ItemData.new(
44
- type: "standard", language: [@doc["language"]], script: ["Latn"],
45
- ext: Ext.new(doctype: parse_doctype), **args
46
- )
47
- end
48
-
49
- def args
50
- ATTRS.to_h { |a| [a, send("parse_#{a}")] }
51
- end
52
-
53
- # @return [Array<Bib::Docidentifier>]
54
- def parse_docidentifier
55
- [
56
- { type: "NIST", content: pub_id, primary: true },
57
- { type: "DOI", content: doi },
58
- ].map { |id| Bib::Docidentifier.new(**id) }
59
- end
60
-
61
- #
62
- # Parse document's ID from XML
63
- #
64
- # @return [String] document's ID
65
- #
66
- def pub_id
67
- if doi
68
- doi.split("/")[1..].join("/").gsub(".", " ").sub(/^[\D]+/, &:upcase)
69
- else
70
- @doc.at("publisher_item/item_number").text
71
- end
72
- end
73
-
74
- def doi # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
75
- return @doi if defined? @doi
76
-
77
- @doi = begin
78
- id = @doc.at("doi_data/doi")&.text
79
- case id
80
- when "10.6028/NBS.CIRC.e2e" then "10.6028/NBS.CIRC.2e2"
81
- when "10.6028/NBS.CIRC.sup" then "10.6028/NBS.CIRC.24e7sup"
82
- when "10.6028/NBS.CIRC.supJun1925-Jun1926" then "10.6028/NBS.CIRC.24e7sup2"
83
- when "10.6028/NBS.CIRC.supJun1925-Jun1927" then "10.6028/NBS.CIRC.24e7sup3"
84
- when "10.6028/NBS.CIRC.24supJuly1922" then "10.6028/NBS.CIRC.24e6sup"
85
- when "10.6028/NBS.CIRC.24supJan1924" then "10.6028/NBS.CIRC.24e6sup2"
86
- else id
87
- end
88
- end
89
- end
90
-
91
- # @return [Array<Bib::Title>]
92
- def parse_title
93
- t = @doc.xpath("titles/title|titles/subtitle")
94
- return [] unless t.any?
95
-
96
- [Bib::Title.new(content: t.map(&:text).join("\n"), language: "en", script: "Latn")]
97
- end
98
-
99
- # @return [Array<Bib::Uri>]
100
- def parse_source
101
- pdf_url = @doc.at("doi_data/resource").text
102
- doi_url = "https://doi.org/#{doi}"
103
- [
104
- Bib::Uri.new(type: "doi", content: doi_url),
105
- Bib::Uri.new(type: "pdf", content: pdf_url),
106
- ]
107
- end
108
-
109
- # @return [Array<Bib::LocalizedMarkedUpString>]
110
- def parse_abstract
111
- @doc.xpath(
112
- "jats:abstract/jats:p", "jats" => "http://www.ncbi.nlm.nih.gov/JATS1"
113
- ).each_with_object([]) do |a, m|
114
- next if a.text.empty?
115
-
116
- m << Bib::LocalizedMarkedUpString.new(
117
- content: a.text, language: @doc["language"], script: "Latn",
118
- )
119
- end
120
- end
121
-
122
- # @return [Array<Bib::Date>]
123
- def parse_date
124
- @doc.xpath("publication_date|approval_date").map do |dt|
125
- on = dt.at("year").text
126
- if (m = dt.at "month")
127
- on += "-#{m.text}"
128
- d = dt.at "day"
129
- on += "-#{d.text}" if d
130
- end
131
- type = dt.name == "publication_date" ? "published" : "confirmed"
132
- Bib::Date.new(type: type, at: on)
133
- end
134
- end
135
-
136
- def parse_doctype
137
- Doctype.new(content: "standard")
138
- end
139
-
140
- # @return [String]
141
- def parse_edition
142
- @doc.at("edition_number")&.text
143
- end
144
-
145
- # @return [Array<Bib::Contributor>]
146
- def parse_contributor # rubocop:disable Metrics/AbcSize
147
- contribs = @doc.xpath("contributors/person_name").map do |p|
148
- person = Bib::Person.new(
149
- name: fullname(p), affiliation: affiliation, identifier: identifier(p),
150
- )
151
- Bib::Contributor.new(
152
- person: person,
153
- role: [Bib::Contributor::Role.new(type: p["contributor_role"])],
154
- )
155
- end
156
- contribs + @doc.xpath("publisher").map do |p|
157
- Bib::Contributor.new(
158
- organization: create_org(p),
159
- role: [Bib::Contributor::Role.new(type: "publisher")],
160
- )
161
- end
162
- end
163
-
164
- def identifier(person)
165
- person.xpath("ORCID").map do |id|
166
- Bib::Person::Identifier.new(type: "orcid", content: id.text)
167
- end
168
- end
169
-
170
- #
171
- # Create full name object from person name element.
172
- #
173
- # @param [Nokogiri::XML::Element] person name element
174
- #
175
- # @return [Bib::FullName] full name object
176
- #
177
- def fullname(person)
178
- fname, initials = forename_initial person
179
- surname = localized_string person.at("surname")&.text
180
- completename = localized_string person.text unless surname
181
- Bib::FullName.new(
182
- surname: surname, forename: fname, formatted_initials: initials,
183
- completename: completename,
184
- )
185
- end
186
-
187
- #
188
- # Create affiliation organization
189
- #
190
- # @return [Array<Bib::Affiliation>] affiliation
191
- #
192
- def affiliation
193
- @doc.xpath("./institution/institution_department").map do |id|
194
- org = Bib::Organization.new(
195
- name: [Bib::TypedLocalizedString.new(content: id.text)],
196
- )
197
- Bib::Affiliation.new(organization: org)
198
- end
199
- end
200
-
201
- #
202
- # Create forename and initials objects from person name element.
203
- #
204
- # @param [Nokogiri::XML::Element] person person name element
205
- #
206
- # @return [Array<Array<Bib::FullNameType::Forename>, Bib::LocalizedString>]
207
- #
208
- def forename_initial(person) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
209
- fnames = []
210
- fname = person.at("given_name")&.text
211
- if fname
212
- if /^(?:(?<name>\w+)\s)?(?<inits>(?:\w(?:\.|\b)\s?)+)/ =~ fname
213
- ints = inits.split(/[.\s]*/)
214
- fnames << forename(name, ints.shift)
215
- ints.each { |i| fnames << forename(nil, i) }
216
- else
217
- fn = forename(fname)
218
- fnames << fn if fn
219
- end
220
- end
221
- initials = localized_string inits unless inits.nil? || inits.empty?
222
- [fnames, initials]
223
- end
224
-
225
- #
226
- # Create forename object
227
- #
228
- # @param [String, nil] cnt forename content
229
- # @param [String, nil] init initial content
230
- #
231
- # @return [Bib::FullNameType::Forename] forename object
232
- #
233
- def forename(cnt, init = nil)
234
- return if (cnt.nil? || cnt.empty?) && (init.nil? || init.empty?)
235
-
236
- Bib::FullNameType::Forename.new(
237
- content: cnt, language: @doc["language"], script: "Latn", initial: init,
238
- )
239
- end
240
-
241
- #
242
- # Create publisher organization
243
- #
244
- # @param [Nokogiri::XML::Element] pub publisher element
245
- #
246
- # @return [Bib::Organization] publisher organization
247
- #
248
- def create_org(pub) # rubocop:disable Metrics/AbcSize
249
- name = pub.at("publisher_name").text
250
- abbr = pub.at("../institution[institution_name[.='#{name}']]/institution_acronym")&.text
251
- place = pub.at("./publisher_place") ||
252
- pub.at("../institution[institution_name[.='#{name}']]/institution_place")
253
- cont = []
254
- if place
255
- city, state = place.text.split(", ")
256
- cont << Bib::Address.new(street: [], city: city, state: state, country: "US")
257
- end
258
- Bib::Organization.new(
259
- name: [Bib::TypedLocalizedString.new(content: name)],
260
- abbreviation: abbr ? Bib::LocalizedString.new(content: abbr) : nil,
261
- address: cont,
262
- )
263
- end
264
-
265
- # @return [Array<Nist::Relation>]
266
- def parse_relation # rubocop:disable Metrics/AbcSize
267
- @doc.xpath("./ns:program/ns:related_item", ns: NS).map do |rel|
268
- rdoi = rel.at_xpath("ns:intra_work_relation|ns:inter_work_relation", ns: NS)
269
- id = rdoi.text.split("/")[1..].join("/").gsub(".", " ")
270
- fref = Bib::LocalizedMarkedUpString.new(content: id)
271
- docid = Bib::Docidentifier.new(type: "NIST", content: id, primary: true)
272
- bibitem = ItemData.new(formattedref: fref, docidentifier: [docid])
273
- type = RELATION_TYPES[rdoi["relationship-type"]]
274
- warn "Relation type #{rdoi['relationship-type']} not found" unless type
275
- Relation.new(type: type, bibitem: bibitem)
276
- end
277
- end
278
-
279
- def parse_status
280
- s = @doc.at("./ns:program/ns:related_item/ns:*[@relationship-type='isPreprintOf']", ns: NS)
281
- return unless s
282
-
283
- Bib::Status.new(stage: Bib::Status::Stage.new(content: "preprint"))
284
- end
285
-
286
- # @return [Array<Bib::Place>]
287
- def parse_place
288
- @doc.xpath("institution/institution_place").map do |p|
289
- city, state = p.text.split(", ")
290
- Bib::Place.new(city: city, region: [Bib::Place::RegionType.new(iso: state)])
291
- end
292
- end
293
-
294
- #
295
- # Fetches series
296
- #
297
- # @return [Array<Bib::Series>] series
298
- #
299
- def parse_series
300
- prf, srs, num = pub_id.split
301
- sname = @series[srs] || srs
302
- title = Bib::Title.new(content: "#{prf} #{sname}")
303
- abbr = Bib::LocalizedString.new(content: srs)
304
- [Bib::Series.new(title: [title], abbreviation: abbr, number: num)]
305
- end
306
-
307
- #
308
- # Create localized string
309
- #
310
- # @param [String] content content of string
311
- #
312
- # @return [Bib::LocalizedString] localized string
313
- #
314
- def localized_string(content)
315
- return unless content
316
-
317
- Bib::LocalizedString.new(content: content, language: @doc["language"], script: "Latn")
318
- end
319
- end
320
- end
321
- end