relaton-bib 2.0.0.pre.alpha.1 → 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 +4 -4
- data/.gitignore +3 -1
- data/.rubocop.yml +1 -1
- data/CLAUDE.md +96 -0
- data/Gemfile +1 -0
- data/README.adoc +14 -2
- data/grammars/basicdoc.rng +75 -45
- data/grammars/biblio-standoc.rng +37 -56
- data/grammars/biblio.rng +68 -36
- data/grammars/versions.json +25 -25
- data/lib/relaton/bib/converter/asciibib/to_asciibib.rb +663 -0
- data/lib/relaton/bib/converter/asciibib.rb +13 -0
- data/lib/relaton/bib/converter/bibtex/from_bibtex.rb +245 -0
- data/lib/relaton/bib/converter/bibtex/to_bibtex.rb +341 -0
- data/lib/relaton/bib/converter/bibtex.rb +23 -0
- data/lib/relaton/bib/converter/bibxml/from_rfcxml.rb +383 -0
- data/lib/relaton/bib/converter/bibxml/from_rfcxml_referencegroup.rb +71 -0
- data/lib/relaton/bib/{renderer/rfc.rb → converter/bibxml/to_rfcxml.rb} +100 -92
- data/lib/relaton/bib/converter/bibxml/to_rfcxml_referencegroup.rb +52 -0
- data/lib/relaton/bib/converter/bibxml.rb +51 -0
- data/lib/relaton/bib/hash_parser_v1.rb +121 -78
- data/lib/relaton/bib/item_data.rb +83 -22
- data/lib/relaton/bib/model/abstract.rb +16 -0
- data/lib/relaton/bib/model/date.rb +6 -4
- data/lib/relaton/bib/model/depiction.rb +2 -0
- data/lib/relaton/bib/model/ext.rb +0 -3
- data/lib/relaton/bib/model/formattedref.rb +43 -0
- data/lib/relaton/bib/model/ics.rb +9 -0
- data/lib/relaton/bib/model/item.rb +12 -4
- data/lib/relaton/bib/model/item_base.rb +17 -9
- data/lib/relaton/bib/model/keyword.rb +3 -3
- data/lib/relaton/bib/model/logo.rb +2 -0
- data/lib/relaton/bib/model/organization_type.rb +1 -1
- data/lib/relaton/bib/model/relation.rb +2 -2
- data/lib/relaton/bib/model/series.rb +5 -3
- data/lib/relaton/bib/model/subdivision.rb +2 -0
- data/lib/relaton/bib/model/title.rb +38 -0
- data/lib/relaton/bib/model/type/string_date.rb +48 -0
- data/lib/relaton/bib/model/validity.rb +3 -3
- data/lib/relaton/bib/namespace_helper.rb +21 -0
- data/lib/relaton/bib/version.rb +1 -1
- data/lib/relaton/bib.rb +5 -82
- data/relaton-bib.gemspec +5 -2
- metadata +63 -29
- data/lib/relaton/bib/model/editorial_group.rb +0 -14
- data/lib/relaton/bib/model/technical_committee.rb +0 -14
- data/lib/relaton/bib/model/workgroup.rb +0 -20
- data/lib/relaton/bib/parser/rfc_address.rb +0 -60
- data/lib/relaton/bib/parser/rfc_contacts.rb +0 -35
- data/lib/relaton/bib/parser/rfc_docidentifier.rb +0 -70
- data/lib/relaton/bib/parser/rfc_organization.rb +0 -31
- data/lib/relaton/bib/parser/rfc_person.rb +0 -42
- data/lib/relaton/bib/parser/rfc_reference.rb +0 -143
- data/lib/relaton/bib/parser/rfc_referencegroup.rb +0 -45
- data/lib/relaton/bib/parser/rfc_shared.rb +0 -23
- data/lib/relaton/bib/renderer/bibtex_builder.rb +0 -348
- data/lib/relaton/bibtex_parser.rb +0 -243
- data/lib/relaton/bibxml_parser.rb +0 -419
- data/lib/relaton/deep_dup.rb +0 -30
- data/lib/relaton/hit.rb +0 -52
- data/lib/relaton/hit_collection.rb +0 -105
- data/lib/relaton/workers_pool.rb +0 -43
- data/lib/relaton/xml_parser.rb +0 -716
data/lib/relaton/xml_parser.rb
DELETED
|
@@ -1,716 +0,0 @@
|
|
|
1
|
-
require "nokogiri"
|
|
2
|
-
|
|
3
|
-
module Relaton
|
|
4
|
-
class XMLParser
|
|
5
|
-
class << self
|
|
6
|
-
#
|
|
7
|
-
# Parse XML bibdata
|
|
8
|
-
#
|
|
9
|
-
# @param [String] xml XML string
|
|
10
|
-
#
|
|
11
|
-
# @return [Relaton::Bib::Item, nil] bibliographic item
|
|
12
|
-
#
|
|
13
|
-
def from_xml(xml)
|
|
14
|
-
doc = Nokogiri::XML(xml)
|
|
15
|
-
doc.remove_namespaces!
|
|
16
|
-
bibitem = doc.at "/bibitem|/bibdata"
|
|
17
|
-
if bibitem
|
|
18
|
-
bib_item item_data(bibitem)
|
|
19
|
-
else
|
|
20
|
-
Util.warn "Can't find bibitem or bibdata element in the XML"
|
|
21
|
-
nil
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
private
|
|
26
|
-
|
|
27
|
-
#
|
|
28
|
-
# Parse bibitem data
|
|
29
|
-
#
|
|
30
|
-
# @param bibitem [Nokogiri::XML::Element] bibitem element
|
|
31
|
-
#
|
|
32
|
-
# @return [Hash] bibitem data
|
|
33
|
-
#
|
|
34
|
-
def item_data(bibitem) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity, Metrics/AbcSize, Metrics/MethodLength
|
|
35
|
-
ext = bibitem.at "//ext"
|
|
36
|
-
{
|
|
37
|
-
id: bibitem[:id].nil? || bibitem[:id].empty? ? nil : bibitem[:id],
|
|
38
|
-
type: bibitem[:type].nil? || bibitem[:type].empty? ? nil : bibitem[:type],
|
|
39
|
-
fetched: bibitem.at("./fetched")&.text,
|
|
40
|
-
title: fetch_titles(bibitem),
|
|
41
|
-
formattedref: fref(bibitem),
|
|
42
|
-
link: fetch_link(bibitem),
|
|
43
|
-
docid: fetch_docid(bibitem),
|
|
44
|
-
docnumber: bibitem.at("./docnumber")&.text,
|
|
45
|
-
date: fetch_dates(bibitem),
|
|
46
|
-
contributor: fetch_contributors(bibitem),
|
|
47
|
-
edition: fetch_edition(bibitem),
|
|
48
|
-
version: fetch_version(bibitem),
|
|
49
|
-
biblionote: fetch_note(bibitem),
|
|
50
|
-
language: fetch_language(bibitem),
|
|
51
|
-
script: fetch_script(bibitem),
|
|
52
|
-
abstract: fetch_abstract(bibitem),
|
|
53
|
-
docstatus: fetch_status(bibitem),
|
|
54
|
-
copyright: fetch_copyright(bibitem),
|
|
55
|
-
relation: fetch_relations(bibitem),
|
|
56
|
-
series: fetch_series(bibitem),
|
|
57
|
-
medium: fetch_medium(bibitem),
|
|
58
|
-
place: fetch_place(bibitem),
|
|
59
|
-
extent: fetch_extent(bibitem),
|
|
60
|
-
size: fetch_size(bibitem),
|
|
61
|
-
accesslocation: bibitem.xpath("./accesslocation").map(&:text),
|
|
62
|
-
classification: fetch_classification(bibitem),
|
|
63
|
-
keyword: bibitem.xpath("keyword").map(&:text),
|
|
64
|
-
license: bibitem.xpath("license").map(&:text),
|
|
65
|
-
validity: fetch_validity(bibitem),
|
|
66
|
-
doctype: fetch_doctype(ext),
|
|
67
|
-
subdoctype: ext&.at("subdoctype")&.text,
|
|
68
|
-
editorialgroup: fetch_editorialgroup(ext),
|
|
69
|
-
ics: fetch_ics(ext),
|
|
70
|
-
structuredidentifier: fetch_structuredidentifier(ext),
|
|
71
|
-
}
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
#
|
|
75
|
-
# Fetch version.
|
|
76
|
-
#
|
|
77
|
-
# @param [Nokogiri::XML::Elemetn] item bibitem element
|
|
78
|
-
#
|
|
79
|
-
# @return [Array<Relaton::Bib::Item::Version>] versions
|
|
80
|
-
#
|
|
81
|
-
def fetch_version(item)
|
|
82
|
-
item.xpath("./version").map do |v|
|
|
83
|
-
revision_date = v.at("revision-date")&.text
|
|
84
|
-
draft = v.at("draft")&.text
|
|
85
|
-
Relaton::Bib::Item::Version.new revision_date, draft
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
#
|
|
90
|
-
# Fetch edition
|
|
91
|
-
#
|
|
92
|
-
# @param [Nokogiri::XML::Elemetn] item bibitem element
|
|
93
|
-
#
|
|
94
|
-
# @return [Relaton::Bib::Edition, nil] edition
|
|
95
|
-
#
|
|
96
|
-
def fetch_edition(item)
|
|
97
|
-
edt = item.at("./edition")
|
|
98
|
-
return unless edt
|
|
99
|
-
|
|
100
|
-
Edition.new content: edt.text, number: edt[:number]
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
#
|
|
104
|
-
# Fetch place.
|
|
105
|
-
#
|
|
106
|
-
# @param [Nokogiri::XML::Element] item bibitem element
|
|
107
|
-
#
|
|
108
|
-
# @return [Array<Relaton::Bib::Place>] array of places
|
|
109
|
-
#
|
|
110
|
-
def fetch_place(item)
|
|
111
|
-
item.xpath("./place").map do |pl|
|
|
112
|
-
if (city = pl.at("./city"))
|
|
113
|
-
Place.new(city: city.text, region: create_region_country(pl),
|
|
114
|
-
country: create_region_country(pl, "country"))
|
|
115
|
-
else
|
|
116
|
-
Place.new(name: pl.text)
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
|
|
121
|
-
#
|
|
122
|
-
# Create region or country from place element
|
|
123
|
-
#
|
|
124
|
-
# @param [Nokogiri::XML::Element] place place element
|
|
125
|
-
# @param [String] node name of the node to parse
|
|
126
|
-
#
|
|
127
|
-
# @return [Array<Relaton::Bib::Place::RegionType>] <description>
|
|
128
|
-
#
|
|
129
|
-
def create_region_country(place, node = "region")
|
|
130
|
-
place.xpath("./#{node}").map do |r|
|
|
131
|
-
Place::RegionType.new(name: r.text, iso: r[:iso], recommended: r[:recommended])
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def fetch_note(item)
|
|
136
|
-
bnotes = item.xpath("./note").map do |n|
|
|
137
|
-
BiblioNote.new(
|
|
138
|
-
content: n.text,
|
|
139
|
-
type: n[:type],
|
|
140
|
-
format: n[:format],
|
|
141
|
-
language: n[:language],
|
|
142
|
-
script: n[:script],
|
|
143
|
-
)
|
|
144
|
-
end
|
|
145
|
-
BiblioNoteCollection.new bnotes
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
#
|
|
149
|
-
# Fetch language
|
|
150
|
-
#
|
|
151
|
-
# @param [Nokogiri::XML::Element] item bibitem element
|
|
152
|
-
#
|
|
153
|
-
# @return [Array<String>] language en, fr, etc.
|
|
154
|
-
#
|
|
155
|
-
def fetch_language(item)
|
|
156
|
-
item.xpath("./language").reduce([]) do |a, l|
|
|
157
|
-
l.text.empty? ? a : a << l.text
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
|
|
161
|
-
#
|
|
162
|
-
# Fetch script
|
|
163
|
-
#
|
|
164
|
-
# @param [Nokogiri::XML::Element] item XML element
|
|
165
|
-
#
|
|
166
|
-
# @return [Array<String>] scripts Latn, Cyr, etc.
|
|
167
|
-
#
|
|
168
|
-
def fetch_script(item)
|
|
169
|
-
item.xpath("./script").reduce([]) do |a, s|
|
|
170
|
-
s.text.empty? ? a : a << s.text
|
|
171
|
-
end
|
|
172
|
-
end
|
|
173
|
-
|
|
174
|
-
#
|
|
175
|
-
# Fetch series
|
|
176
|
-
#
|
|
177
|
-
# @param [Nokogiri::XML::Element] item bibitem element
|
|
178
|
-
#
|
|
179
|
-
# @return [Array<Relaton::Bib::Series>] series
|
|
180
|
-
#
|
|
181
|
-
def fetch_series(item) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize,Metrics/MethodLength,Metrics/PerceivedComplexity
|
|
182
|
-
item.xpath("./series").reduce([]) do |mem, sr|
|
|
183
|
-
formattedref = fref(sr)
|
|
184
|
-
title = ttitle(sr.at("title"))
|
|
185
|
-
next mem unless formattedref || title
|
|
186
|
-
|
|
187
|
-
abbreviation = localized_string sr.at("abbreviation")
|
|
188
|
-
mem << Series.new(
|
|
189
|
-
type: sr[:type], formattedref: formattedref,
|
|
190
|
-
title: title, place: sr.at("place")&.text,
|
|
191
|
-
organization: sr.at("organization")&.text,
|
|
192
|
-
abbreviation: abbreviation, from: sr.at("from")&.text,
|
|
193
|
-
to: sr.at("to")&.text, number: sr.at("number")&.text,
|
|
194
|
-
partnumber: sr.at("partnumber")&.text, run: sr.at("run")&.text
|
|
195
|
-
)
|
|
196
|
-
end
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
#
|
|
200
|
-
# Fetch medium
|
|
201
|
-
#
|
|
202
|
-
# @param [Nokogiri::XML::Element] item item element
|
|
203
|
-
#
|
|
204
|
-
# @return [Relaton::Bib::Medium, nil] medium
|
|
205
|
-
#
|
|
206
|
-
def fetch_medium(item) # rubocop:disable Metrics/CyclomaticComplexity,Metrics/AbcSize,Metrics/PerceivedComplexity
|
|
207
|
-
medium = item.at("./medium")
|
|
208
|
-
return unless medium
|
|
209
|
-
|
|
210
|
-
Medium.new(
|
|
211
|
-
content: medium.at("content")&.text, genre: medium.at("genre")&.text,
|
|
212
|
-
form: medium.at("form")&.text, carrier: medium.at("carrier")&.text,
|
|
213
|
-
size: medium.at("size")&.text, scale: medium.at("scale")&.text
|
|
214
|
-
)
|
|
215
|
-
end
|
|
216
|
-
|
|
217
|
-
#
|
|
218
|
-
# Fetch extent
|
|
219
|
-
#
|
|
220
|
-
# @param [Nokogiri::XML::Element] item item element
|
|
221
|
-
#
|
|
222
|
-
# @return [Array<RelatonBib::Extent>] extent
|
|
223
|
-
#
|
|
224
|
-
def fetch_extent(item)
|
|
225
|
-
item.xpath("./extent").map do |ex|
|
|
226
|
-
RelatonBib::Extent.new localities(ex)
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
|
|
230
|
-
#
|
|
231
|
-
# Fetch size
|
|
232
|
-
#
|
|
233
|
-
# @param [Nokogiri::XML::Element] item item element
|
|
234
|
-
#
|
|
235
|
-
# @return [Relaton::Bib::BibliographicSize, nil] size
|
|
236
|
-
#
|
|
237
|
-
def fetch_size(item)
|
|
238
|
-
size = item.xpath("./size/value").map do |sz|
|
|
239
|
-
BibliographicSize::Value.new type: sz[:type], value: sz.text
|
|
240
|
-
end
|
|
241
|
-
BibliographicSize.new size if size.any?
|
|
242
|
-
end
|
|
243
|
-
|
|
244
|
-
#
|
|
245
|
-
# Fetch classification
|
|
246
|
-
#
|
|
247
|
-
# @param [Nokogiri::XML::Element] item bibitem element
|
|
248
|
-
#
|
|
249
|
-
# @return [Array<Relaton::Bib::Classification>] classifications
|
|
250
|
-
#
|
|
251
|
-
def fetch_classification(item)
|
|
252
|
-
item.xpath("classification").map do |cls|
|
|
253
|
-
Classification.new type: cls[:type], value: cls.text
|
|
254
|
-
end
|
|
255
|
-
end
|
|
256
|
-
|
|
257
|
-
#
|
|
258
|
-
# Parse validity
|
|
259
|
-
#
|
|
260
|
-
# @param [Nokogiri::XML::Element] item bibitem element
|
|
261
|
-
#
|
|
262
|
-
# @return [Relaton::Bib::Validity, nil] validity
|
|
263
|
-
#
|
|
264
|
-
def fetch_validity(item)
|
|
265
|
-
vl = item.at("./validity")
|
|
266
|
-
return unless vl
|
|
267
|
-
|
|
268
|
-
begins = (b = vl.at("validityBegins")) &&
|
|
269
|
-
Time.strptime(b.text, "%Y-%m-%d %H:%M")
|
|
270
|
-
ends = (e = vl.at("validityEnds")) &&
|
|
271
|
-
Time.strptime(e.text, "%Y-%m-%d %H:%M")
|
|
272
|
-
revision = (r = vl.at("revision")) &&
|
|
273
|
-
Time.strptime(r.text, "%Y-%m-%d %H:%M")
|
|
274
|
-
Validity.new begins: begins, ends: ends, revision: revision
|
|
275
|
-
end
|
|
276
|
-
|
|
277
|
-
def fetch_doctype(ext)
|
|
278
|
-
dt = ext&.at("doctype")
|
|
279
|
-
return unless dt
|
|
280
|
-
|
|
281
|
-
create_doctype dt
|
|
282
|
-
end
|
|
283
|
-
|
|
284
|
-
def create_doctype(type)
|
|
285
|
-
DocumentType.new type: type.text, abbreviation: type[:abbreviation]
|
|
286
|
-
end
|
|
287
|
-
|
|
288
|
-
# @param item [Nokogiri::XML::Element]
|
|
289
|
-
# @return [Array<Relaton::Bib::Docidentifier>]
|
|
290
|
-
def fetch_docid(item)
|
|
291
|
-
item.xpath("./docidentifier").map do |id|
|
|
292
|
-
args = id.to_h.transform_keys(&:to_sym)
|
|
293
|
-
args[:id] = id.children.map { |n| n.text? ? n.content : n.to_xml }.join
|
|
294
|
-
args[:primary] = id[:primary] == "true" ? true : nil
|
|
295
|
-
create_docid(**args)
|
|
296
|
-
end
|
|
297
|
-
end
|
|
298
|
-
|
|
299
|
-
def create_docid(**args)
|
|
300
|
-
DocumentIdentifier.new(**args)
|
|
301
|
-
end
|
|
302
|
-
|
|
303
|
-
# @param item [Nokogiri::XML::Element]
|
|
304
|
-
# @return [Relaton::Bib::TitleCollection]
|
|
305
|
-
def fetch_titles(item)
|
|
306
|
-
ttl = item.xpath("./title").map { |t| ttitle t }
|
|
307
|
-
TitleCollection.new ttl
|
|
308
|
-
end
|
|
309
|
-
|
|
310
|
-
# @param title [Nokogiri::XML::Element]
|
|
311
|
-
# @return [Relaton::Bib::Title]
|
|
312
|
-
def ttitle(title)
|
|
313
|
-
return unless title
|
|
314
|
-
|
|
315
|
-
content = variants(title)
|
|
316
|
-
content = title.children.map { |n| n.text? ? n.content : n.to_xml }.join unless content.any?
|
|
317
|
-
Typed.new(
|
|
318
|
-
type: title[:type], content: content, language: title[:language],
|
|
319
|
-
script: title[:script], format: title[:format]
|
|
320
|
-
)
|
|
321
|
-
end
|
|
322
|
-
|
|
323
|
-
# @param title [Nokogiri::XML::Element]
|
|
324
|
-
# @return [Array<Relaton::Bib::LocalizedString>]
|
|
325
|
-
def variants(elm)
|
|
326
|
-
elm.xpath("variant").map { |v| localized_string v }
|
|
327
|
-
end
|
|
328
|
-
|
|
329
|
-
#
|
|
330
|
-
# Parse status
|
|
331
|
-
#
|
|
332
|
-
# @param [Nokogiri::XML::Element] item XML element
|
|
333
|
-
#
|
|
334
|
-
# @return [Relaton::Bib::DocumentStatus, nil] status
|
|
335
|
-
#
|
|
336
|
-
def fetch_status(item)
|
|
337
|
-
status = item.at("./status")
|
|
338
|
-
return unless status
|
|
339
|
-
|
|
340
|
-
stg = status.at "stage"
|
|
341
|
-
DocumentStatus.new(
|
|
342
|
-
stage: stg ? stage(stg) : status.text,
|
|
343
|
-
substage: stage(status.at("substage")),
|
|
344
|
-
iteration: status.at("iteration")&.text,
|
|
345
|
-
)
|
|
346
|
-
end
|
|
347
|
-
|
|
348
|
-
# @param node [Nokogiri::XML::Elemen]
|
|
349
|
-
# @return [Relaton::Bib::DocumentStatus::Stage]
|
|
350
|
-
def stage(elm)
|
|
351
|
-
return unless elm
|
|
352
|
-
|
|
353
|
-
DocumentStatus::Stage.new(value: elm.text,
|
|
354
|
-
abbreviation: elm[:abbreviation])
|
|
355
|
-
end
|
|
356
|
-
|
|
357
|
-
# @param node [Nokogiri::XML::Elemen]
|
|
358
|
-
# @return [Array<Relaton::Bib::Bdate>]
|
|
359
|
-
def fetch_dates(item) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
|
360
|
-
item.xpath("./date").each_with_object([]) do |d, a|
|
|
361
|
-
type = d[:type].to_s.empty? ? "published" : d[:type]
|
|
362
|
-
if (on = d.at("on"))
|
|
363
|
-
a << Relaton::Bib::Bdate.new(type: type, on: on.text,
|
|
364
|
-
to: d.at("to")&.text)
|
|
365
|
-
elsif (from = d.at("from"))
|
|
366
|
-
a << Relaton::Bib::Bdate.new(type: type, from: from.text,
|
|
367
|
-
to: d.at("to")&.text)
|
|
368
|
-
end
|
|
369
|
-
end
|
|
370
|
-
end
|
|
371
|
-
|
|
372
|
-
#
|
|
373
|
-
# Parse organization
|
|
374
|
-
#
|
|
375
|
-
# @param [Nokogiri::XML::Element] org XML element
|
|
376
|
-
#
|
|
377
|
-
# @return [Relaton::Bib::Organization, nil] organization
|
|
378
|
-
#
|
|
379
|
-
def get_org(org) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
380
|
-
return unless org
|
|
381
|
-
|
|
382
|
-
names = org.xpath("name").map do |n|
|
|
383
|
-
{ content: n.text, language: n[:language], script: n[:script] }
|
|
384
|
-
end
|
|
385
|
-
identifier = org.xpath("./identifier").map do |i|
|
|
386
|
-
OrgIdentifier.new(i[:type], i.text)
|
|
387
|
-
end
|
|
388
|
-
subdiv = org.xpath("subdivision").map &:text
|
|
389
|
-
contact = parse_contact org
|
|
390
|
-
logo = fetch_image org.at("./logo/image")
|
|
391
|
-
Organization.new(
|
|
392
|
-
name: names, abbreviation: org.at("abbreviation")&.text,
|
|
393
|
-
subdivision: subdiv, # url: org.at("uri")&.text,
|
|
394
|
-
identifier: identifier, contact: contact, logo: logo
|
|
395
|
-
)
|
|
396
|
-
end
|
|
397
|
-
|
|
398
|
-
def fetch_image(elm)
|
|
399
|
-
return unless elm
|
|
400
|
-
|
|
401
|
-
Image.new(**elm.to_h.transform_keys(&:to_sym))
|
|
402
|
-
end
|
|
403
|
-
|
|
404
|
-
#
|
|
405
|
-
# Parse person from XML
|
|
406
|
-
#
|
|
407
|
-
# @param [Nokogiri::XML::Element] person XML element
|
|
408
|
-
#
|
|
409
|
-
# @return [Relaton::Bib::Person, nil] person
|
|
410
|
-
#
|
|
411
|
-
def get_person(person) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
412
|
-
return unless person
|
|
413
|
-
|
|
414
|
-
affiliations = person.xpath("./affiliation").map { |a| fetch_affiliation a }
|
|
415
|
-
|
|
416
|
-
contact = parse_contact person
|
|
417
|
-
identifier = person.xpath("./identifier").map do |pi|
|
|
418
|
-
Person::Identifier.new type: pi[:type], content: pi.text
|
|
419
|
-
end
|
|
420
|
-
|
|
421
|
-
Person.new(
|
|
422
|
-
name: full_name(person.at("./name")),
|
|
423
|
-
credential: person.xpath("./credential").map(&:text),
|
|
424
|
-
affiliation: affiliations,
|
|
425
|
-
contact: contact,
|
|
426
|
-
identifier: identifier,
|
|
427
|
-
)
|
|
428
|
-
end
|
|
429
|
-
|
|
430
|
-
def full_name(name)
|
|
431
|
-
cname = localized_string name.at("./completename")
|
|
432
|
-
sname = localized_string name.at("./surname")
|
|
433
|
-
abbreviation = localized_string name.at("./abbreviation")
|
|
434
|
-
|
|
435
|
-
FullName.new(
|
|
436
|
-
completename: cname, surname: sname, abbreviation: abbreviation,
|
|
437
|
-
initials: parse_initials(name), forename: parse_forename(name),
|
|
438
|
-
addition: name_part(name, "addition"), prefix: name_part(name, "prefix")
|
|
439
|
-
)
|
|
440
|
-
end
|
|
441
|
-
|
|
442
|
-
def fetch_affiliation(elm)
|
|
443
|
-
org = get_org elm.at("./organization")
|
|
444
|
-
desc = elm.xpath("./description").map do |e|
|
|
445
|
-
FormattedString.new(content: e.text, language: e[:language],
|
|
446
|
-
script: e[:script], format: e[:format])
|
|
447
|
-
end
|
|
448
|
-
name = localized_string elm.at("./name")
|
|
449
|
-
Affiliation.new organization: org, description: desc, name: name
|
|
450
|
-
end
|
|
451
|
-
|
|
452
|
-
def localized_string(elm)
|
|
453
|
-
return unless elm
|
|
454
|
-
|
|
455
|
-
LocalizedString.new(elm.text, elm[:language], elm[:script])
|
|
456
|
-
end
|
|
457
|
-
|
|
458
|
-
#
|
|
459
|
-
# Parse contact information
|
|
460
|
-
#
|
|
461
|
-
# @param [Nokogiri::XML::Element] contrib contributor element
|
|
462
|
-
#
|
|
463
|
-
# @return [Array<Relaton::Bib::Address, Relaton::Bib::Contact>] contacts
|
|
464
|
-
#
|
|
465
|
-
def parse_contact(contrib)
|
|
466
|
-
contrib.xpath("./address|./phone|./email|./uri").map do |c|
|
|
467
|
-
parse_address(c) || Contact.new(type: c.name, value: c.text, subtype: c[:type])
|
|
468
|
-
end
|
|
469
|
-
end
|
|
470
|
-
|
|
471
|
-
#
|
|
472
|
-
# Parse address
|
|
473
|
-
#
|
|
474
|
-
# @param [Nokogiri::XML::Element] contact contact element
|
|
475
|
-
#
|
|
476
|
-
# @return [Relaton::Bib::Address] address
|
|
477
|
-
#
|
|
478
|
-
def parse_address(contact) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
|
479
|
-
return unless contact.name == "address"
|
|
480
|
-
|
|
481
|
-
Address.new(
|
|
482
|
-
street: contact.xpath("./street").map(&:text),
|
|
483
|
-
city: contact.at("./city")&.text,
|
|
484
|
-
state: contact.at("./state")&.text,
|
|
485
|
-
country: contact.at("./country")&.text,
|
|
486
|
-
postcode: contact.at("./postcode")&.text,
|
|
487
|
-
formatted_address: contact.at("./formattedAddress")&.text,
|
|
488
|
-
)
|
|
489
|
-
end
|
|
490
|
-
|
|
491
|
-
#
|
|
492
|
-
# Parse initials
|
|
493
|
-
#
|
|
494
|
-
# @param [Nokogiri::XML::Element] name person name element
|
|
495
|
-
#
|
|
496
|
-
# @return [Relaton::Bib::LocalizedString, nil] initials
|
|
497
|
-
#
|
|
498
|
-
def parse_initials(name)
|
|
499
|
-
localized_string name.at("./formatted-initials")
|
|
500
|
-
end
|
|
501
|
-
|
|
502
|
-
#
|
|
503
|
-
# Parse forename
|
|
504
|
-
#
|
|
505
|
-
# @param [Nokogiri::XML::Element] name person name element
|
|
506
|
-
#
|
|
507
|
-
# @return [Array<Relaton::Bib::Forename>] forenames
|
|
508
|
-
#
|
|
509
|
-
def parse_forename(name)
|
|
510
|
-
name.xpath("./forename").map do |np|
|
|
511
|
-
args = np.attributes.each_with_object({}) { |(k, v), h| h[k.to_sym] = v.to_s }
|
|
512
|
-
args[:content] = np.text
|
|
513
|
-
Forename.new(**args)
|
|
514
|
-
end
|
|
515
|
-
end
|
|
516
|
-
|
|
517
|
-
#
|
|
518
|
-
# Parse name part
|
|
519
|
-
#
|
|
520
|
-
# @param [Nokogiri::XML::Element] name person name element
|
|
521
|
-
# @param [String] part name part
|
|
522
|
-
#
|
|
523
|
-
# @return [Array<Relaton::Bib::LocalizedString>] name parts
|
|
524
|
-
#
|
|
525
|
-
def name_part(name, part)
|
|
526
|
-
name.xpath("./#{part}").map { |np| localized_string np }
|
|
527
|
-
end
|
|
528
|
-
|
|
529
|
-
# @param item [Nokogiri::XML::Element]
|
|
530
|
-
# @return [Array<Relaton::Bib::ContributionInfo>]
|
|
531
|
-
def fetch_contributors(item)
|
|
532
|
-
item.xpath("./contributor").map { |c| fetch_contribution_info c }
|
|
533
|
-
end
|
|
534
|
-
|
|
535
|
-
def fetch_contribution_info(contrib)
|
|
536
|
-
entity = get_org(contrib.at("./organization")) || get_person(contrib.at("./person"))
|
|
537
|
-
role = contrib.xpath("./role").map do |r|
|
|
538
|
-
{ type: r[:type], description: r.xpath("./description").map(&:text) }
|
|
539
|
-
end
|
|
540
|
-
ContributionInfo.new entity: entity, role: role
|
|
541
|
-
end
|
|
542
|
-
|
|
543
|
-
# @param item [Nokogiri::XML::Element]
|
|
544
|
-
# @return [Array<Relaton::Bib::FormattedString>]
|
|
545
|
-
def fetch_abstract(item)
|
|
546
|
-
item.xpath("./abstract").map do |a|
|
|
547
|
-
c = a.children.to_xml(encoding: "utf-8").strip
|
|
548
|
-
FormattedString.new(content: c, language: a[:language],
|
|
549
|
-
script: a[:script], format: a[:format])
|
|
550
|
-
end
|
|
551
|
-
end
|
|
552
|
-
|
|
553
|
-
# @param item [Nokogiri::XML::Element]
|
|
554
|
-
# @return [Array<Relaton::Bib::CopyrightAssociation>]
|
|
555
|
-
def fetch_copyright(item)
|
|
556
|
-
item.xpath("./copyright").map do |cp|
|
|
557
|
-
owner = cp.xpath("owner").map { |o| fetch_contribution_info o }
|
|
558
|
-
from = cp.at("from")&.text
|
|
559
|
-
to = cp.at("to")&.text
|
|
560
|
-
scope = cp.at("scope")&.text
|
|
561
|
-
CopyrightAssociation.new(owner: owner, from: from, to: to, scope: scope)
|
|
562
|
-
end
|
|
563
|
-
end
|
|
564
|
-
|
|
565
|
-
# @param item [Nokogiri::XML::Element]
|
|
566
|
-
# @return [Arra<Relaton::Bib::Bsource>]
|
|
567
|
-
def fetch_link(item)
|
|
568
|
-
item.xpath("./uri").map do |l|
|
|
569
|
-
Bsource.new(type: l[:type], content: l.text, language: l[:language],
|
|
570
|
-
script: l[:script])
|
|
571
|
-
end
|
|
572
|
-
end
|
|
573
|
-
|
|
574
|
-
# @param item [Nokogiri::XML::Element]
|
|
575
|
-
# @param klass [Relaton::Bib::DocumentRelation.class, RelatonNist::DocumentRelation.class]
|
|
576
|
-
# @return [Array<Relaton::Bib::DocumentRelation>]
|
|
577
|
-
def fetch_relations(item, klass = DocumentRelation)
|
|
578
|
-
item.xpath("./relation").map do |rel|
|
|
579
|
-
klass.new(
|
|
580
|
-
type: rel[:type].nil? || rel[:type].empty? ? nil : rel[:type],
|
|
581
|
-
description: relation_description(rel),
|
|
582
|
-
bibitem: bib_item(item_data(rel.at("./bibitem"))),
|
|
583
|
-
locality: localities(rel),
|
|
584
|
-
source_locality: source_localities(rel),
|
|
585
|
-
)
|
|
586
|
-
end
|
|
587
|
-
end
|
|
588
|
-
|
|
589
|
-
# @param rel [Nokogiri::XML::Element]
|
|
590
|
-
# @return [Relaton::Bib::FormattedString, nil]
|
|
591
|
-
def relation_description(rel)
|
|
592
|
-
d = rel.at "./description"
|
|
593
|
-
return unless d
|
|
594
|
-
|
|
595
|
-
FormattedString.new(content: d.text, language: d[:language],
|
|
596
|
-
script: d[:script], format: d[:format])
|
|
597
|
-
end
|
|
598
|
-
|
|
599
|
-
#
|
|
600
|
-
# Create bibliographic item
|
|
601
|
-
#
|
|
602
|
-
# @param item_hash [Hash] bibliographic item hash
|
|
603
|
-
#
|
|
604
|
-
# @return [Relaton::Bib::Item] bibliographic item
|
|
605
|
-
#
|
|
606
|
-
def bib_item(item_hash)
|
|
607
|
-
Item.new(**item_hash)
|
|
608
|
-
end
|
|
609
|
-
|
|
610
|
-
#
|
|
611
|
-
# Parse locality
|
|
612
|
-
#
|
|
613
|
-
# @param rel [Nokogiri::XML::Element] relation element
|
|
614
|
-
#
|
|
615
|
-
# @return [Array<Relaton::Bib::Locality, Relaton::Bib::LocalityStack>] localities
|
|
616
|
-
#
|
|
617
|
-
def localities(rel)
|
|
618
|
-
rel.xpath("./locality|./localityStack").map do |lc|
|
|
619
|
-
if lc.name == "locality"
|
|
620
|
-
locality lc
|
|
621
|
-
else
|
|
622
|
-
LocalityStack.new(lc.xpath("./locality").map { |l| locality l })
|
|
623
|
-
end
|
|
624
|
-
end
|
|
625
|
-
end
|
|
626
|
-
|
|
627
|
-
#
|
|
628
|
-
# Create Locality object from Nokogiri::XML::Element
|
|
629
|
-
#
|
|
630
|
-
# @param loc [Nokogiri::XML::Element]
|
|
631
|
-
# @param klass [Relaton::Bib::Locality, Relaton::Bib::LocalityStack]
|
|
632
|
-
#
|
|
633
|
-
# @return [Relaton::Bib::Locality]
|
|
634
|
-
def locality(loc, klass = Locality)
|
|
635
|
-
klass.new(
|
|
636
|
-
loc[:type],
|
|
637
|
-
loc.at("./referenceFrom")&.text,
|
|
638
|
-
loc.at("./referenceTo")&.text,
|
|
639
|
-
)
|
|
640
|
-
end
|
|
641
|
-
|
|
642
|
-
# @param rel [Nokogiri::XML::Element]
|
|
643
|
-
# @return [Array<Relaton::Bib::SourceLocality, Relaton::Bib::SourceLocalityStack>]
|
|
644
|
-
def source_localities(rel)
|
|
645
|
-
rel.xpath("./sourceLocality|./sourceLocalityStack").map do |loc|
|
|
646
|
-
if loc.name == "sourceLocality"
|
|
647
|
-
# src_locs = loc.xapth("./sourceLocality").map { |sl| locality(sl, SourceLocality) }
|
|
648
|
-
# SourceLocalityStack.new src_locs
|
|
649
|
-
locality loc, SourceLocality
|
|
650
|
-
else
|
|
651
|
-
sls = loc.xpath("./sourceLocality").map { |l| locality l, SourceLocality }
|
|
652
|
-
SourceLocalityStack.new sls
|
|
653
|
-
end
|
|
654
|
-
end
|
|
655
|
-
end
|
|
656
|
-
|
|
657
|
-
# @param item [Nokogiri::XML::Element]
|
|
658
|
-
# @return [Relaton::Bib::Formattedref, nil]
|
|
659
|
-
def fref(item)
|
|
660
|
-
ident = item&.at("./formattedref")
|
|
661
|
-
return unless ident
|
|
662
|
-
|
|
663
|
-
Formattedref.new(
|
|
664
|
-
content: ident.children.to_s, format: ident[:format],
|
|
665
|
-
language: ident[:language], script: ident[:script]
|
|
666
|
-
)
|
|
667
|
-
end
|
|
668
|
-
|
|
669
|
-
# @param ext [Nokogiri::XML::Element]
|
|
670
|
-
# @return [Relaton::Bib::EditorialGroup, nil]
|
|
671
|
-
def fetch_editorialgroup(ext)
|
|
672
|
-
return unless ext && (eg = ext.at "editorialgroup")
|
|
673
|
-
|
|
674
|
-
eg = eg.xpath("technical-committee").map do |tc|
|
|
675
|
-
wg = WorkGroup.new(
|
|
676
|
-
name: tc.text, number: tc[:number]&.to_i, type: tc[:type],
|
|
677
|
-
identifier: tc[:identifier], prefix: tc[:prefix]
|
|
678
|
-
)
|
|
679
|
-
TechnicalCommittee.new wg
|
|
680
|
-
end
|
|
681
|
-
EditorialGroup.new eg if eg.any?
|
|
682
|
-
end
|
|
683
|
-
|
|
684
|
-
def fetch_ics(ext)
|
|
685
|
-
return [] unless ext
|
|
686
|
-
|
|
687
|
-
ext.xpath("ics").map do |ics|
|
|
688
|
-
ICS.new code: ics.at("code")&.text, text: ics.at("text")&.text
|
|
689
|
-
end
|
|
690
|
-
end
|
|
691
|
-
|
|
692
|
-
# @param ext [Nokogiri::XML::Element]
|
|
693
|
-
# @return [Relaton::Bib::StructuredIdentifierCollection]
|
|
694
|
-
def fetch_structuredidentifier(ext) # rubocop:disable Metrics/AbcSize,Metrics/MethodLength,Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity
|
|
695
|
-
return unless ext
|
|
696
|
-
|
|
697
|
-
sids = ext.xpath("structuredidentifier").map do |si|
|
|
698
|
-
StructuredIdentifier.new(
|
|
699
|
-
type: si[:type],
|
|
700
|
-
agency: si.xpath("agency").map(&:text),
|
|
701
|
-
class: si.at("class")&.text,
|
|
702
|
-
docnumber: si.at("docnumber")&.text,
|
|
703
|
-
partnumber: si.at("partnumber")&.text,
|
|
704
|
-
edition: si.at("edition")&.text,
|
|
705
|
-
version: si.at("version")&.text,
|
|
706
|
-
supplementtype: si.at("supplementtype")&.text,
|
|
707
|
-
supplementnumber: si.at("supplementnumber")&.text,
|
|
708
|
-
language: si.at("language")&.text,
|
|
709
|
-
year: si.at("year")&.text,
|
|
710
|
-
)
|
|
711
|
-
end
|
|
712
|
-
StructuredIdentifierCollection.new sids
|
|
713
|
-
end
|
|
714
|
-
end
|
|
715
|
-
end
|
|
716
|
-
end
|