relaton-iec 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/grammars/biblio.rng +35 -5
- data/grammars/isodoc.rng +17 -1
- data/grammars/isostandard.rng +9 -1
- data/lib/relaton_iec/scrapper.rb +38 -130
- data/lib/relaton_iec/version.rb +1 -1
- data/relaton_iec.gemspec +1 -1
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: feed37a0cc997a6fbbc8ca4dd6b83dd3cb4496336f65eaeb03f20b12f3ff9f2d
|
4
|
+
data.tar.gz: 7dd0c847253d5e44ad50e36b7352ed905d55c6155cf0bd1621f9b1a46b019160
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d8ded4181c4a2130743bef4664c411b435aa6e9d25b5c580340c6eb644049adc43313089640c4195838ae165a843cfcf869c1076afe92b4f35101c55977f7d22
|
7
|
+
data.tar.gz: 764b7692397d25da284c7ef704ccbc56373d4b743c3c02864e1ede7b530f641ce5a53c3c0486f943a86b52843f7dd30c7ee9f66a0b618647c6bd4f7f1863eedb
|
data/grammars/biblio.rng
CHANGED
@@ -88,7 +88,7 @@
|
|
88
88
|
<text/>
|
89
89
|
</element>
|
90
90
|
</define>
|
91
|
-
<define name="
|
91
|
+
<define name="LocalizedString1">
|
92
92
|
<optional>
|
93
93
|
<!-- multiple languages and scripts possible: comma delimit them if so -->
|
94
94
|
<attribute name="language"/>
|
@@ -98,6 +98,16 @@
|
|
98
98
|
</optional>
|
99
99
|
<text/>
|
100
100
|
</define>
|
101
|
+
<define name="LocalizedString">
|
102
|
+
<choice>
|
103
|
+
<ref name="LocalizedString1"/>
|
104
|
+
<oneOrMore>
|
105
|
+
<element name="variant">
|
106
|
+
<ref name="LocalizedString1"/>
|
107
|
+
</element>
|
108
|
+
</oneOrMore>
|
109
|
+
</choice>
|
110
|
+
</define>
|
101
111
|
<!--
|
102
112
|
Unlike UML, change type to format: type is overloaded
|
103
113
|
Would be need if plain were default value and could omit the attribute
|
@@ -121,7 +131,7 @@
|
|
121
131
|
</optional>
|
122
132
|
<ref name="LocalizedStringOrXsAny"/>
|
123
133
|
</define>
|
124
|
-
<define name="
|
134
|
+
<define name="LocalizedStringOrXsAny1">
|
125
135
|
<optional>
|
126
136
|
<!-- multiple languages and scripts possible: comma delimit them if so -->
|
127
137
|
<attribute name="language"/>
|
@@ -136,6 +146,16 @@
|
|
136
146
|
</choice>
|
137
147
|
</oneOrMore>
|
138
148
|
</define>
|
149
|
+
<define name="LocalizedStringOrXsAny">
|
150
|
+
<choice>
|
151
|
+
<ref name="LocalizedStringOrXsAny1"/>
|
152
|
+
<oneOrMore>
|
153
|
+
<element name="variant">
|
154
|
+
<ref name="LocalizedStringOrXsAny1"/>
|
155
|
+
</element>
|
156
|
+
</oneOrMore>
|
157
|
+
</choice>
|
158
|
+
</define>
|
139
159
|
<define name="contributor">
|
140
160
|
<element name="contributor">
|
141
161
|
<zeroOrMore>
|
@@ -641,9 +661,9 @@
|
|
641
661
|
<optional>
|
642
662
|
<ref name="status"/>
|
643
663
|
</optional>
|
644
|
-
<
|
664
|
+
<zeroOrMore>
|
645
665
|
<ref name="copyright"/>
|
646
|
-
</
|
666
|
+
</zeroOrMore>
|
647
667
|
<zeroOrMore>
|
648
668
|
<ref name="docrelation"/>
|
649
669
|
</zeroOrMore>
|
@@ -1001,7 +1021,17 @@
|
|
1001
1021
|
<optional>
|
1002
1022
|
<ref name="to"/>
|
1003
1023
|
</optional>
|
1004
|
-
<
|
1024
|
+
<oneOrMore>
|
1025
|
+
<ref name="owner"/>
|
1026
|
+
</oneOrMore>
|
1027
|
+
<optional>
|
1028
|
+
<ref name="copyright_scope"/>
|
1029
|
+
</optional>
|
1030
|
+
</element>
|
1031
|
+
</define>
|
1032
|
+
<define name="copyright_scope">
|
1033
|
+
<element name="scope">
|
1034
|
+
<text/>
|
1005
1035
|
</element>
|
1006
1036
|
</define>
|
1007
1037
|
<define name="from">
|
data/grammars/isodoc.rng
CHANGED
@@ -53,6 +53,14 @@
|
|
53
53
|
<optional>
|
54
54
|
<attribute name="alt"/>
|
55
55
|
</optional>
|
56
|
+
<optional>
|
57
|
+
<attribute name="case">
|
58
|
+
<choice>
|
59
|
+
<value>capital</value>
|
60
|
+
<value>lowercase</value>
|
61
|
+
</choice>
|
62
|
+
</attribute>
|
63
|
+
</optional>
|
56
64
|
<text/>
|
57
65
|
</element>
|
58
66
|
</define>
|
@@ -902,7 +910,15 @@
|
|
902
910
|
<attribute name="id">
|
903
911
|
<data type="ID"/>
|
904
912
|
</attribute>
|
905
|
-
<
|
913
|
+
<oneOrMore>
|
914
|
+
<choice>
|
915
|
+
<ref name="paragraph"/>
|
916
|
+
<ref name="ul"/>
|
917
|
+
<ref name="ol"/>
|
918
|
+
<ref name="dl"/>
|
919
|
+
<ref name="formula"/>
|
920
|
+
</choice>
|
921
|
+
</oneOrMore>
|
906
922
|
</element>
|
907
923
|
</define>
|
908
924
|
<define name="termexample">
|
data/grammars/isostandard.rng
CHANGED
@@ -91,6 +91,12 @@
|
|
91
91
|
</define>
|
92
92
|
<define name="sections">
|
93
93
|
<element name="sections">
|
94
|
+
<zeroOrMore>
|
95
|
+
<choice>
|
96
|
+
<ref name="note"/>
|
97
|
+
<ref name="admonition"/>
|
98
|
+
</choice>
|
99
|
+
</zeroOrMore>
|
94
100
|
<ref name="clause"/>
|
95
101
|
<optional>
|
96
102
|
<choice>
|
@@ -263,6 +269,8 @@
|
|
263
269
|
<value>publicly-available-specification</value>
|
264
270
|
<value>international-workshop-agreement</value>
|
265
271
|
<value>guide</value>
|
272
|
+
<value>amendment</value>
|
273
|
+
<value>technical-corrigendum</value>
|
266
274
|
</choice>
|
267
275
|
</define>
|
268
276
|
<define name="structuredidentifier">
|
@@ -510,7 +518,7 @@
|
|
510
518
|
</attribute>
|
511
519
|
</optional>
|
512
520
|
<oneOrMore>
|
513
|
-
<ref name="
|
521
|
+
<ref name="BasicBlock"/>
|
514
522
|
</oneOrMore>
|
515
523
|
</element>
|
516
524
|
</define>
|
data/lib/relaton_iec/scrapper.rb
CHANGED
@@ -32,27 +32,18 @@ module RelatonIec
|
|
32
32
|
}.freeze
|
33
33
|
|
34
34
|
class << self
|
35
|
-
#
|
36
|
-
# @return [Array<Hash>]
|
37
|
-
# def get(text)
|
38
|
-
# iso_workers = WorkersPool.new 4
|
39
|
-
# iso_workers.worker { |hit| iso_worker(hit, iso_workers) }
|
40
|
-
# algolia_workers = start_algolia_search(text, iso_workers)
|
41
|
-
# iso_docs = iso_workers.result
|
42
|
-
# algolia_workers.end
|
43
|
-
# algolia_workers.result
|
44
|
-
# iso_docs
|
45
|
-
# end
|
35
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
46
36
|
|
47
37
|
# Parse page.
|
48
38
|
# @param hit [Hash]
|
49
39
|
# @return [Hash]
|
50
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
51
40
|
def parse_page(hit_data)
|
52
41
|
doc = get_page hit_data[:url]
|
53
42
|
|
54
43
|
# Fetch edition.
|
55
|
-
edition = doc.at(
|
44
|
+
edition = doc.at(
|
45
|
+
"//th[contains(., 'Edition')]/following-sibling::td/span",
|
46
|
+
).text
|
56
47
|
|
57
48
|
status, relations = fetch_status_relations hit_data[:url]
|
58
49
|
|
@@ -81,46 +72,6 @@ module RelatonIec
|
|
81
72
|
|
82
73
|
private
|
83
74
|
|
84
|
-
# Start search workers.
|
85
|
-
# @param text[String]
|
86
|
-
# @param iec_workers [Isobib::WorkersPool]
|
87
|
-
# @reaturn [Isobib::WorkersPool]
|
88
|
-
# def start_algolia_search(text, iec_workers)
|
89
|
-
# index = Algolia::Index.new 'all_en'
|
90
|
-
# workers = WorkersPool.new
|
91
|
-
# workers.worker do |page|
|
92
|
-
# algolia_worker(index, text, page, workers, iec_workers)
|
93
|
-
# end
|
94
|
-
|
95
|
-
# # Add first page so search worker will start.
|
96
|
-
# workers << 0
|
97
|
-
# end
|
98
|
-
|
99
|
-
# Fetch ISO documents.
|
100
|
-
# @param hit [Hash]
|
101
|
-
# @param isiso_workers [Isobib::WorkersPool]
|
102
|
-
# def iso_worker(hit, iso_workers)
|
103
|
-
# print "Parse #{iso_workers.size} of #{iso_workers.nb_hits} \r"
|
104
|
-
# parse_page hit
|
105
|
-
# end
|
106
|
-
|
107
|
-
# Fetch hits from algolia search service.
|
108
|
-
# @param index[Algolia::Index]
|
109
|
-
# @param text [String]
|
110
|
-
# @param page [Integer]
|
111
|
-
# @param algolia_workers [Isobib::WorkersPool]
|
112
|
-
# @param isiso_workers [Isobib::WorkersPool]
|
113
|
-
# def algolia_worker(index, text, page, algolia_workers, iso_workers)
|
114
|
-
# res = index.search text, facetFilters: ['category:standard'], page: page
|
115
|
-
# next_page = res['page'] + 1
|
116
|
-
# algolia_workers << next_page if next_page < res['nbPages']
|
117
|
-
# res['hits'].each do |hit|
|
118
|
-
# iso_workers.nb_hits = res['nbHits']
|
119
|
-
# iso_workers << hit
|
120
|
-
# end
|
121
|
-
# iso_workers.end unless next_page < res['nbPages']
|
122
|
-
# end
|
123
|
-
|
124
75
|
# Fetch abstracts.
|
125
76
|
# @param doc [Nokigiri::HTML::Document]
|
126
77
|
# @return [Array<Array>]
|
@@ -134,19 +85,6 @@ module RelatonIec
|
|
134
85
|
}]
|
135
86
|
end
|
136
87
|
|
137
|
-
# Get langs.
|
138
|
-
# @param doc [Nokogiri::HTML::Document]
|
139
|
-
# @return [Array<Hash>]
|
140
|
-
# def langs(doc)
|
141
|
-
# lgs = [{ lang: 'en' }]
|
142
|
-
# doc.css('ul#lang-switcher ul li a').each do |lang_link|
|
143
|
-
# lang_path = lang_link.attr('href')
|
144
|
-
# lang = lang_path.match(%r{^\/(fr)\/})
|
145
|
-
# lgs << { lang: lang[1], path: lang_path } if lang
|
146
|
-
# end
|
147
|
-
# lgs
|
148
|
-
# end
|
149
|
-
|
150
88
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
151
89
|
|
152
90
|
# Get page.
|
@@ -154,25 +92,20 @@ module RelatonIec
|
|
154
92
|
# @return [Array<Nokogiri::HTML::Document, String>]
|
155
93
|
def get_page(url)
|
156
94
|
uri = URI url
|
157
|
-
resp = Net::HTTP.get_response(uri)
|
95
|
+
resp = Net::HTTP.get_response(uri)
|
158
96
|
case resp.code
|
159
97
|
when "301"
|
160
98
|
path = resp["location"]
|
161
99
|
url = DOMAIN + path
|
162
100
|
uri = URI url
|
163
|
-
resp = Net::HTTP.get_response(uri)
|
101
|
+
resp = Net::HTTP.get_response(uri)
|
164
102
|
when "404"
|
165
103
|
raise RelatonBib::RequestError, "Page not found #{url}"
|
166
104
|
end
|
167
|
-
# n = 0
|
168
|
-
# while resp.body !~ /<strong/ && n < 10
|
169
|
-
# resp = Net::HTTP.get_response(uri)#.encode("UTF-8")
|
170
|
-
# n += 1
|
171
|
-
# end
|
172
105
|
Nokogiri::HTML(resp.body)
|
173
|
-
rescue SocketError, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
|
174
|
-
Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
|
175
|
-
OpenSSL::SSL::SSLError
|
106
|
+
rescue SocketError, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
|
107
|
+
EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
|
108
|
+
Net::ProtocolError, OpenSSL::SSL::SSLError
|
176
109
|
raise RelatonBib::RequestError, "Could not access #{url}"
|
177
110
|
end
|
178
111
|
# rubocop:enable Metrics/AbcSize
|
@@ -211,15 +144,12 @@ module RelatonIec
|
|
211
144
|
statuses = YAML.load_file "lib/relaton_iec/statuses.yml"
|
212
145
|
s = wip.at("STAGE").text
|
213
146
|
stage, substage = statuses[s]["stage"].split "."
|
214
|
-
# status = statuses[s]["status"]
|
215
147
|
else
|
216
|
-
# status = "Published"
|
217
148
|
stage = "60"
|
218
149
|
substage = "60"
|
219
150
|
end
|
220
151
|
RelatonBib::DocumentStatus.new(stage: stage, substage: substage)
|
221
152
|
end
|
222
|
-
# rubocop:enable Metrics/MethodLength
|
223
153
|
|
224
154
|
# Fetch workgroup.
|
225
155
|
# @param doc [Nokogiri::HTML::Document]
|
@@ -237,13 +167,15 @@ module RelatonIec
|
|
237
167
|
}],
|
238
168
|
}
|
239
169
|
end
|
170
|
+
# rubocop:enable Metrics/MethodLength
|
240
171
|
|
241
172
|
# Fetch relations.
|
242
173
|
# @param doc [Nokogiri::HTML::Document]
|
243
174
|
# @return [Array<Hash>]
|
244
175
|
# rubocop:disable Metrics/MethodLength
|
245
176
|
def fetch_relations(doc)
|
246
|
-
doc.xpath('//ROW[STATUS[.!="PREPARING"]][STATUS[.!="PUBLISHED"]]').
|
177
|
+
doc.xpath('//ROW[STATUS[.!="PREPARING"]][STATUS[.!="PUBLISHED"]]').
|
178
|
+
map do |r|
|
247
179
|
r_type = r.at("STATUS").text.downcase
|
248
180
|
type = case r_type
|
249
181
|
# when 'published' then 'obsoletes' # Valid
|
@@ -251,7 +183,6 @@ module RelatonIec
|
|
251
183
|
when "withdrawn" then "obsoletes"
|
252
184
|
else r_type
|
253
185
|
end
|
254
|
-
# url = DOMAIN + "/publication/" + r.at("PUB_ID").text
|
255
186
|
fref = RelatonBib::FormattedRef.new(
|
256
187
|
content: r.at("FULL_NAME").text, format: "text/plain",
|
257
188
|
)
|
@@ -270,22 +201,6 @@ module RelatonIec
|
|
270
201
|
status = fetch_status doc
|
271
202
|
relations = fetch_relations doc
|
272
203
|
[status, relations]
|
273
|
-
# doc.css('ul.steps li').inject([]) do |a, r|
|
274
|
-
# r_type = r.css('strong').text
|
275
|
-
# type = case r_type
|
276
|
-
# when 'Previously', 'Will be replaced by' then 'obsoletes'
|
277
|
-
# when 'Corrigenda/Amendments', 'Revised by', 'Now confirmed'
|
278
|
-
# 'updates'
|
279
|
-
# else r_type
|
280
|
-
# end
|
281
|
-
# if ['Now', 'Now under review'].include? type
|
282
|
-
# a
|
283
|
-
# else
|
284
|
-
# a + r.css('a').map do |id|
|
285
|
-
# { type: type, identifier: id.text, url: id['href'] }
|
286
|
-
# end
|
287
|
-
# end
|
288
|
-
# end
|
289
204
|
end
|
290
205
|
# rubocop:enable Metrics/MethodLength
|
291
206
|
|
@@ -293,23 +208,13 @@ module RelatonIec
|
|
293
208
|
# @param doc [Nokogiri::HTML::Document]
|
294
209
|
# @return [String]
|
295
210
|
def fetch_type(doc)
|
296
|
-
doc.at(
|
297
|
-
|
298
|
-
|
299
|
-
# /NP)*\s|/)(TS|TR|PAS|AWI|CD|FDIS|NP|DIS|WD|R|Guide|(?=\d+))}x)
|
300
|
-
# #return "international-standard" if type_match.nil?
|
301
|
-
# if TYPES[type_match[2]]
|
302
|
-
# TYPES[type_match[2]]
|
303
|
-
# elsif type_match[1]
|
304
|
-
# elsif type_match[1] == 'ISO'
|
305
|
-
# 'international-standard'
|
306
|
-
# elsif type_match[1] == 'IWA'
|
307
|
-
# 'international-workshop-agreement'
|
308
|
-
# end
|
309
|
-
# # rescue => _e
|
310
|
-
# # puts 'Unknown document type: ' + title
|
211
|
+
doc.at(
|
212
|
+
'//th[contains(., "Publication type")]/following-sibling::td/span',
|
213
|
+
).text.downcase.tr " ", "-"
|
311
214
|
end
|
312
215
|
|
216
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
217
|
+
|
313
218
|
# Fetch titles.
|
314
219
|
# @param hit_data [Hash]
|
315
220
|
# @return [Array<Hash>]
|
@@ -337,21 +242,13 @@ module RelatonIec
|
|
337
242
|
end
|
338
243
|
[{
|
339
244
|
title_intro: intro,
|
340
|
-
title_main:
|
341
|
-
title_part:
|
342
|
-
language:
|
343
|
-
script:
|
245
|
+
title_main: main,
|
246
|
+
title_part: part,
|
247
|
+
language: "en",
|
248
|
+
script: "Latn",
|
344
249
|
}]
|
345
250
|
end
|
346
|
-
|
347
|
-
# Return ISO script code.
|
348
|
-
# @param lang [String]
|
349
|
-
# @return [String]
|
350
|
-
# def script(lang)
|
351
|
-
# case lang
|
352
|
-
# when 'en', 'fr' then 'Latn'
|
353
|
-
# end
|
354
|
-
# end
|
251
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength
|
355
252
|
|
356
253
|
# Fetch dates
|
357
254
|
# @param doc [Nokogiri::HTML::Document]
|
@@ -365,6 +262,8 @@ module RelatonIec
|
|
365
262
|
dates
|
366
263
|
end
|
367
264
|
|
265
|
+
# rubocop:disable Metrics/MethodLength
|
266
|
+
|
368
267
|
def fetch_contributors(code)
|
369
268
|
code.sub(/\s.*/, "").split("/").map do |abbrev|
|
370
269
|
case abbrev
|
@@ -379,12 +278,15 @@ module RelatonIec
|
|
379
278
|
role: [type: "publisher"] }
|
380
279
|
end
|
381
280
|
end
|
281
|
+
# rubocop:enable Metrics/MethodLength
|
382
282
|
|
383
283
|
# Fetch ICS.
|
384
284
|
# @param doc [Nokogiri::HTML::Document]
|
385
285
|
# @return [Array<Hash>]
|
386
286
|
def fetch_ics(doc)
|
387
|
-
doc.xpath(
|
287
|
+
doc.xpath(
|
288
|
+
'//th[contains(text(), "ICS")]/following-sibling::td/a',
|
289
|
+
).map do |i|
|
388
290
|
code = i.text.match(/[\d\.]+/).to_s.split "."
|
389
291
|
{ field: code[0], group: code[1], subgroup: code[2] }
|
390
292
|
end
|
@@ -401,9 +303,11 @@ module RelatonIec
|
|
401
303
|
links
|
402
304
|
end
|
403
305
|
|
306
|
+
# rubocop:disable Metrics/MethodLength
|
307
|
+
|
404
308
|
# Fetch copyright.
|
405
309
|
# @param title [String]
|
406
|
-
# @return [Hash]
|
310
|
+
# @return [Array<Hash>]
|
407
311
|
def fetch_copyright(code, doc)
|
408
312
|
abbreviation = code.match(/.*?(?=\s)/).to_s
|
409
313
|
case abbreviation
|
@@ -413,11 +317,15 @@ module RelatonIec
|
|
413
317
|
end
|
414
318
|
from = code.match(/(?<=:)\d{4}/).to_s
|
415
319
|
if from.empty?
|
416
|
-
from = doc.xpath("//span[@itemprop='releaseDate']").text
|
417
|
-
|
320
|
+
from = doc.xpath("//span[@itemprop='releaseDate']").text.
|
321
|
+
match(/\d{4}/).to_s
|
418
322
|
end
|
419
|
-
{
|
323
|
+
[{
|
324
|
+
owner: [{ name: name, abbreviation: abbreviation, url: url }],
|
325
|
+
from: from,
|
326
|
+
}]
|
420
327
|
end
|
328
|
+
# rubocop:enable Metrics/MethodLength
|
421
329
|
end
|
422
330
|
end
|
423
331
|
# rubocop:enable Metrics/ModuleLength
|
data/lib/relaton_iec/version.rb
CHANGED
data/relaton_iec.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: relaton-iec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ribose Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: debase
|
@@ -168,16 +168,16 @@ dependencies:
|
|
168
168
|
name: relaton-iso-bib
|
169
169
|
requirement: !ruby/object:Gem::Requirement
|
170
170
|
requirements:
|
171
|
-
- - "
|
171
|
+
- - "~>"
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 1.0
|
173
|
+
version: 1.1.0
|
174
174
|
type: :runtime
|
175
175
|
prerelease: false
|
176
176
|
version_requirements: !ruby/object:Gem::Requirement
|
177
177
|
requirements:
|
178
|
-
- - "
|
178
|
+
- - "~>"
|
179
179
|
- !ruby/object:Gem::Version
|
180
|
-
version: 1.0
|
180
|
+
version: 1.1.0
|
181
181
|
description: 'RelatonIec: retrieve IEC Standards for bibliographic use using the IecBibliographicItem
|
182
182
|
model'
|
183
183
|
email:
|