oddb2xml 0.0.1
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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/History.txt +6 -0
- data/Manifest.txt +14 -0
- data/README.md +4 -0
- data/Rakefile +17 -0
- data/bin/oddb2xml +20 -0
- data/lib/oddb2xml/builder.rb +318 -0
- data/lib/oddb2xml/cli.rb +80 -0
- data/lib/oddb2xml/downloader.rb +94 -0
- data/lib/oddb2xml/extractor.rb +122 -0
- data/lib/oddb2xml/version.rb +3 -0
- data/lib/oddb2xml.rb +5 -0
- data/oddb2xml.gemspec +24 -0
- metadata +86 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
.gitignore
|
2
|
+
Gemfile
|
3
|
+
History.txt
|
4
|
+
Manifest.txt
|
5
|
+
README.md
|
6
|
+
Rakefile
|
7
|
+
bin/oddb2xml
|
8
|
+
lib/oddb2xml.rb
|
9
|
+
lib/oddb2xml/builder.rb
|
10
|
+
lib/oddb2xml/cli.rb
|
11
|
+
lib/oddb2xml/downloader.rb
|
12
|
+
lib/oddb2xml/extractor.rb
|
13
|
+
lib/oddb2xml/version.rb
|
14
|
+
oddb2xml.gemspec
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
|
6
|
+
# Hoe.plugin :compiler
|
7
|
+
# Hoe.plugin :gem_prelude_sucks
|
8
|
+
# Hoe.plugin :inline
|
9
|
+
# Hoe.plugin :minitest
|
10
|
+
# Hoe.plugin :racc
|
11
|
+
# Hoe.plugin :rubyforge
|
12
|
+
|
13
|
+
Hoe.spec 'oddb2xml' do
|
14
|
+
|
15
|
+
developer('Yasuhiro Asaka, Zeno R.R. Davatz', 'yasaka@ywesee.com, zdavatz@ywesee.com')
|
16
|
+
|
17
|
+
end
|
data/bin/oddb2xml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
root = Pathname.new(__FILE__).realpath.parent.parent
|
6
|
+
$:.unshift root.join('lib') if $0 == __FILE__
|
7
|
+
|
8
|
+
require 'oddb2xml'
|
9
|
+
|
10
|
+
ui = Oddb2xml::Cli.new
|
11
|
+
unless ARGV.empty?
|
12
|
+
ui.help
|
13
|
+
else
|
14
|
+
begin
|
15
|
+
ui.run
|
16
|
+
rescue Interrupt
|
17
|
+
puts
|
18
|
+
exit
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,318 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module Oddb2xml
|
6
|
+
class Builder
|
7
|
+
attr_accessor :subject, :index, :items
|
8
|
+
def initialize
|
9
|
+
@subject = nil
|
10
|
+
@index = {}
|
11
|
+
@items = {}
|
12
|
+
if block_given?
|
13
|
+
yield self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
def to_xml
|
17
|
+
if @subject
|
18
|
+
self.send('build_' + @subject)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
private
|
22
|
+
def build_product
|
23
|
+
# merge company info from swissINDEX
|
24
|
+
objects = []
|
25
|
+
objects = @items.values.uniq.map do |seq|
|
26
|
+
%w[de fr].each do |lang|
|
27
|
+
name_key = "company_name_#{lang}".intern
|
28
|
+
seq[name_key] = ''
|
29
|
+
if pharmacode = seq[:pharmacodes].first
|
30
|
+
indices = @index[lang.upcase]
|
31
|
+
if index = indices[pharmacode]
|
32
|
+
seq[name_key] = index[:company_name]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
seq
|
37
|
+
end
|
38
|
+
_builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
|
39
|
+
xml.PRODUCT(
|
40
|
+
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
|
41
|
+
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
42
|
+
'xmlns' => 'http://wiki.oddb.org/wiki.php?pagename=Swissmedic.Datendeklaration',
|
43
|
+
'CREATION_DATETIME' => Time.new.strftime('%FT%T.%7N%z'),
|
44
|
+
'PROD_DATE' => '',
|
45
|
+
'VALID_DATE' => ''
|
46
|
+
) {
|
47
|
+
objects.each do |seq|
|
48
|
+
xml.PRD('DT' => '') {
|
49
|
+
xml.PRDNO seq[:product_key] unless seq[:product_key].empty?
|
50
|
+
%w[de fr].each do |l|
|
51
|
+
name = "name_#{l}".intern
|
52
|
+
desc = "desc_#{l}".intern
|
53
|
+
elem = "DSCR" + l[0].upcase
|
54
|
+
if !seq[name].empty? and !seq[desc].empty?
|
55
|
+
xml.send(elem, seq[name] + ' ' + seq[desc])
|
56
|
+
elsif !seq[desc].empty?
|
57
|
+
xml.send(elem, seq[desc])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
#xml.BNAMD
|
61
|
+
#xml.BNAMF
|
62
|
+
#xml.ADNAMD
|
63
|
+
#xml.ADNAMF
|
64
|
+
#xml.SIZE
|
65
|
+
xml.ADINFD seq[:comment_de] unless seq[:comment_de].empty?
|
66
|
+
xml.ADINFF seq[:comment_fr] unless seq[:comment_fr].empty?
|
67
|
+
xml.GENCD seq[:org_gen_code] unless seq[:org_gen_code].empty?
|
68
|
+
#xml.GENGRP
|
69
|
+
xml.ATC seq[:atc_code] unless seq[:atc_code].empty?
|
70
|
+
xml.IT seq[:it_code] unless seq[:it_code].empty?
|
71
|
+
#xml.ITBAG
|
72
|
+
#xml.KONO
|
73
|
+
#xml.TRADE
|
74
|
+
#xml.PRTNO
|
75
|
+
#xml.MONO
|
76
|
+
#xml.CDGALD
|
77
|
+
#xml.CDGALF
|
78
|
+
#xml.FORMD
|
79
|
+
#xml.FORMF
|
80
|
+
#xml.DOSE
|
81
|
+
#xml.DOSEU
|
82
|
+
#xml.DRGFD
|
83
|
+
#xml.DRGFF
|
84
|
+
#xml.ORPH
|
85
|
+
#xml.BIOPHA
|
86
|
+
#xml.BIOSIM
|
87
|
+
#xml.BFS
|
88
|
+
#xml.BLOOD
|
89
|
+
#xml.MSCD # always empty
|
90
|
+
#xml.DEL
|
91
|
+
xml.CPT {
|
92
|
+
#xml.CPTLNO
|
93
|
+
#xml.CNAMED
|
94
|
+
#xml.CNAMEF
|
95
|
+
#xml.IDXIND
|
96
|
+
#xml.DDDD
|
97
|
+
#xml.DDDU
|
98
|
+
#xml.DDDA
|
99
|
+
#xml.IDXIA
|
100
|
+
#xml.IXREL
|
101
|
+
#xml.GALF
|
102
|
+
#xml.DRGGRPCD
|
103
|
+
#xml.PRBSUIT
|
104
|
+
#xml.CSOLV
|
105
|
+
#xml.CSOLVQ
|
106
|
+
#xml.CSOLVQU
|
107
|
+
#xml.PHVAL
|
108
|
+
#xml.LSPNSOL
|
109
|
+
#xml.APDURSOL
|
110
|
+
#xml.EXCIP
|
111
|
+
#xml.EXCIPQ
|
112
|
+
#xml.EXCIPCD
|
113
|
+
#xml.EXCIPCF
|
114
|
+
#xml.PQTY
|
115
|
+
#xml.PQTYU
|
116
|
+
#xml.SIZEMM
|
117
|
+
#xml.WEIGHT
|
118
|
+
#xml.LOOKD
|
119
|
+
#xml.LOOKF
|
120
|
+
#xml.IMG2
|
121
|
+
seq[:substances].each do |sub|
|
122
|
+
xml.CPTCMP {
|
123
|
+
xml.LINE sub[:index] unless sub[:index].empty?
|
124
|
+
#xml.SUBNO
|
125
|
+
xml.QTY sub[:quantity] unless sub[:quantity].empty?
|
126
|
+
xml.QTYU sub[:unit] unless sub[:unit].empty?
|
127
|
+
#xml.WHK
|
128
|
+
}
|
129
|
+
end
|
130
|
+
#xml.CPTIX {
|
131
|
+
#xml.IXNO
|
132
|
+
#xml.GRP
|
133
|
+
#xml.RLV
|
134
|
+
#}
|
135
|
+
#xml.CPTROA {
|
136
|
+
#xml.SYSLOC
|
137
|
+
#xml.ROA
|
138
|
+
#}
|
139
|
+
}
|
140
|
+
#xml.PRDICD { # currently empty
|
141
|
+
#xml.ICD
|
142
|
+
#xml.RTYP
|
143
|
+
#xml.RSIG
|
144
|
+
#xml.REMD
|
145
|
+
#xml.REMF
|
146
|
+
#}
|
147
|
+
}
|
148
|
+
end
|
149
|
+
xml.RESULT {
|
150
|
+
xml.OK_ERROR 'OK'
|
151
|
+
xml.NBR_RECORD objects.length.to_s
|
152
|
+
xml.ERROR_CODE ''
|
153
|
+
xml.MESSAGE ''
|
154
|
+
}
|
155
|
+
}
|
156
|
+
end
|
157
|
+
_builder.to_xml
|
158
|
+
end
|
159
|
+
def build_article
|
160
|
+
objects = [] # base is 'DE'
|
161
|
+
@index['DE'].each_pair do |pharmacode, index|
|
162
|
+
object = {
|
163
|
+
:de => index,
|
164
|
+
:fr => @index['FR'][pharmacode],
|
165
|
+
}
|
166
|
+
if seq = @items[pharmacode]
|
167
|
+
object[:seq] = seq
|
168
|
+
end
|
169
|
+
objects << object
|
170
|
+
end
|
171
|
+
_builder = Nokogiri::XML::Builder.new(:encoding => 'utf-8') do |xml|
|
172
|
+
xml.ARTICLE(
|
173
|
+
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
|
174
|
+
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
|
175
|
+
'xmlns' => 'http://wiki.oddb.org/wiki.php?pagename=Swissmedic.Datendeklaration',
|
176
|
+
'CREATION_DATETIME' => Time.new.strftime('%FT%T.%7N%z'),
|
177
|
+
'PROD_DATE' => '',
|
178
|
+
'VALID_DATE' => ''
|
179
|
+
) {
|
180
|
+
objects.each do |obj|
|
181
|
+
de_pac = obj[:de] # swiss index DE (base)
|
182
|
+
fr_pac = obj[:fr] # swiss index FR
|
183
|
+
bg_pac = nil # BAG XML (additional data)
|
184
|
+
if obj[:seq]
|
185
|
+
bg_pac = obj[:seq][:packages][de_pac[:pharmacode]]
|
186
|
+
end
|
187
|
+
xml.ART('DT' => '') {
|
188
|
+
xml.PHAR de_pac[:pharmacode] unless de_pac[:pharmacode].empty?
|
189
|
+
#xml.GRPCD
|
190
|
+
#xml.CDS01
|
191
|
+
#xml.CDS02
|
192
|
+
if obj[:seq]
|
193
|
+
xml.PRDNO obj[:seq][:product_key] unless obj[:seq][:product_key].empty?
|
194
|
+
end
|
195
|
+
if bg_pac
|
196
|
+
xml.SMCAT bg_pac[:swissmedic_category] unless bg_pac[:swissmedic_category].empty?
|
197
|
+
xml.SMNO bg_pac[:swissmedic_number] unless bg_pac[:swissmedic_number].empty?
|
198
|
+
end
|
199
|
+
#xml.HOSPCD
|
200
|
+
#xml.CLINCD
|
201
|
+
#xml.ARTTYP
|
202
|
+
#xml.VAT
|
203
|
+
#xml.SALECD
|
204
|
+
if bg_pac
|
205
|
+
#xml.INSLIM
|
206
|
+
xml.LIMPTS bg_pac[:limitation_points] unless bg_pac[:limitation_points].empty?
|
207
|
+
end
|
208
|
+
#xml.GRDFR
|
209
|
+
#xml.COOL
|
210
|
+
#xml.TEMP
|
211
|
+
#xml.CDBG
|
212
|
+
#xml.BG
|
213
|
+
#xml.EXP
|
214
|
+
xml.QTY de_pac[:additional_desc] unless de_pac[:additional_desc].empty?
|
215
|
+
xml.DSCRD de_pac[:desc] unless de_pac[:desc].empty?
|
216
|
+
xml.DSCRF fr_pac[:desc] unless fr_pac[:desc].empty?
|
217
|
+
xml.SORTD de_pac[:desc].upcase unless de_pac[:desc].empty?
|
218
|
+
xml.SORTF fr_pac[:desc].upcase unless fr_pac[:desc].empty?
|
219
|
+
#xml.QTYUD
|
220
|
+
#xml.QTYUF
|
221
|
+
#xml.IMG
|
222
|
+
#xml.IMG2
|
223
|
+
#xml.PCKTYPD
|
224
|
+
#xml.PCKTYPF
|
225
|
+
#xml.MULT
|
226
|
+
if obj[:seq]
|
227
|
+
xml.SYN1D obj[:seq][:name_de] unless obj[:seq][:name_de].empty?
|
228
|
+
xml.SYN1F obj[:seq][:name_fr] unless obj[:seq][:name_fr].empty?
|
229
|
+
end
|
230
|
+
#xml.SLOPLUS
|
231
|
+
#xml.NOPCS
|
232
|
+
#xml.HSCD
|
233
|
+
#xml.MINI
|
234
|
+
#xml.DEPCD
|
235
|
+
#xml.DEPOT
|
236
|
+
#xml.BAGSL
|
237
|
+
#xml.BAGSLC
|
238
|
+
#xml.LOACD
|
239
|
+
if de_pac[:status] == "I"
|
240
|
+
xml.OUTSAL de_pac[:stat_date] unless de_pac[:stat_date].empty?
|
241
|
+
end
|
242
|
+
#xml.STTOX
|
243
|
+
#xml.NOTI
|
244
|
+
#xml.GGL
|
245
|
+
#xml.CE
|
246
|
+
#xml.SMDAT
|
247
|
+
#xml.SMCDAT
|
248
|
+
#xml.SIST
|
249
|
+
#xml.ESIST
|
250
|
+
#xml.BIOCID
|
251
|
+
#xml.BAGNO
|
252
|
+
#xml.LIGHT
|
253
|
+
#xml.DEL
|
254
|
+
xml.ARTCOMP {
|
255
|
+
# use ean13(gln) as COMPNO
|
256
|
+
xml.COMPNO de_pac[:company_ean] unless de_pac[:company_ean].empty?
|
257
|
+
#xml.ROLE
|
258
|
+
#xml.ARTNO1
|
259
|
+
#xml.ARTNO2
|
260
|
+
#xml.ARTNO3
|
261
|
+
}
|
262
|
+
xml.ARTBAR {
|
263
|
+
xml.CDTYP 'E13'
|
264
|
+
xml.BC de_pac[:ean] unless de_pac[:ean].empty?
|
265
|
+
xml.BCSTAT 'A' # P is alternative
|
266
|
+
#xml.PHAR2
|
267
|
+
}
|
268
|
+
#xml.ARTCH {
|
269
|
+
#xml.PHAR2
|
270
|
+
#xml.CHTYPE
|
271
|
+
#xml.LINENO
|
272
|
+
#xml.NOUNITS
|
273
|
+
#}
|
274
|
+
if bg_pac
|
275
|
+
bg_pac[:prices].each_pair do |key, price|
|
276
|
+
xml.ARTPRI {
|
277
|
+
xml.VDAT price[:valid_date] unless price[:valid_date].empty?
|
278
|
+
xml.PTYP price[:price_code] unless price[:price_code].empty?
|
279
|
+
xml.PRICE price[:price] unless price[:price].empty?
|
280
|
+
}
|
281
|
+
end
|
282
|
+
end
|
283
|
+
#xml.ARTMIG {
|
284
|
+
#xml.VDAT
|
285
|
+
#xml.MIGCD
|
286
|
+
#xml.LINENO
|
287
|
+
#}
|
288
|
+
#xml.ARTDAN {
|
289
|
+
#xml.CDTYP
|
290
|
+
#xml.LINENO
|
291
|
+
#xml.CDVAL
|
292
|
+
#}
|
293
|
+
if bg_pac
|
294
|
+
bg_pac[:limitations].each do |lim|
|
295
|
+
xml.ARTLIM {
|
296
|
+
xml.LIMCD lim[:code] unless lim[:code].empty?
|
297
|
+
}
|
298
|
+
end
|
299
|
+
end
|
300
|
+
#xml.ARTINS {
|
301
|
+
#xml.VDAT
|
302
|
+
#xml.INCD
|
303
|
+
#xml.NINCD
|
304
|
+
#}
|
305
|
+
}
|
306
|
+
end
|
307
|
+
xml.RESULT {
|
308
|
+
xml.OK_ERROR 'OK'
|
309
|
+
xml.NBR_RECORD objects.length.to_s
|
310
|
+
xml.ERROR_CODE ''
|
311
|
+
xml.MESSAGE ''
|
312
|
+
}
|
313
|
+
}
|
314
|
+
end
|
315
|
+
_builder.to_xml
|
316
|
+
end
|
317
|
+
end
|
318
|
+
end
|
data/lib/oddb2xml/cli.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'thread'
|
4
|
+
require 'oddb2xml/builder'
|
5
|
+
require 'oddb2xml/downloader'
|
6
|
+
require 'oddb2xml/extractor'
|
7
|
+
|
8
|
+
module Oddb2xml
|
9
|
+
class Cli
|
10
|
+
SUBJECTS = %w[product article]
|
11
|
+
LANGUAGES = %w[DE FR] # EN does not exist
|
12
|
+
def initialize
|
13
|
+
#@mutex = Mutex.new
|
14
|
+
@items = {} # Preparations.xml in BAG
|
15
|
+
@index = {}
|
16
|
+
LANGUAGES.each do |lang|
|
17
|
+
@index[lang] = {} # swissINDEX
|
18
|
+
end
|
19
|
+
end
|
20
|
+
def help
|
21
|
+
puts <<EOS
|
22
|
+
#$0 ver.#{Oddb2xml::VERSION}
|
23
|
+
Usage:
|
24
|
+
oddb2xml
|
25
|
+
EOS
|
26
|
+
end
|
27
|
+
def run
|
28
|
+
# Sometimes nokogiri crashes with ruby in Threads.
|
29
|
+
#threads = []
|
30
|
+
# bag_xml
|
31
|
+
#threads << Thread.new do
|
32
|
+
downloader = BagXmlDownloader.new
|
33
|
+
xml = downloader.download
|
34
|
+
extractor = BagXmlExtractor.new(xml)
|
35
|
+
@items = extractor.to_hash
|
36
|
+
#end
|
37
|
+
LANGUAGES.map do |lang|
|
38
|
+
# swissindex
|
39
|
+
#threads << Thread.new do
|
40
|
+
downloader = SwissIndexDownloader.new
|
41
|
+
xml = downloader.download_by(lang)
|
42
|
+
extractor = SwissIndexExtractor.new(xml)
|
43
|
+
index = extractor.to_hash
|
44
|
+
#@mutex.synchronize do
|
45
|
+
@index["#{lang}"] = index
|
46
|
+
#end
|
47
|
+
#end
|
48
|
+
end
|
49
|
+
#threads.map(&:join)
|
50
|
+
build
|
51
|
+
report
|
52
|
+
end
|
53
|
+
private
|
54
|
+
def build
|
55
|
+
files = {}
|
56
|
+
SUBJECTS.each{ |sbj| files[sbj] = "oddb_#{sbj}.xml" }
|
57
|
+
begin
|
58
|
+
files.each_pair do |sbj, file|
|
59
|
+
builder = Builder.new do |builder|
|
60
|
+
builder.subject = sbj
|
61
|
+
builder.index = @index
|
62
|
+
builder.items = @items
|
63
|
+
end
|
64
|
+
xml = builder.to_xml
|
65
|
+
File.open(file, 'w:utf-8'){ |fh| fh << xml }
|
66
|
+
end
|
67
|
+
rescue Interrupt
|
68
|
+
files.values.each do |file|
|
69
|
+
if File.exist? file
|
70
|
+
File.unlink file
|
71
|
+
end
|
72
|
+
end
|
73
|
+
raise Interrupt
|
74
|
+
end
|
75
|
+
end
|
76
|
+
def report
|
77
|
+
# pass
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'mechanize'
|
4
|
+
require 'zip/zip'
|
5
|
+
require 'savon'
|
6
|
+
|
7
|
+
module Oddb2xml
|
8
|
+
class Downloader
|
9
|
+
def initialize(url=nil)
|
10
|
+
@url = url
|
11
|
+
@retry_times = 3
|
12
|
+
HTTPI.log = false # disable httpi warning
|
13
|
+
init
|
14
|
+
end
|
15
|
+
def init
|
16
|
+
# pass
|
17
|
+
end
|
18
|
+
protected
|
19
|
+
def retrievable?
|
20
|
+
if @retry_times > 0
|
21
|
+
sleep 5
|
22
|
+
@retry_times -= 1
|
23
|
+
true
|
24
|
+
else
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
class BagXmlDownloader < Downloader
|
30
|
+
def init
|
31
|
+
@url ||= 'http://bag.e-mediat.net/SL2007.Web.External/File.axd?file=XMLPublications.zip'
|
32
|
+
end
|
33
|
+
def download
|
34
|
+
file = 'XMLPublications.zip'
|
35
|
+
begin
|
36
|
+
response = Mechanize.new.get(@url)
|
37
|
+
response.save_as file
|
38
|
+
xml = ''
|
39
|
+
Zip::ZipFile.foreach(file) do |entry|
|
40
|
+
if entry.name =~ /^Preparation/iu
|
41
|
+
entry.get_input_stream{ |io| xml = io.read }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
return xml
|
45
|
+
rescue Timeout::Error
|
46
|
+
retrievable? ? retry : raise
|
47
|
+
ensure
|
48
|
+
if File.exists? file
|
49
|
+
File.unlink file
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
class SwissIndexDownloader < Downloader
|
55
|
+
def init
|
56
|
+
@url ||= 'https://index.ws.e-mediat.net/Swissindex/Pharma/ws_Pharma_V101.asmx?WSDL'
|
57
|
+
Savon.configure do |config|
|
58
|
+
config.log_level = :info
|
59
|
+
config.log = false # $stdout
|
60
|
+
config.raise_errors = true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
def download_by(lang = 'DE')
|
64
|
+
client = Savon::Client.new do |wsdl, http|
|
65
|
+
http.auth.ssl.verify_mode = :none
|
66
|
+
wsdl.document = @url
|
67
|
+
end
|
68
|
+
begin
|
69
|
+
response = client.request :download_all do
|
70
|
+
soap.xml = <<XML
|
71
|
+
<?xml version="1.0" encoding="utf-8"?>
|
72
|
+
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
|
73
|
+
<soap:Body>
|
74
|
+
<lang xmlns="http://swissindex.e-mediat.net/SwissindexPharma_out_V101">#{lang}</lang>
|
75
|
+
</soap:Body>
|
76
|
+
</soap:Envelope>
|
77
|
+
XML
|
78
|
+
end
|
79
|
+
if response.success?
|
80
|
+
if xml = response.to_xml
|
81
|
+
return xml
|
82
|
+
else
|
83
|
+
# received broken data or internal error
|
84
|
+
raise StandardError
|
85
|
+
end
|
86
|
+
else
|
87
|
+
raise Timeout::Error
|
88
|
+
end
|
89
|
+
rescue Timeout::Error
|
90
|
+
retrievable? ? retry : raise
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module Oddb2xml
|
6
|
+
class Extractor
|
7
|
+
attr_accessor :xml
|
8
|
+
def initialize(xml)
|
9
|
+
@xml = xml
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class BagXmlExtractor < Extractor
|
13
|
+
def to_hash
|
14
|
+
#File.open('../bagxml.xml', 'r:ASCII-8BIT') do |f|
|
15
|
+
# @xml = f.read
|
16
|
+
#end
|
17
|
+
# pharmacode => sequence
|
18
|
+
data = {}
|
19
|
+
doc = Nokogiri::XML(@xml)
|
20
|
+
doc.xpath('//Preparation').each do |seq|
|
21
|
+
item = {}
|
22
|
+
item[:product_key] = seq.attr('ProductCommercial').to_s
|
23
|
+
item[:desc_de] = (desc = seq.at_xpath('.//DescriptionDe')) ? desc.text : ''
|
24
|
+
item[:desc_fr] = (desc = seq.at_xpath('.//DescriptionFr')) ? desc.text : ''
|
25
|
+
item[:name_de] = (name = seq.at_xpath('.//NameDe')) ? name.text : ''
|
26
|
+
item[:name_fr] = (name = seq.at_xpath('.//NameFr')) ? name.text : ''
|
27
|
+
item[:org_gen_code] = (orgc = seq.at_xpath('.//OrgGenCode')) ? orgc.text : ''
|
28
|
+
item[:atc_code] = (orgc = seq.at_xpath('.//AtcCode')) ? orgc.text : ''
|
29
|
+
item[:comment_de] = (info = seq.at_xpath('.//CommentDe')) ? info.text : ''
|
30
|
+
item[:comment_fr] = (info = seq.at_xpath('.//CommentFr')) ? info.text : ''
|
31
|
+
item[:it_code] = ''
|
32
|
+
seq.xpath('.//ItCode').each do |itc|
|
33
|
+
if item[:it_code].to_s.empty?
|
34
|
+
it_code = itc.attr('Code').to_s
|
35
|
+
item[:it_code] = (it_code =~ /(\d+)\.(\d+)\.(\d+)./) ? it_code : ''
|
36
|
+
end
|
37
|
+
end
|
38
|
+
item[:substances] = []
|
39
|
+
seq.xpath('.//Substance').each_with_index do |sub, i|
|
40
|
+
item[:substances] << {
|
41
|
+
:index => i.to_s,
|
42
|
+
:quantity => (qtty = sub.at_xpath('.//Quantity')) ? qtty.text : '',
|
43
|
+
:unit => (unit = sub.at_xpath('.//QuantityUnit')) ? unit.text : '',
|
44
|
+
}
|
45
|
+
end
|
46
|
+
item[:pharmacodes] = []
|
47
|
+
item[:packages] = {} # pharmacode => package
|
48
|
+
seq.xpath('.//Pack').each do |pac|
|
49
|
+
if phar = pac.attr('Pharmacode')
|
50
|
+
phar = phar.to_s
|
51
|
+
# as common key with swissINDEX
|
52
|
+
item[:pharmacodes] << phar
|
53
|
+
# packages
|
54
|
+
item[:packages][phar] = {
|
55
|
+
:pharmacode => phar,
|
56
|
+
:swissmedic_category => (cat = pac.at_xpath('.//SwissmedicCategory')) ? cat.text : '',
|
57
|
+
:swissmedic_number => (num = pac.at_xpath('.//SwissmedicNo8')) ? num.text : '',
|
58
|
+
:narcosis_flag => (flg = pac.at_xpath('.//FlagNarcosis')) ? flg.text : '',
|
59
|
+
:prices => {
|
60
|
+
:exf_price => {
|
61
|
+
:price => (exf = pac.at_xpath('.//ExFactoryPrice/Price')) ? exf.text : '',
|
62
|
+
:valid_date => (exf = pac.at_xpath('.//ExFactoryPrice/ValidFromDate')) ? exf.text : '',
|
63
|
+
:price_code => (exf = pac.at_xpath('.//ExFactoryPrice/PriceTypeCode')) ? exf.text : '',
|
64
|
+
},
|
65
|
+
:pub_price => {
|
66
|
+
:price => (pub = pac.at_xpath('.//PublicPrice/Price')) ? pub.text : '',
|
67
|
+
:valid_date => (pub = pac.at_xpath('.//PublicPrice/ValidFromDate')) ? pub.text : '',
|
68
|
+
:price_code => (pub = pac.at_xpath('.//PublicPrice/PriceTypeCode')) ? pub.text : '',
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
72
|
+
# limitation
|
73
|
+
item[:packages][phar][:limitations] = []
|
74
|
+
pac.xpath('.//Limitation').each do |lim|
|
75
|
+
item[:packages][phar][:limitations] << {
|
76
|
+
:code => (lic = lim.at_xpath('.//LimitationCode')) ? lic.text : '',
|
77
|
+
:type => (lit = lim.at_xpath('.//LimitationType')) ? lit.text : '',
|
78
|
+
}
|
79
|
+
end
|
80
|
+
# limitation points
|
81
|
+
pts = pac.at_xpath('.//PointLimitations/PointLimitation/Points') # only first points
|
82
|
+
item[:packages][phar][:limitation_points] = pts ? pts.text : ''
|
83
|
+
# pharmacode => seq (same data)
|
84
|
+
data[phar] = item
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
data
|
89
|
+
end
|
90
|
+
end
|
91
|
+
class SwissIndexExtractor < Extractor
|
92
|
+
def to_hash
|
93
|
+
#File.open('../swissindex.xml', 'r:ASCII-8BIT') do |f|
|
94
|
+
# @xml = f.read
|
95
|
+
#end
|
96
|
+
# pharmacode => package
|
97
|
+
data = {}
|
98
|
+
doc = Nokogiri::XML(@xml)
|
99
|
+
doc.remove_namespaces!
|
100
|
+
doc.xpath('//Envelope/Body/PHARMA/ITEM').each do |pac|
|
101
|
+
item = {}
|
102
|
+
item[:ean] = (gtin = pac.at_xpath('.//GTIN')) ? gtin.text : ''
|
103
|
+
item[:pharmacode] = (phar = pac.at_xpath('.//PHAR')) ? phar.text : ''
|
104
|
+
item[:status] = (stat = pac.at_xpath('.//STATUS')) ? stat.text : ''
|
105
|
+
item[:stat_date] = (date = pac.at_xpath('.//SDATE')) ? date.text : ''
|
106
|
+
item[:lang] = (lang = pac.at_xpath('.//LANG')) ? lang.text : ''
|
107
|
+
item[:desc] = (dscr = pac.at_xpath('.//DSCR')) ? dscr.text : ''
|
108
|
+
item[:atc_code] = (code = pac.at_xpath('.//ATC')) ? code.text : ''
|
109
|
+
# as quantity text
|
110
|
+
item[:additional_desc] = (dscr = pac.at_xpath('.//ADDSCR')) ? dscr.text : ''
|
111
|
+
if comp = pac.xpath('.//COMP')
|
112
|
+
item[:company_name] = (nam = comp.at_xpath('.//NAME')) ? nam.text : ''
|
113
|
+
item[:company_ean] = (gln = comp.at_xpath('.//GLN')) ? gln.text : ''
|
114
|
+
end
|
115
|
+
unless item[:pharmacode].empty?
|
116
|
+
data[item[:pharmacode]] = item
|
117
|
+
end
|
118
|
+
end
|
119
|
+
data
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/lib/oddb2xml.rb
ADDED
data/oddb2xml.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'oddb2xml/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "oddb2xml"
|
8
|
+
gem.version = Oddb2xml::VERSION
|
9
|
+
gem.authors = [""]
|
10
|
+
gem.email = [""]
|
11
|
+
gem.description = %q{TODO: Write a gem description}
|
12
|
+
gem.summary = %q{TODO: Write a gem summary}
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency 'rubyzip'
|
21
|
+
gem.add_dependency 'mechanize'
|
22
|
+
gem.add_dependency 'nokogiri'
|
23
|
+
gem.add_dependency 'savon'
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oddb2xml
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Yasuhiro Asaka, Zeno R.R. Davatz
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-17 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rdoc
|
16
|
+
requirement: &8627820 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.10'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *8627820
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
requirement: &8627320 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.13'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *8627320
|
36
|
+
description: ''
|
37
|
+
email:
|
38
|
+
- yasaka@ywesee.com, zdavatz@ywesee.com
|
39
|
+
executables:
|
40
|
+
- oddb2xml
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files:
|
43
|
+
- History.txt
|
44
|
+
- Manifest.txt
|
45
|
+
files:
|
46
|
+
- .gitignore
|
47
|
+
- Gemfile
|
48
|
+
- History.txt
|
49
|
+
- Manifest.txt
|
50
|
+
- README.md
|
51
|
+
- Rakefile
|
52
|
+
- bin/oddb2xml
|
53
|
+
- lib/oddb2xml.rb
|
54
|
+
- lib/oddb2xml/builder.rb
|
55
|
+
- lib/oddb2xml/cli.rb
|
56
|
+
- lib/oddb2xml/downloader.rb
|
57
|
+
- lib/oddb2xml/extractor.rb
|
58
|
+
- lib/oddb2xml/version.rb
|
59
|
+
- oddb2xml.gemspec
|
60
|
+
homepage:
|
61
|
+
licenses: []
|
62
|
+
post_install_message:
|
63
|
+
rdoc_options:
|
64
|
+
- --main
|
65
|
+
- README.txt
|
66
|
+
require_paths:
|
67
|
+
- lib
|
68
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
69
|
+
none: false
|
70
|
+
requirements:
|
71
|
+
- - ! '>='
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0'
|
74
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
requirements: []
|
81
|
+
rubyforge_project: oddb2xml
|
82
|
+
rubygems_version: 1.8.15
|
83
|
+
signing_key:
|
84
|
+
specification_version: 3
|
85
|
+
summary: ''
|
86
|
+
test_files: []
|