relaton-render 0.1.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.adoc +64 -19
- data/lib/isodoc/i18n.rb +12 -3
- data/lib/isodoc-yaml/i18n-ar.yaml +29 -0
- data/lib/isodoc-yaml/i18n-de.yaml +27 -0
- data/lib/isodoc-yaml/i18n-en.yaml +14 -5
- data/lib/isodoc-yaml/i18n-es.yaml +28 -0
- data/lib/isodoc-yaml/i18n-fr.yaml +28 -0
- data/lib/isodoc-yaml/i18n-ru.yaml +13 -5
- data/lib/isodoc-yaml/i18n-zh-Hans.yaml +28 -0
- data/lib/relaton/render/fields/date.rb +45 -0
- data/lib/relaton/render/fields/fields.rb +212 -0
- data/lib/relaton/{config.yml → render/general/config.yml} +36 -31
- data/lib/relaton/{render.rb → render/general/render.rb} +52 -33
- data/lib/relaton/{render_classes.rb → render/general/render_classes.rb} +4 -1
- data/lib/relaton/render/parse/parse.rb +62 -0
- data/lib/relaton/render/parse/parse_contributors.rb +105 -0
- data/lib/relaton/render/parse/parse_extract.rb +188 -0
- data/lib/relaton/render/template/liquid.rb +15 -0
- data/lib/relaton/render/template/template.rb +183 -0
- data/lib/{utils → relaton/render/utils}/utils.rb +0 -0
- data/lib/relaton/{version.rb → render/version.rb} +1 -1
- data/lib/relaton-render.rb +5 -4
- data/relaton-render.gemspec +4 -1
- metadata +42 -12
- data/lib/parse/parse.rb +0 -54
- data/lib/parse/parse_contributors.rb +0 -96
- data/lib/parse/parse_extract.rb +0 -155
- data/lib/relaton/render_fields.rb +0 -151
- data/lib/template/template.rb +0 -152
@@ -0,0 +1,188 @@
|
|
1
|
+
module Relaton
|
2
|
+
module Render
|
3
|
+
class Parse
|
4
|
+
def host(doc)
|
5
|
+
doc.relation.detect { |r| r.type == "includedIn" }&.bibitem
|
6
|
+
end
|
7
|
+
|
8
|
+
# TODO : first is naive choice
|
9
|
+
def title(doc)
|
10
|
+
return nil if doc.nil? || doc.title.empty?
|
11
|
+
|
12
|
+
t = doc.title.select { |x| x.title.language&.include? @lang }
|
13
|
+
t.empty? and t = doc.title
|
14
|
+
t.first&.title&.content
|
15
|
+
end
|
16
|
+
|
17
|
+
def medium(doc, host)
|
18
|
+
x = doc.medium || host&.medium or return nil
|
19
|
+
|
20
|
+
%w(content genre form carrier size scale).each_with_object({}) do |i, m|
|
21
|
+
m[i] = x.send i
|
22
|
+
end.compact
|
23
|
+
end
|
24
|
+
|
25
|
+
def size(doc)
|
26
|
+
x = doc.size or return nil
|
27
|
+
x.size.each_with_object({}) do |v, m|
|
28
|
+
m[v.type] ||= []
|
29
|
+
m[v.type] << v.value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def edition(doc, host)
|
34
|
+
doc.edition || host&.edition
|
35
|
+
end
|
36
|
+
|
37
|
+
def place(doc, host)
|
38
|
+
x = doc.place
|
39
|
+
x.empty? && host and x = host.place
|
40
|
+
x.empty? and return x
|
41
|
+
x.map(&:name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def publisher(doc, host)
|
45
|
+
x = pick_contributor(doc, "publisher")
|
46
|
+
host and x ||= pick_contributor(host, "publisher")
|
47
|
+
x.nil? and return nil
|
48
|
+
x.map { |c| extractname(c) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def distributor(doc, host)
|
52
|
+
x = pick_contributor(doc, "distributor")
|
53
|
+
host and x ||= pick_contributor(host, "distributor")
|
54
|
+
x.nil? and return nil
|
55
|
+
x.map { |c| extractname(c) }
|
56
|
+
end
|
57
|
+
|
58
|
+
def series(doc)
|
59
|
+
doc.series.detect { |s| s.type == "main" } ||
|
60
|
+
doc.series.detect { |s| s.type.nil? } ||
|
61
|
+
doc.series.first
|
62
|
+
end
|
63
|
+
|
64
|
+
def series_title(series, _doc)
|
65
|
+
return nil if series.nil?
|
66
|
+
|
67
|
+
series.title.respond_to?(:titles) and
|
68
|
+
return series.title.titles.first.title.content
|
69
|
+
series.title&.title&.content || series.formattedref&.content
|
70
|
+
end
|
71
|
+
|
72
|
+
def series_formatted(series, _doc)
|
73
|
+
series.formattedref&.content
|
74
|
+
end
|
75
|
+
|
76
|
+
def series_abbr(series, _doc)
|
77
|
+
series.abbreviation&.content
|
78
|
+
end
|
79
|
+
|
80
|
+
def series_num(series, _doc)
|
81
|
+
series.number
|
82
|
+
end
|
83
|
+
|
84
|
+
def series_partnumber(series, _doc)
|
85
|
+
series.partnumber
|
86
|
+
end
|
87
|
+
|
88
|
+
def series_run(series, _doc)
|
89
|
+
series.run
|
90
|
+
end
|
91
|
+
|
92
|
+
def standardidentifier(doc)
|
93
|
+
doc.docidentifier.each_with_object([]) do |id, ret|
|
94
|
+
ret << id.id unless standardidentifier_exclude.include? id.type
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def standardidentifier_exclude
|
99
|
+
%w(metanorma metanorma-ordinal)
|
100
|
+
end
|
101
|
+
|
102
|
+
def uri(doc)
|
103
|
+
uri = nil
|
104
|
+
%i(doi uri src).each do |t|
|
105
|
+
uri = doc.link.detect { |u| u.type == t } and break
|
106
|
+
end
|
107
|
+
uri ||= doc.link.first
|
108
|
+
return nil unless uri
|
109
|
+
|
110
|
+
uri.content.to_s
|
111
|
+
end
|
112
|
+
|
113
|
+
def access_location(doc, host)
|
114
|
+
x = doc.accesslocation || host&.accesslocation or
|
115
|
+
return nil
|
116
|
+
x.first
|
117
|
+
end
|
118
|
+
|
119
|
+
def included(type)
|
120
|
+
["article", "inbook", "incollection", "inproceedings"].include? type
|
121
|
+
end
|
122
|
+
|
123
|
+
def type(doc)
|
124
|
+
type = doc.type and return type
|
125
|
+
doc.relation.any? { |r| r.type == "includedIn" } and return "inbook"
|
126
|
+
"book"
|
127
|
+
end
|
128
|
+
|
129
|
+
def extent1(localities)
|
130
|
+
localities.each_with_object({}) do |l, ret|
|
131
|
+
ret[(l.type || "page").to_sym] = {
|
132
|
+
from: localized_string_or_text(l.reference_from),
|
133
|
+
to: localized_string_or_text(l.reference_to),
|
134
|
+
}
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def extent(doc)
|
139
|
+
doc.extent.each_with_object([]) do |e, acc|
|
140
|
+
case e
|
141
|
+
when RelatonBib::LocalityStack
|
142
|
+
acc << extent1(e.locality)
|
143
|
+
when RelatonBib::Locality
|
144
|
+
acc << extent1(Array(e))
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def draft(doc, host)
|
150
|
+
dr = doc.status&.stage&.value || host&.status&.stage&.value
|
151
|
+
|
152
|
+
{ iteration: iter_ordinal(doc) || iter_ordinal(host), status: dr }
|
153
|
+
end
|
154
|
+
|
155
|
+
def iter_ordinal(doc)
|
156
|
+
return nil unless iter = doc&.status&.iteration
|
157
|
+
|
158
|
+
iter
|
159
|
+
end
|
160
|
+
|
161
|
+
def status(doc)
|
162
|
+
doc.status&.stage&.value
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def blank?(text)
|
168
|
+
text.nil? || text.empty?
|
169
|
+
end
|
170
|
+
|
171
|
+
def pick_contributor(doc, role)
|
172
|
+
ret = doc.contributor.select do |c|
|
173
|
+
c.role.any? { |r| r.type == role }
|
174
|
+
end
|
175
|
+
ret.empty? ? nil : ret
|
176
|
+
end
|
177
|
+
|
178
|
+
def localized_string_or_text(str)
|
179
|
+
case str
|
180
|
+
when RelatonBib::LocalizedString
|
181
|
+
str.content
|
182
|
+
when String
|
183
|
+
str
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Relaton
|
2
|
+
module Render
|
3
|
+
module Template
|
4
|
+
module CapitalizeFirst
|
5
|
+
def capitalize_first(words)
|
6
|
+
return nil if words.nil?
|
7
|
+
|
8
|
+
ret = words.split(/[ _]/)
|
9
|
+
ret.first.capitalize! if ret.size.positive?
|
10
|
+
ret.join("_")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
require_relative "../utils/utils"
|
2
|
+
require_relative "liquid"
|
3
|
+
|
4
|
+
module Relaton
|
5
|
+
module Render
|
6
|
+
module Template
|
7
|
+
class General
|
8
|
+
def initialize(opt = {})
|
9
|
+
@htmlentities = HTMLEntities.new
|
10
|
+
customise_liquid
|
11
|
+
parse_options(opt)
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse_options(opt)
|
15
|
+
opt = Utils::sym_keys(opt)
|
16
|
+
@i18n = opt[:i18n]
|
17
|
+
@template_raw = opt[:template].dup
|
18
|
+
@template =
|
19
|
+
case opt[:template]
|
20
|
+
when Hash
|
21
|
+
opt[:template].transform_values { |x| template_process(x) }
|
22
|
+
when Array then opt[:template].map { |x| template_process(x) }
|
23
|
+
else { default: template_process(opt[:template]) }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def customise_liquid
|
28
|
+
::Liquid::Template
|
29
|
+
.register_filter(::Relaton::Render::Template::CapitalizeFirst)
|
30
|
+
end
|
31
|
+
|
32
|
+
# denote start and end of field,
|
33
|
+
# so that we can detect empty fields in postprocessing
|
34
|
+
FIELD_DELIM = "\u0018".freeze
|
35
|
+
|
36
|
+
# escape < >
|
37
|
+
LT_DELIM = "\u0019".freeze
|
38
|
+
GT_DELIM = "\u001a".freeze
|
39
|
+
|
40
|
+
# use tab internally for non-spacing delimiter
|
41
|
+
NON_SPACING_DELIM = "\t".freeze
|
42
|
+
|
43
|
+
def template_process(template)
|
44
|
+
t = template.gsub(/\{\{/, "#{FIELD_DELIM}{{")
|
45
|
+
.gsub(/\}\}/, "}}#{FIELD_DELIM}")
|
46
|
+
.gsub(/\t/, " ")
|
47
|
+
t1 = t.split(/(\{\{.+?\}\})/).map do |n|
|
48
|
+
n.include?("{{") ? n : n.gsub(/(?<!\\)\|/, "\t")
|
49
|
+
end.join
|
50
|
+
::Liquid::Template.parse(t1)
|
51
|
+
end
|
52
|
+
|
53
|
+
def render(hash)
|
54
|
+
t = template_select(hash) or return nil
|
55
|
+
|
56
|
+
template_clean(t.render(liquid_hash(hash.merge("labels" => @i18n.get))))
|
57
|
+
end
|
58
|
+
|
59
|
+
def template_select(_hash)
|
60
|
+
@template[:default]
|
61
|
+
end
|
62
|
+
|
63
|
+
def template_clean(str)
|
64
|
+
str = str.gsub(/</i, LT_DELIM).gsub(/>/i, GT_DELIM)
|
65
|
+
str = template_clean1(@htmlentities.decode(str))
|
66
|
+
/[[:alnum:]]/.match?(str) or return nil
|
67
|
+
str.strip.gsub(/#{LT_DELIM}/o, "<")
|
68
|
+
.gsub(/#{GT_DELIM}/o, ">")
|
69
|
+
.gsub(/&(?!#\S+?;)/, "&")
|
70
|
+
end
|
71
|
+
|
72
|
+
# use tab internally for non-spacing delimiter
|
73
|
+
def template_clean1(str)
|
74
|
+
str.gsub(/\S*#{FIELD_DELIM}#{FIELD_DELIM}\S*/o, "")
|
75
|
+
.gsub(/#{FIELD_DELIM}/o, "")
|
76
|
+
.gsub(/([,:;]\s*)+([,:;](\s|$))/, "\\2")
|
77
|
+
.gsub(/([,.:;]\s*)+([.](\s|$))/, "\\2")
|
78
|
+
.gsub(/([,:;]\s*)+(,(\s|$))/, "\\2")
|
79
|
+
.gsub(/(:\s+)(&\s)/, "\\2")
|
80
|
+
.gsub(/\s+([,.:;)])/, "\\1")
|
81
|
+
.sub(/^\s*[,.:;]\s*/, "")
|
82
|
+
.gsub(/_/, " ")
|
83
|
+
.gsub(/#{NON_SPACING_DELIM}/o, "").gsub(/\s+/, " ")
|
84
|
+
end
|
85
|
+
|
86
|
+
# need non-breaking spaces in fields: "Updated:_nil" ---
|
87
|
+
# we want the "Updated:" deleted,
|
88
|
+
# even if it's multiple words, as in French Mise_à_jour.
|
89
|
+
def liquid_hash(hash)
|
90
|
+
case hash
|
91
|
+
when Hash
|
92
|
+
hash.map { |k, v| [k.to_s, liquid_hash(v)] }.to_h
|
93
|
+
when Array
|
94
|
+
hash.map { |v| liquid_hash(v) }
|
95
|
+
when String
|
96
|
+
hash.empty? ? nil : hash.gsub(/ /, "_")
|
97
|
+
else hash
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
class Series < General
|
103
|
+
end
|
104
|
+
|
105
|
+
class Extent < General
|
106
|
+
def template_select(hash)
|
107
|
+
@template[hash[:type].to_sym]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class Size < General
|
112
|
+
def template_select(hash)
|
113
|
+
@template[hash[:type].to_sym]
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class Name < General
|
118
|
+
def initialize(opt = {})
|
119
|
+
@etal_count = opt[:template]["etal_count"]
|
120
|
+
opt[:template].delete("etal_count")
|
121
|
+
super
|
122
|
+
end
|
123
|
+
|
124
|
+
def template_select(names)
|
125
|
+
return nil if names.nil? || names.empty?
|
126
|
+
|
127
|
+
case names[:surname].size
|
128
|
+
when 1 then @template[:one]
|
129
|
+
when 2 then @template[:two]
|
130
|
+
when 3 then @template[:more]
|
131
|
+
else template_select_etal(names)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def template_select_etal(names)
|
136
|
+
if @etal_count && names.size >= @etal_count
|
137
|
+
@template[:etal]
|
138
|
+
else expand_nametemplate(@template_raw[:more], names.size)
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# assumes that template contains, consecutively and not interleaved,
|
143
|
+
# ...[0], ...[1], ...[2]
|
144
|
+
def expand_nametemplate(template, size)
|
145
|
+
t = nametemplate_split(template)
|
146
|
+
mid = (1..size - 2).each_with_object([]) do |i, m|
|
147
|
+
m << t[1].gsub(/\[1\]/, "[#{i}]")
|
148
|
+
end
|
149
|
+
template_process(t[0] + mid.join + t[2].gsub(/\[2\]/,
|
150
|
+
"[#{size - 1}]"))
|
151
|
+
end
|
152
|
+
|
153
|
+
def nametemplate_split(template)
|
154
|
+
curr = 0
|
155
|
+
prec = ""
|
156
|
+
t = template.split(/(\{[{%].+?[}%]\})/)
|
157
|
+
.each_with_object(["", "", ""]) do |n, m|
|
158
|
+
m, curr, prec = nametemplate_split1(n, m, curr, prec)
|
159
|
+
|
160
|
+
m
|
161
|
+
end
|
162
|
+
t[-1] += prec
|
163
|
+
t
|
164
|
+
end
|
165
|
+
|
166
|
+
def nametemplate_split1(elem, acc, curr, prec)
|
167
|
+
if match = /\{[{%].+?\[(\d)\]/.match(elem)
|
168
|
+
curr += 1 if match[1].to_i > curr
|
169
|
+
acc[curr] += prec
|
170
|
+
prec = ""
|
171
|
+
acc[curr] += elem
|
172
|
+
elsif /\{%\s*endif/.match?(elem)
|
173
|
+
acc[curr] += prec
|
174
|
+
prec = ""
|
175
|
+
acc[curr] += elem
|
176
|
+
else prec += elem
|
177
|
+
end
|
178
|
+
[acc, curr, prec]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
File without changes
|
data/lib/relaton-render.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
-
require "relaton/version"
|
2
|
-
require "relaton/render"
|
3
|
-
require "
|
4
|
-
require "
|
1
|
+
require "relaton/render/version"
|
2
|
+
require "relaton/render/general/render"
|
3
|
+
require "relaton/render/fields/fields"
|
4
|
+
require "relaton/render/parse/parse"
|
5
|
+
require "relaton/render/utils/utils"
|
5
6
|
require "isodoc/i18n"
|
6
7
|
|
data/relaton-render.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
lib = File.expand_path("lib", __dir__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require "relaton/version"
|
3
|
+
require "relaton/render/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "relaton-render"
|
@@ -31,5 +31,8 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_dependency "isodoc-i18n"
|
32
32
|
spec.add_dependency "liquid", "~> 4"
|
33
33
|
spec.add_dependency "nokogiri"
|
34
|
+
spec.add_dependency "relaton-bib", ">= 1.11.0"
|
34
35
|
spec.add_dependency "twitter_cldr"
|
36
|
+
spec.add_dependency "tzinfo-data" # we need this for windows only
|
37
|
+
#spec.metadata["rubygems_mfa_required"] = "true"
|
35
38
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: relaton-render
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-04-
|
11
|
+
date: 2022-04-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -136,6 +136,20 @@ dependencies:
|
|
136
136
|
- - ">="
|
137
137
|
- !ruby/object:Gem::Version
|
138
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: relaton-bib
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 1.11.0
|
146
|
+
type: :runtime
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: 1.11.0
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: twitter_cldr
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,6 +164,20 @@ dependencies:
|
|
150
164
|
- - ">="
|
151
165
|
- !ruby/object:Gem::Version
|
152
166
|
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: tzinfo-data
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
153
181
|
description: Rendering of ISO 690 XML
|
154
182
|
email:
|
155
183
|
- open.source@ribose.com
|
@@ -175,17 +203,19 @@ files:
|
|
175
203
|
- lib/isodoc-yaml/i18n-ru.yaml
|
176
204
|
- lib/isodoc-yaml/i18n-zh-Hans.yaml
|
177
205
|
- lib/isodoc/i18n.rb
|
178
|
-
- lib/parse/parse.rb
|
179
|
-
- lib/parse/parse_contributors.rb
|
180
|
-
- lib/parse/parse_extract.rb
|
181
206
|
- lib/relaton-render.rb
|
182
|
-
- lib/relaton/
|
183
|
-
- lib/relaton/render.rb
|
184
|
-
- lib/relaton/
|
185
|
-
- lib/relaton/
|
186
|
-
- lib/relaton/
|
187
|
-
- lib/
|
188
|
-
- lib/
|
207
|
+
- lib/relaton/render/fields/date.rb
|
208
|
+
- lib/relaton/render/fields/fields.rb
|
209
|
+
- lib/relaton/render/general/config.yml
|
210
|
+
- lib/relaton/render/general/render.rb
|
211
|
+
- lib/relaton/render/general/render_classes.rb
|
212
|
+
- lib/relaton/render/parse/parse.rb
|
213
|
+
- lib/relaton/render/parse/parse_contributors.rb
|
214
|
+
- lib/relaton/render/parse/parse_extract.rb
|
215
|
+
- lib/relaton/render/template/liquid.rb
|
216
|
+
- lib/relaton/render/template/template.rb
|
217
|
+
- lib/relaton/render/utils/utils.rb
|
218
|
+
- lib/relaton/render/version.rb
|
189
219
|
- relaton-render.gemspec
|
190
220
|
homepage: https://github.com/relaton/relaton-render
|
191
221
|
licenses:
|
data/lib/parse/parse.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
require "nokogiri"
|
2
|
-
require "twitter_cldr"
|
3
|
-
require_relative "parse_contributors"
|
4
|
-
require_relative "parse_extract"
|
5
|
-
|
6
|
-
class Iso690Parse
|
7
|
-
def initialize; end
|
8
|
-
|
9
|
-
def extract(doc)
|
10
|
-
host = doc.at("./relation[@type = 'includedIn']/bibitem")
|
11
|
-
simple_xml2hash(doc).merge(simple_or_host_xml2hash(doc, host))
|
12
|
-
.merge(host_xml2hash(host))
|
13
|
-
.merge(series_xml2hash(doc, host))
|
14
|
-
end
|
15
|
-
|
16
|
-
def simple_xml2hash(doc)
|
17
|
-
creators, role = creatornames(doc)
|
18
|
-
{ type: type(doc), title: title(doc), extent_raw: extent(doc),
|
19
|
-
standardidentifier: standardidentifier(doc), uri: uri(doc),
|
20
|
-
status: status(doc), creators: creators, role_raw: role }
|
21
|
-
end
|
22
|
-
|
23
|
-
def simple_or_host_xml2hash(doc, host)
|
24
|
-
{ edition_raw: edition(doc, host), medium: medium(doc, host),
|
25
|
-
place: place(doc, host), publisher: publisher(doc, host),
|
26
|
-
distributor: distributor(doc, host),
|
27
|
-
access_location: access_location(doc, host),
|
28
|
-
date: date(doc, host), date_updated: date_updated(doc, host),
|
29
|
-
date_accessed: date_accessed(doc, host) }
|
30
|
-
end
|
31
|
-
|
32
|
-
def host_xml2hash(host)
|
33
|
-
creators, role = creatornames(host)
|
34
|
-
{ host_creators: creators, host_role_raw: role, host_title: title(host) }
|
35
|
-
end
|
36
|
-
|
37
|
-
def series_xml2hash(doc, host)
|
38
|
-
series = doc.at("./series[@type = 'main']") ||
|
39
|
-
doc.at("./series[not(@type)]") || doc.at("./series")
|
40
|
-
host and series ||=
|
41
|
-
host.at("./series[@type = 'main']") ||
|
42
|
-
host.at("./series[not(@type)]") || host.at("./series")
|
43
|
-
|
44
|
-
series_xml2hash1(series)
|
45
|
-
end
|
46
|
-
|
47
|
-
def series_xml2hash1(series)
|
48
|
-
return {} unless series
|
49
|
-
|
50
|
-
{ series_title: series_title(series), series_abbr: series_abbr(series),
|
51
|
-
series_run: series_run(series), series_num: series_num(series),
|
52
|
-
series_partnumber: series_partnumber(series) }
|
53
|
-
end
|
54
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
class Iso690Parse
|
2
|
-
def extract_orgname(org)
|
3
|
-
name = org.at("./name")
|
4
|
-
name&.text
|
5
|
-
end
|
6
|
-
|
7
|
-
def extract_personname(person)
|
8
|
-
surname = person.at("./name/surname") || person.at("./name/completename")
|
9
|
-
given, middle, initials = given_and_middle_name(person)
|
10
|
-
{ surname: surname&.text,
|
11
|
-
given: given,
|
12
|
-
middle: middle,
|
13
|
-
initials: initials }
|
14
|
-
end
|
15
|
-
|
16
|
-
def given_and_middle_name(person)
|
17
|
-
forenames = person.xpath("./name/forename")&.map(&:text)
|
18
|
-
initials = person.xpath("./name/initial")&.map(&:text)
|
19
|
-
forenames.empty? and initials.empty? and return [nil, nil, nil]
|
20
|
-
forenames.empty? and forenames = initials.dup
|
21
|
-
initials.empty? and initials = forenames.map { |x| x[0] }
|
22
|
-
[forenames.first, forenames[1..-1], initials]
|
23
|
-
end
|
24
|
-
|
25
|
-
def extractname(contributor)
|
26
|
-
org = contributor.at("./organization")
|
27
|
-
person = contributor.at("./person")
|
28
|
-
return { surname: extract_orgname(org) } if org
|
29
|
-
return extract_personname(person) if person
|
30
|
-
|
31
|
-
nil
|
32
|
-
end
|
33
|
-
|
34
|
-
def contributor_role(contributors)
|
35
|
-
return nil unless contributors.length.positive?
|
36
|
-
|
37
|
-
desc = contributors[0].at("role/description")&.text
|
38
|
-
type = contributors[0].at("role/@type")&.text
|
39
|
-
return nil if %w(author publisher).include?(type) && desc.nil?
|
40
|
-
|
41
|
-
type
|
42
|
-
end
|
43
|
-
|
44
|
-
def creatornames(doc)
|
45
|
-
cr = creatornames1(doc)
|
46
|
-
cr.empty? and return [nil, nil]
|
47
|
-
[cr.map { |x| extractname(x) }, contributor_role(cr)]
|
48
|
-
end
|
49
|
-
|
50
|
-
def creatornames1(doc)
|
51
|
-
cr = []
|
52
|
-
return cr if doc.nil?
|
53
|
-
|
54
|
-
%w(author performer adapter translator editor publisher distributor)
|
55
|
-
.each do |r|
|
56
|
-
add = doc.xpath("./contributor[role/@type = '#{r}']")
|
57
|
-
next if add.empty?
|
58
|
-
|
59
|
-
cr = add and break
|
60
|
-
end
|
61
|
-
cr.empty? and cr = doc.xpath("./contributor")
|
62
|
-
cr
|
63
|
-
end
|
64
|
-
|
65
|
-
def date1(date)
|
66
|
-
on = date.at("./on")
|
67
|
-
from = date.at("./from")
|
68
|
-
to = date.at("./to")
|
69
|
-
return { on: on.text } if on
|
70
|
-
return { from: from.text, to: to&.text } if from
|
71
|
-
|
72
|
-
nil
|
73
|
-
end
|
74
|
-
|
75
|
-
def date(doc, host)
|
76
|
-
x = doc.at("./date[@type = 'issued']") ||
|
77
|
-
doc.at("./date[@type = 'circulated']") ||
|
78
|
-
doc.at("./date") ||
|
79
|
-
host&.at("./date[@type = 'issued']") ||
|
80
|
-
host&.at("./date[@type = 'circulated']") ||
|
81
|
-
host&.at("./date") or return nil
|
82
|
-
date1(x)
|
83
|
-
end
|
84
|
-
|
85
|
-
def date_updated(doc, host)
|
86
|
-
x = doc.at("./date[@type = 'updated']") ||
|
87
|
-
host&.at("./date[@type = 'updated']") or return nil
|
88
|
-
date1(x)
|
89
|
-
end
|
90
|
-
|
91
|
-
def date_accessed(doc, host)
|
92
|
-
x = doc.at("./date[@type = 'accessed']") ||
|
93
|
-
host&.at("./date[@type = 'accessed']") or return nil
|
94
|
-
date1(x)
|
95
|
-
end
|
96
|
-
end
|