relaton-ieee 1.19.1 → 1.19.3
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 +4 -4
- data/lib/relaton_ieee/data_fetcher.rb +11 -13
- data/lib/relaton_ieee/idams_parser.rb +252 -0
- data/lib/relaton_ieee/ieee_bibliographic_item.rb +14 -0
- data/lib/relaton_ieee/renderer/bibxml.rb +17 -0
- data/lib/relaton_ieee/version.rb +1 -1
- data/relaton_ieee.gemspec +1 -0
- metadata +18 -3
- data/lib/relaton_ieee/data_parser.rb +0 -350
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aff076d0381b1923da4c5d4283d074ec079d2036c137d88000b18abf02104591
|
4
|
+
data.tar.gz: a7e3c169397610b0535d76dc6b9f960f5b3364058a40a6b3cacd19390fd66cde
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c00b424479fcc970c2c3f7bf69cbfafc12497e4aead258bb33c269ccd0562e2a2d390e4450f15b48fa00469b38212ce6476fa02063beff3b2393adf12ee2cb82
|
7
|
+
data.tar.gz: 18eb28f45eb03c3a330a862995c061c6b3463307818cc6e643ebd23b146f511ba12548629fea161a4818fc82619e178891719af9b648d31b9bff59013f001333
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require "zip"
|
2
|
-
require "relaton_ieee/
|
2
|
+
require "relaton_ieee/idams_parser"
|
3
3
|
require "relaton_ieee/rawbib_id_parser"
|
4
4
|
|
5
5
|
module RelatonIeee
|
@@ -88,27 +88,25 @@ module RelatonIeee
|
|
88
88
|
# @param [String] filename source file
|
89
89
|
#
|
90
90
|
def fetch_doc(xml, filename) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
91
|
-
|
92
|
-
|
91
|
+
begin
|
92
|
+
doc = Ieee::Idams::Publication.from_xml(xml)
|
93
|
+
rescue StandardError
|
93
94
|
Util.warn "Empty file: `#{filename}`"
|
94
95
|
return
|
95
96
|
end
|
96
|
-
|
97
|
-
return if stdid == "0"
|
97
|
+
return if doc.publicationinfo&.standard_id == "0"
|
98
98
|
|
99
|
-
|
100
|
-
bib = fetcher.parse
|
99
|
+
bib = IdamsParser.new(doc, self).parse
|
101
100
|
if bib.docnumber.nil?
|
102
|
-
|
103
|
-
Util.warn "PubID parse error. Normtitle: `#{nt}`, file: `#{filename}`"
|
101
|
+
Util.warn "PubID parse error. Normtitle: `#{doc.normtitle}`, file: `#{filename}`"
|
104
102
|
return
|
105
103
|
end
|
106
|
-
amsid = doc.
|
104
|
+
amsid = doc.publicationinfo.amsid
|
107
105
|
if backrefs.value?(bib.docidentifier[0].id) && /updates\.\d+/ !~ filename
|
108
106
|
oamsid = backrefs.key bib.docidentifier[0].id
|
109
107
|
Util.warn "Document exists ID: `#{bib.docidentifier[0].id}` AMSID: " \
|
110
108
|
"`#{amsid}` source: `#{filename}`. Other AMSID: `#{oamsid}`"
|
111
|
-
if bib.docidentifier
|
109
|
+
if bib.docidentifier.find(&:primary).id.include?(doc.publicationinfo.stdnumber)
|
112
110
|
save_doc bib # rewrite file if the PubID matches to the stdnumber
|
113
111
|
backrefs[amsid] = bib.docidentifier[0].id
|
114
112
|
end
|
@@ -125,9 +123,9 @@ module RelatonIeee
|
|
125
123
|
# @param [Nokogiri::XML::Element] amsid relation data
|
126
124
|
#
|
127
125
|
def add_crossref(docnumber, amsid)
|
128
|
-
return if RELATION_TYPES[amsid
|
126
|
+
return if RELATION_TYPES[amsid.type] == false
|
129
127
|
|
130
|
-
ref = { amsid: amsid.
|
128
|
+
ref = { amsid: amsid.date_string, type: amsid.type }
|
131
129
|
if @crossrefs[docnumber]
|
132
130
|
@crossrefs[docnumber] << ref
|
133
131
|
else @crossrefs[docnumber] = [ref]
|
@@ -0,0 +1,252 @@
|
|
1
|
+
require "ieee-idams"
|
2
|
+
|
3
|
+
module RelatonIeee
|
4
|
+
class IdamsParser
|
5
|
+
ATTRS = %i[
|
6
|
+
docnumber title date docid contributor abstract copyright docstatus
|
7
|
+
relation link keyword ics editorialgroup standard_status standard_modified
|
8
|
+
pubstatus holdstatus doctype
|
9
|
+
].freeze
|
10
|
+
|
11
|
+
def initialize(doc, fetcher)
|
12
|
+
@doc = doc
|
13
|
+
@fetcher = fetcher
|
14
|
+
end
|
15
|
+
|
16
|
+
#
|
17
|
+
# Parse IEEE document
|
18
|
+
#
|
19
|
+
# @return [RelatonIeee::IeeeBibliographicItem]
|
20
|
+
#
|
21
|
+
def parse
|
22
|
+
args = { type: "standard", language: ["en"], script: ["Latn"] }
|
23
|
+
ATTRS.each { |attr| args[attr] = send("parse_#{attr}") }
|
24
|
+
IeeeBibliographicItem.new(**args)
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_docnumber
|
28
|
+
docnumber
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Parse docnumber
|
33
|
+
#
|
34
|
+
# @return [String] PubID
|
35
|
+
#
|
36
|
+
def docnumber
|
37
|
+
@docnumber ||= pubid&.to_id
|
38
|
+
end
|
39
|
+
|
40
|
+
#
|
41
|
+
# Create PubID
|
42
|
+
#
|
43
|
+
# @return [RelatonIeee::RawbibIdParser] PubID
|
44
|
+
#
|
45
|
+
def pubid
|
46
|
+
@pubid ||= begin
|
47
|
+
normtitle = @doc.normtitle
|
48
|
+
stdnumber = @doc.publicationinfo.stdnumber
|
49
|
+
RawbibIdParser.parse(normtitle, stdnumber)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Parse title
|
55
|
+
#
|
56
|
+
# @return [Array<RelatonBib::TypedTitleString>]
|
57
|
+
#
|
58
|
+
def parse_title
|
59
|
+
@doc.btitle.map { |args| RelatonBib::TypedTitleString.new(**args) }
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Parse date
|
64
|
+
#
|
65
|
+
# @return [Array<RelatonBib::BibliographicDate>]
|
66
|
+
#
|
67
|
+
def parse_date
|
68
|
+
@doc.bdate.map { |args| RelatonBib::BibliographicDate.new(**args) }
|
69
|
+
end
|
70
|
+
|
71
|
+
#
|
72
|
+
# Parse identifiers
|
73
|
+
#
|
74
|
+
# @return [Array<RelatonBib::DocumentIdentifier>]
|
75
|
+
#
|
76
|
+
def parse_docid # rubocop:disable Metrics/MethodLength
|
77
|
+
ids = @doc.isbn_doi
|
78
|
+
|
79
|
+
ids.unshift(id: pubid.to_s(trademark: true), scope: "trademark", type: "IEEE", primary: true)
|
80
|
+
ids.unshift(id: pubid.to_s, type: "IEEE", primary: true)
|
81
|
+
|
82
|
+
ids.map { |dcid| RelatonBib::DocumentIdentifier.new(**dcid) }
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# Parse contributors
|
87
|
+
#
|
88
|
+
# @return [Array<RelatonBib::ContributionInfo>]
|
89
|
+
#
|
90
|
+
def parse_contributor
|
91
|
+
name, addr = @doc.contrib_name_addr { |args| RelatonBib::Address.new(**args) }
|
92
|
+
|
93
|
+
entity = create_org name, addr
|
94
|
+
[RelatonBib::ContributionInfo.new(entity: entity, role: [type: "publisher"])]
|
95
|
+
end
|
96
|
+
|
97
|
+
#
|
98
|
+
# Parse abstract
|
99
|
+
#
|
100
|
+
# @return [Array<RelatonBib::FormattedString>]
|
101
|
+
#
|
102
|
+
def parse_abstract
|
103
|
+
@doc.volume.article.articleinfo.abstract.map do |abs|
|
104
|
+
RelatonBib::FormattedString.new(content: abs.value, language: "en", script: "Latn")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# Parse copyright
|
110
|
+
#
|
111
|
+
# @return [Array<RelatonBib::CopyrightAssociation>]
|
112
|
+
#
|
113
|
+
def parse_copyright
|
114
|
+
@doc.copyright.map do |owner, year|
|
115
|
+
contrib = owner.map { |own| RelatonBib::ContributionInfo.new entity: create_org(own) }
|
116
|
+
RelatonBib::CopyrightAssociation.new(owner: contrib, from: year)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
#
|
121
|
+
# Parse status
|
122
|
+
#
|
123
|
+
# @return [RelatonIee::DocumentStatus, nil]
|
124
|
+
#
|
125
|
+
def parse_docstatus
|
126
|
+
@doc.docstatus { |args| DocumentStatus.new(**args) }
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# Parse relation
|
131
|
+
#
|
132
|
+
# @return [RelatonBib::DocRelationCollection]
|
133
|
+
#
|
134
|
+
def parse_relation # rubocop:disable Metrics/AbcSize
|
135
|
+
rels = []
|
136
|
+
@doc.publicationinfo.standard_relationship&.each do |relation|
|
137
|
+
if (ref = @fetcher.backrefs[relation.date_string])
|
138
|
+
rel = @fetcher.create_relation(relation.type, ref)
|
139
|
+
rels << rel if rel
|
140
|
+
elsif !relation.date_string.include?("Inactive Date") && docnumber
|
141
|
+
@fetcher.add_crossref(docnumber, relation)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
RelatonBib::DocRelationCollection.new rels
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Parce link
|
149
|
+
#
|
150
|
+
# @return [Array<RelatonBib::TypedUri>]
|
151
|
+
#
|
152
|
+
def parse_link
|
153
|
+
@doc.link { |url| RelatonBib::TypedUri.new(content: url, type: "src") }
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# Parse keyword
|
158
|
+
#
|
159
|
+
# @return [Array<Strign>]
|
160
|
+
#
|
161
|
+
def parse_keyword
|
162
|
+
@doc.keyword
|
163
|
+
end
|
164
|
+
|
165
|
+
#
|
166
|
+
# Parse ICS
|
167
|
+
#
|
168
|
+
# @return [Array<RelatonBib::ICS>]
|
169
|
+
#
|
170
|
+
def parse_ics
|
171
|
+
@doc.ics { |ics| RelatonBib::ICS.new(**ics) }
|
172
|
+
end
|
173
|
+
|
174
|
+
#
|
175
|
+
# Parse editorialgroup
|
176
|
+
#
|
177
|
+
# @return [RelatonIeee::EditorialGroup, nil] editorialgroup or nil
|
178
|
+
#
|
179
|
+
def parse_editorialgroup
|
180
|
+
@doc.editorialgroup { |committee| EditorialGroup.new committee: committee }
|
181
|
+
end
|
182
|
+
|
183
|
+
#
|
184
|
+
# Parse standard status
|
185
|
+
#
|
186
|
+
# @return [String, nil] standard status or nil
|
187
|
+
#
|
188
|
+
def parse_standard_status
|
189
|
+
@doc.publicationinfo.standard_status
|
190
|
+
end
|
191
|
+
|
192
|
+
#
|
193
|
+
# Parse standard modifier
|
194
|
+
#
|
195
|
+
# @return [String, nil] standard modifier or nil
|
196
|
+
#
|
197
|
+
def parse_standard_modified
|
198
|
+
@doc.standard_modifier
|
199
|
+
end
|
200
|
+
|
201
|
+
#
|
202
|
+
# Parse pubstatus
|
203
|
+
#
|
204
|
+
# @return [String, nil] pubstatus or nil
|
205
|
+
#
|
206
|
+
def parse_pubstatus
|
207
|
+
@doc.publicationinfo.pubstatus
|
208
|
+
end
|
209
|
+
|
210
|
+
#
|
211
|
+
# Pasrse holdstatus
|
212
|
+
#
|
213
|
+
# @return [String, nil] holdstatus or nil
|
214
|
+
#
|
215
|
+
def parse_holdstatus
|
216
|
+
@doc.publicationinfo.holdstatus
|
217
|
+
end
|
218
|
+
|
219
|
+
#
|
220
|
+
# Parse doctype
|
221
|
+
#
|
222
|
+
# @return [String] doctype
|
223
|
+
#
|
224
|
+
def parse_doctype
|
225
|
+
DocumentType.new type: @doc.doctype
|
226
|
+
end
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
#
|
231
|
+
# Create organization
|
232
|
+
#
|
233
|
+
# @param [String] name organization's name
|
234
|
+
# @param [Array<Hash>] addr address
|
235
|
+
#
|
236
|
+
# @return [RelatonBib::Organization]
|
237
|
+
def create_org(name, addr = []) # rubocop:disable Metrics/MethodLength
|
238
|
+
case name
|
239
|
+
when "IEEE"
|
240
|
+
abbr = name
|
241
|
+
n = "Institute of Electrical and Electronics Engineers"
|
242
|
+
url = "http://www.ieee.org"
|
243
|
+
when "ANSI"
|
244
|
+
abbr = name
|
245
|
+
n = "American National Standards Institute"
|
246
|
+
url = "https://www.ansi.org"
|
247
|
+
else n = name
|
248
|
+
end
|
249
|
+
RelatonBib::Organization.new(name: n, abbreviation: abbr, url: url, contact: addr)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative "renderer/bibxml"
|
2
|
+
|
1
3
|
module RelatonIeee
|
2
4
|
class IeeeBibliographicItem < RelatonBib::BibliographicItem
|
3
5
|
SUBTYPES = %w[amendment corrigendum erratum].freeze
|
@@ -102,5 +104,17 @@ module RelatonIeee
|
|
102
104
|
out += "#{prefix}.trialuse:: #{trialuse}\n" unless trialuse.nil?
|
103
105
|
out
|
104
106
|
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# Render BibXML (RFC)
|
110
|
+
#
|
111
|
+
# @param [Nokogiri::XML::Builder, nil] builder
|
112
|
+
# @param [Boolean] include_keywords (false)
|
113
|
+
#
|
114
|
+
# @return [String, Nokogiri::XML::Builder::NodeBuilder] XML
|
115
|
+
#
|
116
|
+
def to_bibxml(builder = nil, include_keywords: false)
|
117
|
+
Renderer::BibXML.new(self).render builder: builder, include_keywords: include_keywords
|
118
|
+
end
|
105
119
|
end
|
106
120
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RelatonIeee
|
2
|
+
module Renderer
|
3
|
+
class BibXML < RelatonBib::Renderer::BibXML
|
4
|
+
|
5
|
+
#
|
6
|
+
# Render workgroup
|
7
|
+
#
|
8
|
+
# @param [Nokogiri::XML::Builder] builder xml builder
|
9
|
+
#
|
10
|
+
def render_workgroup(builder)
|
11
|
+
@bib.editorialgroup&.committee&.each do |committee|
|
12
|
+
builder.workgroup committee
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/relaton_ieee/version.rb
CHANGED
data/relaton_ieee.gemspec
CHANGED
@@ -32,6 +32,7 @@ Gem::Specification.new do |spec|
|
|
32
32
|
spec.require_paths = ["lib"]
|
33
33
|
|
34
34
|
spec.add_dependency "faraday", "~> 2.7.0"
|
35
|
+
spec.add_dependency "ieee-idams", "~> 0.2.10"
|
35
36
|
spec.add_dependency "mini_portile2", "~> 2.8.0"
|
36
37
|
spec.add_dependency "relaton-bib", "~> 1.19.0"
|
37
38
|
spec.add_dependency "relaton-index", "~> 0.2.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: relaton-ieee
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.19.
|
4
|
+
version: 1.19.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 2.7.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: ieee-idams
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.2.10
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.2.10
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: mini_portile2
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,16 +123,17 @@ files:
|
|
109
123
|
- lib/relaton_ieee/balloting_group.rb
|
110
124
|
- lib/relaton_ieee/bibxml_parser.rb
|
111
125
|
- lib/relaton_ieee/data_fetcher.rb
|
112
|
-
- lib/relaton_ieee/data_parser.rb
|
113
126
|
- lib/relaton_ieee/document_status.rb
|
114
127
|
- lib/relaton_ieee/document_type.rb
|
115
128
|
- lib/relaton_ieee/editorial_group.rb
|
116
129
|
- lib/relaton_ieee/hash_converter.rb
|
130
|
+
- lib/relaton_ieee/idams_parser.rb
|
117
131
|
- lib/relaton_ieee/ieee_bibliographic_item.rb
|
118
132
|
- lib/relaton_ieee/ieee_bibliography.rb
|
119
133
|
- lib/relaton_ieee/processor.rb
|
120
134
|
- lib/relaton_ieee/pub_id.rb
|
121
135
|
- lib/relaton_ieee/rawbib_id_parser.rb
|
136
|
+
- lib/relaton_ieee/renderer/bibxml.rb
|
122
137
|
- lib/relaton_ieee/util.rb
|
123
138
|
- lib/relaton_ieee/version.rb
|
124
139
|
- lib/relaton_ieee/xml_parser.rb
|
@@ -1,350 +0,0 @@
|
|
1
|
-
module RelatonIeee
|
2
|
-
class DataParser
|
3
|
-
DATETYPES = { "OriginalPub" => "created", "ePub" => "published",
|
4
|
-
"LastInspecUpd" => "updated" }.freeze
|
5
|
-
ATTRS = %i[
|
6
|
-
docnumber title date docid contributor abstract copyright docstatus
|
7
|
-
relation link keyword ics editorialgroup standard_status standard_modified
|
8
|
-
pubstatus holdstatus doctype
|
9
|
-
].freeze
|
10
|
-
|
11
|
-
attr_reader :doc, :fetcher
|
12
|
-
|
13
|
-
#
|
14
|
-
# Create RelatonIeee::DataParser instance
|
15
|
-
#
|
16
|
-
# @param [Nokogiri::XML::Element] doc document
|
17
|
-
# @param [RelatonIeee::DataFetcher] fetcher
|
18
|
-
#
|
19
|
-
def initialize(doc, fetcher)
|
20
|
-
@doc = doc
|
21
|
-
@fetcher = fetcher
|
22
|
-
end
|
23
|
-
|
24
|
-
#
|
25
|
-
# Parse IEEE document
|
26
|
-
#
|
27
|
-
# @param [Nokogiri::XML::Element] doc document
|
28
|
-
# @param [RelatonIeee::DataFetcher] fetcher <description>
|
29
|
-
#
|
30
|
-
# @return [RelatonIeee::IeeeBibliographicItem]
|
31
|
-
#
|
32
|
-
def self.parse(doc, fetcher)
|
33
|
-
new(doc, fetcher).parse
|
34
|
-
end
|
35
|
-
|
36
|
-
#
|
37
|
-
# Parse IEEE document
|
38
|
-
#
|
39
|
-
# @return [RelatonIeee::IeeeBibliographicItem]
|
40
|
-
#
|
41
|
-
def parse
|
42
|
-
args = { type: "standard", language: ["en"], script: ["Latn"] }
|
43
|
-
ATTRS.each { |attr| args[attr] = send("parse_#{attr}") }
|
44
|
-
IeeeBibliographicItem.new(**args)
|
45
|
-
end
|
46
|
-
|
47
|
-
#
|
48
|
-
# Parse title
|
49
|
-
#
|
50
|
-
# @return [Array<RelatonBib::TypedTitleString>]
|
51
|
-
#
|
52
|
-
def parse_title
|
53
|
-
t = []
|
54
|
-
content = CGI.unescapeHTML doc.at("./volume/article/title").text
|
55
|
-
if content =~ /\A(.+)\s[-\u2014]\sredline\z/i
|
56
|
-
t << RelatonBib::TypedTitleString.new(content: $1, type: "title-main")
|
57
|
-
end
|
58
|
-
t << RelatonBib::TypedTitleString.new(content: content, type: "main")
|
59
|
-
end
|
60
|
-
|
61
|
-
#
|
62
|
-
# Parse date
|
63
|
-
#
|
64
|
-
# @return [Array<RelatonBib::BibliographicDate>]
|
65
|
-
#
|
66
|
-
def parse_date # rubocop:disable Metrics/AbcSize,Metrics/CyclomaticComplexity,Metrics/MethodLength,Metrics/PerceivedComplexity
|
67
|
-
dates = doc.xpath("./volume/article/articleinfo/date").map do |d|
|
68
|
-
da = [d.at("./year").text]
|
69
|
-
m = d.at("./month")&.text
|
70
|
-
if m
|
71
|
-
/^(?:(?<day>\d{1,2})\s)?(?<mon>\w+)/ =~ m
|
72
|
-
month = Date::ABBR_MONTHNAMES.index(mon) || Date::MONTHNAMES.index(mon) || m
|
73
|
-
da << month.to_s.rjust(2, "0")
|
74
|
-
end
|
75
|
-
day = d.at("./day")&.text || day
|
76
|
-
da << day.rjust(2, "0") if day
|
77
|
-
on = da.compact.join "-"
|
78
|
-
RelatonBib::BibliographicDate.new type: DATETYPES[d[:datetype]], on: on
|
79
|
-
end
|
80
|
-
pad = doc.at("./publicationinfo/PubApprovalDate")
|
81
|
-
if pad
|
82
|
-
issued = parse_date_string pad.text
|
83
|
-
dates << RelatonBib::BibliographicDate.new(type: "issued", on: issued)
|
84
|
-
end
|
85
|
-
dates
|
86
|
-
end
|
87
|
-
|
88
|
-
#
|
89
|
-
# Convert date string with month name to numeric date
|
90
|
-
#
|
91
|
-
# @param [String] date source date
|
92
|
-
#
|
93
|
-
# @return [String] numeric date
|
94
|
-
#
|
95
|
-
def parse_date_string(date)
|
96
|
-
case date
|
97
|
-
when /^\d{4}$/ then date
|
98
|
-
when /^\d{1,2}\s\w+\.?\s\d{4}/ then Date.parse(date).to_s
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
#
|
103
|
-
# Parse identifiers
|
104
|
-
#
|
105
|
-
# @return [Array<RelatonBib::DocumentIdentifier>]
|
106
|
-
#
|
107
|
-
def parse_docid # rubocop:disable Metrics/MethodLength
|
108
|
-
ids = [
|
109
|
-
{ id: pubid.to_s, type: "IEEE", primary: true },
|
110
|
-
{ id: pubid.to_s(trademark: true), scope: "trademark", type: "IEEE", primary: true },
|
111
|
-
]
|
112
|
-
isbn = doc.at("./publicationinfo/isbn")
|
113
|
-
ids << { id: isbn.text, type: "ISBN" } if isbn
|
114
|
-
doi = doc.at("./volume/article/articleinfo/articledoi")
|
115
|
-
ids << { id: doi.text, type: "DOI" } if doi
|
116
|
-
ids.map do |dcid|
|
117
|
-
RelatonBib::DocumentIdentifier.new(**dcid)
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
#
|
122
|
-
# Create PubID
|
123
|
-
#
|
124
|
-
# @return [RelatonIeee::RawbibIdParser] PubID
|
125
|
-
#
|
126
|
-
def pubid
|
127
|
-
@pubid ||= begin
|
128
|
-
normtitle = doc.at("./normtitle").text
|
129
|
-
stdnumber = doc.at("./publicationinfo/stdnumber")&.text
|
130
|
-
RawbibIdParser.parse(normtitle, stdnumber)
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
def parse_docnumber
|
135
|
-
docnumber
|
136
|
-
end
|
137
|
-
|
138
|
-
#
|
139
|
-
# Parse docnumber
|
140
|
-
#
|
141
|
-
# @return [String] PubID
|
142
|
-
#
|
143
|
-
def docnumber
|
144
|
-
@docnumber ||= pubid&.to_id # doc.at("./publicationinfo/stdnumber").text
|
145
|
-
end
|
146
|
-
|
147
|
-
#
|
148
|
-
# Parse contributors
|
149
|
-
#
|
150
|
-
# @return [Array<RelatonBib::ContributionInfo>]
|
151
|
-
#
|
152
|
-
def parse_contributor # rubocop:disable Metrics/AbcSize,Metrics/MethodLength
|
153
|
-
doc.xpath("./publicationinfo/publisher").map do |contrib|
|
154
|
-
n = contrib.at("./publishername").text
|
155
|
-
addr = contrib.xpath("./address").each_with_object([]) do |adr, ob|
|
156
|
-
city, country, state = parse_country_city adr
|
157
|
-
next unless city && country
|
158
|
-
|
159
|
-
ob << RelatonBib::Address.new(street: [], city: city, state: state, country: country)
|
160
|
-
end
|
161
|
-
e = create_org n, addr
|
162
|
-
RelatonBib::ContributionInfo.new entity: e, role: [type: "publisher"]
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def parse_country_city(address)
|
167
|
-
city = address.at("./city")
|
168
|
-
return unless city
|
169
|
-
|
170
|
-
city, state = city.text.split(", ")
|
171
|
-
country = address.at("./country")&.text || "USA"
|
172
|
-
[city, country, state]
|
173
|
-
end
|
174
|
-
|
175
|
-
#
|
176
|
-
# Create organization
|
177
|
-
#
|
178
|
-
# @param [String] name organization's name
|
179
|
-
# @param [Array<Hash>] addr address
|
180
|
-
#
|
181
|
-
# @return [RelatonBib::Organization]
|
182
|
-
def create_org(name, addr = []) # rubocop:disable Metrics/MethodLength
|
183
|
-
case name
|
184
|
-
when "IEEE"
|
185
|
-
abbr = name
|
186
|
-
n = "Institute of Electrical and Electronics Engineers"
|
187
|
-
url = "http://www.ieee.org"
|
188
|
-
when "ANSI"
|
189
|
-
abbr = name
|
190
|
-
n = "American National Standards Institute"
|
191
|
-
url = "https://www.ansi.org"
|
192
|
-
else n = name
|
193
|
-
end
|
194
|
-
RelatonBib::Organization.new(
|
195
|
-
name: n, abbreviation: abbr, url: url, contact: addr,
|
196
|
-
)
|
197
|
-
end
|
198
|
-
|
199
|
-
#
|
200
|
-
# Parse abstract
|
201
|
-
#
|
202
|
-
# @return [Array<RelatonBib::FormattedString>]
|
203
|
-
#
|
204
|
-
def parse_abstract
|
205
|
-
doc.xpath("./volume/article/articleinfo/abstract")[0...1].map do |a|
|
206
|
-
RelatonBib::FormattedString.new(
|
207
|
-
content: a.text, language: "en", script: "Latn",
|
208
|
-
)
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
#
|
213
|
-
# Parse copyright
|
214
|
-
#
|
215
|
-
# @return [Array<RelatonBib::CopyrightAssociation>]
|
216
|
-
#
|
217
|
-
def parse_copyright
|
218
|
-
doc.xpath("./publicationinfo/copyrightgroup/copyright").map do |c|
|
219
|
-
owner = c.at("./holder").text.split("/").map do |own|
|
220
|
-
RelatonBib::ContributionInfo.new entity: create_org(own)
|
221
|
-
end
|
222
|
-
RelatonBib::CopyrightAssociation.new(
|
223
|
-
owner: owner, from: c.at("./year").text,
|
224
|
-
)
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
#
|
229
|
-
# Parse status
|
230
|
-
#
|
231
|
-
# @return [RelatonIee::DocumentStatus, nil]
|
232
|
-
#
|
233
|
-
def parse_docstatus
|
234
|
-
st = parse_standard_modified
|
235
|
-
return unless %w[Draft Approved Superseded Withdrawn].include?(st)
|
236
|
-
|
237
|
-
DocumentStatus.new stage: st.downcase
|
238
|
-
end
|
239
|
-
|
240
|
-
#
|
241
|
-
# Parse relation
|
242
|
-
#
|
243
|
-
# @return [RelatonBib::DocRelationCollection]
|
244
|
-
#
|
245
|
-
def parse_relation # rubocop:disable Metrics/AbcSize
|
246
|
-
rels = []
|
247
|
-
doc.xpath("./publicationinfo/standard_relationship").each do |r|
|
248
|
-
if (ref = fetcher.backrefs[r.text])
|
249
|
-
rel = fetcher.create_relation(r[:type], ref)
|
250
|
-
rels << rel if rel
|
251
|
-
elsif !"Inactive Date".include?(r) && docnumber
|
252
|
-
fetcher.add_crossref(docnumber, r)
|
253
|
-
end
|
254
|
-
end
|
255
|
-
RelatonBib::DocRelationCollection.new rels
|
256
|
-
end
|
257
|
-
|
258
|
-
#
|
259
|
-
# Parce link
|
260
|
-
#
|
261
|
-
# @return [Array<RelatonBib::TypedUri>]
|
262
|
-
#
|
263
|
-
def parse_link
|
264
|
-
doc.xpath("./volume/article/articleinfo/amsid").map do |id|
|
265
|
-
l = "https://ieeexplore.ieee.org/document/#{id.text}"
|
266
|
-
RelatonBib::TypedUri.new content: l, type: "src"
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
#
|
271
|
-
# Parse keyword
|
272
|
-
#
|
273
|
-
# @return [Array<Strign>]
|
274
|
-
#
|
275
|
-
def parse_keyword
|
276
|
-
doc.xpath(
|
277
|
-
"./volume/article/articleinfo/keywordset/keyword/keywordterm",
|
278
|
-
).map &:text
|
279
|
-
end
|
280
|
-
|
281
|
-
#
|
282
|
-
# Parse ICS
|
283
|
-
#
|
284
|
-
# @return [Array<RelatonBib::ICS>]
|
285
|
-
#
|
286
|
-
def parse_ics
|
287
|
-
doc.xpath("./publicationinfo/icscodes/code_term").map do |ics|
|
288
|
-
RelatonBib::ICS.new code: ics[:codenum], text: ics.text
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
#
|
293
|
-
# Parse editorialgroup
|
294
|
-
#
|
295
|
-
# @return [RelatonIeee::EditorialGroup, nil] editorialgroup or nil
|
296
|
-
#
|
297
|
-
def parse_editorialgroup
|
298
|
-
committee = doc.xpath(
|
299
|
-
"./publicationinfo/pubsponsoringcommitteeset/pubsponsoringcommittee",
|
300
|
-
).map &:text
|
301
|
-
EditorialGroup.new committee: committee if committee.any?
|
302
|
-
end
|
303
|
-
|
304
|
-
#
|
305
|
-
# Parse standard status
|
306
|
-
#
|
307
|
-
# @return [String, nil] standard status or nil
|
308
|
-
#
|
309
|
-
def parse_standard_status
|
310
|
-
doc.at("./publicationinfo/standard_status")&.text
|
311
|
-
end
|
312
|
-
|
313
|
-
#
|
314
|
-
# Parse standard modifier
|
315
|
-
#
|
316
|
-
# @return [String, nil] standard modifier or nil
|
317
|
-
#
|
318
|
-
def parse_standard_modified
|
319
|
-
doc.at("./publicationinfo/standardmodifierset/standard_modifier")&.text
|
320
|
-
end
|
321
|
-
|
322
|
-
#
|
323
|
-
# Parse pubstatus
|
324
|
-
#
|
325
|
-
# @return [String, nil] pubstatus or nil
|
326
|
-
#
|
327
|
-
def parse_pubstatus
|
328
|
-
doc.at("./publicationinfo/pubstatus")&.text
|
329
|
-
end
|
330
|
-
|
331
|
-
#
|
332
|
-
# Pasrse holdstatus
|
333
|
-
#
|
334
|
-
# @return [String, nil] holdstatus or nil
|
335
|
-
#
|
336
|
-
def parse_holdstatus
|
337
|
-
doc.at("./publicationinfo/holdstatus")&.text
|
338
|
-
end
|
339
|
-
|
340
|
-
#
|
341
|
-
# Parse doctype
|
342
|
-
#
|
343
|
-
# @return [String] doctype
|
344
|
-
#
|
345
|
-
def parse_doctype
|
346
|
-
type = parse_standard_modified == "Redline" ? "redline" : "standard"
|
347
|
-
DocumentType.new type: type
|
348
|
-
end
|
349
|
-
end
|
350
|
-
end
|