elsevier_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2d54cf0dc5287b82d77c1eb3bfaa84aa274535f7ede5e168e8d3766dda3de4be
4
+ data.tar.gz: 591553769d5a31753c3d1a8ef4d3b24a2d8737ef178d5efdf0cde251264d0518
5
+ SHA512:
6
+ metadata.gz: 7359e8f97afc750f9b703206d41a468530c2249856c45783bb9d239158cdcaaca82ffbb4ae553c223934b529b74d7d9366c5655cd46dbea3f0a1f0388d5dad98
7
+ data.tar.gz: bc767d36f271fd430d5221e7163989fc9f8e36084823a302ccec36ed1bb8902c49d6a5cc8c9ff5544d6591b5283cf7b36d2e98e189d8dea1beb27d5ca1ad2924
data/.idea/vcs.xml ADDED
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org' do
2
+
3
+ # Specify your gem's dependencies in scopus.gemspec
4
+ gem 'bundler'
5
+ gem 'nokogiri'
6
+ gem 'rspec'
7
+ gem 'openssl', '~>2.1.2'
8
+ gem 'simplecov', require: false, group: :test
9
+ gem 'rake'
10
+ gem 'curb'
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,43 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ curb (0.9.10)
5
+ diff-lcs (1.3)
6
+ docile (1.3.2)
7
+ mini_portile2 (2.4.0)
8
+ nokogiri (1.10.8)
9
+ mini_portile2 (~> 2.4.0)
10
+ openssl (2.1.2)
11
+ rake (13.0.1)
12
+ rspec (3.9.0)
13
+ rspec-core (~> 3.9.0)
14
+ rspec-expectations (~> 3.9.0)
15
+ rspec-mocks (~> 3.9.0)
16
+ rspec-core (3.9.1)
17
+ rspec-support (~> 3.9.1)
18
+ rspec-expectations (3.9.0)
19
+ diff-lcs (>= 1.2.0, < 2.0)
20
+ rspec-support (~> 3.9.0)
21
+ rspec-mocks (3.9.1)
22
+ diff-lcs (>= 1.2.0, < 2.0)
23
+ rspec-support (~> 3.9.0)
24
+ rspec-support (3.9.2)
25
+ simplecov (0.18.2)
26
+ docile (~> 1.1)
27
+ simplecov-html (~> 0.11)
28
+ simplecov-html (0.12.0)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ bundler!
35
+ curb!
36
+ nokogiri!
37
+ openssl (~> 2.1.2)!
38
+ rake!
39
+ rspec!
40
+ simplecov!
41
+
42
+ BUNDLED WITH
43
+ 2.1.4
data/LICENSE ADDED
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2016-2020, Claudio Bustos Navarrete
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ * Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ * Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ * Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # elsevier_api
2
+
3
+ Provides access to Elsevier dev services for Ruby. You require an API from https://dev.elsevier.com/apikey/ first.
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'elsevier_api'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install elservier_api
21
+
22
+ ## Usage
23
+
24
+ First, you should create a connection to Elsevier server using your Elsevier API key
25
+ ```ruby
26
+ require 'elsevier_api'
27
+ @conn=ElsevierApi::Connection.new(api_key)
28
+ ```
29
+
30
+ If you need to use a proxy, just add the information after the key.
31
+ ```ruby
32
+ @conn=ElsevierApi::Connection.new(api_key,
33
+ proxy_host: proxy_host,
34
+
35
+ proxy_port: proxy_port,
36
+ proxy_user: proxy_user,
37
+ proxy_pass: proxy_password
38
+ )
39
+ ```
40
+
41
+ The basic method is *retrieve_response*, that requires an URI and retrieves a parsed response. ElsevierApi retrieves the XML responde from Elsevier, and parse it using a class of type ElsevierApi::XMLResponse based on the first node of XML.
42
+
43
+ For example, we could retrieve the information about the developer of this gem
44
+
45
+ ```ruby
46
+
47
+ info = @conn.retrieve_response("https://api.elsevier.com/content/author?author_id=56609918400")
48
+ info.class
49
+ => ElsevierApi::XMLResponse::Authorretrievalresponse
50
+ ```
51
+
52
+ We could operate directly on the XML
53
+
54
+ ```ruby
55
+ info.xml.xpath("//document-count").text
56
+ => 26
57
+ ```
58
+
59
+ A more interesting XMLResponse object is provided if we use a search
60
+
61
+ ```ruby
62
+ query_encoded=URI::encode("(ruby language) and api")
63
+
64
+ search = @conn.retrieve_response("https://api.elsevier.com/content/search/scopus?query=#{query_encoded}&count=2")
65
+ search.class
66
+ => ElsevierApi::XMLResponse::Searchresults
67
+
68
+ search.entries_to_ary
69
+ => [{:scopus_id=>"SCOPUS_ID:85077509321",
70
+ :title=>"Energy-Delay investigation of Remote Inter-Process communication technologies",
71
+ :journal=>"Journal of Systems and Software",
72
+ :creator=>"Georgiou S.",
73
+ :doi=>"10.1016/j.jss.2019.110506"},
74
+ {:scopus_id=>"SCOPUS_ID:85079458224",
75
+ :title=>"A mechanized formalization of GraphQL",
76
+ :journal=>
77
+ "CPP 2020 - Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs, co-located with POPL 2020",
78
+ :creator=>"Diaz T.",
79
+ :doi=>"10.1145/3372885.3373822"}]
80
+
81
+ ```
82
+
83
+ The most complete parsing procedure was developed for abstracts, to retrieve complete information about authors and affiliations.
84
+
85
+ ```ruby
86
+ abstract = @conn.retrieve_response("https://api.elsevier.com/content/abstract/scopus_id/85079458224")
87
+ => #<ElsevierApi::XMLResponse::Abstractsretrievalresponse:27496700 @title=A mechanized formalization of GraphQL @journal=CPP 2020 - Proceedings of the 9th ACM SIGPLAN International Conference on Certified Programs and Proofs, co-located with POPL 2020 @authors=[56940212100,35174987700,13104010300]>
88
+
89
+ abstract.scopus_id
90
+ => "SCOPUS_ID:85079458224"
91
+
92
+ abstract.authors.first
93
+ => ["56940212100",
94
+ {:auid=>"56940212100",
95
+ :seq=>"1",
96
+ :initials=>"T.",
97
+ :indexed_name=>"Diaz T.",
98
+ :given_name=>"Tomas",
99
+ :surname=>"Diaz",
100
+ :email=>nil,
101
+ :affiliation=>"123888358"}]
102
+
103
+ abstract.affiliations
104
+ => {"60012464"=>
105
+ {:id=>"60012464",
106
+ :name=>"Universidad de Chile",
107
+ :city=>"Santiago",
108
+ :country=>"Chile",
109
+ :type=>:scopus},
110
+ "123888358"=>
111
+ {:id=>"123888358", :name=>"IMFD Chile", :city=>"", :country=>"Chile", :type=>:scopus},
112
+ "123888173"=>
113
+ {:id=>"123888173",
114
+ :name=>"U. of Chile and IMFD Chile and Inria Paris",
115
+ :city=>"Paris",
116
+ :country=>"France",
117
+ :type=>:scopus}}
118
+ ```
119
+
120
+ Some methods to create URIs for Elsevier API are located in ElsevierApi::URIRequest module, that is included on connection.
121
+
122
+
123
+ ## Development
124
+
125
+ After checking out the repository, use
126
+
127
+ $ bundle install
128
+
129
+ to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
130
+
131
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
132
+
133
+ ## Contributing
134
+
135
+ Bug reports and pull requests are welcome on GitHub at https://github.com/clbustos/elsevier-api.
136
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require_relative "../lib/elsevier_api"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,24 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'elsevier_api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "elsevier_api"
8
+ spec.version = ElsevierApi::VERSION
9
+ spec.authors = ["Claudio Bustos"]
10
+ spec.email = ["clbustos@gmail.com"]
11
+
12
+ spec.summary = %q{Ruby gem to interact with Elsevier's APIs}
13
+ spec.description = %q{A Ruby gem for use with Elsevier's APIs: Scopus, ScienceDirect, others. }
14
+ spec.homepage = "https://github.com/clbustos/elsevier_api"
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
+ spec.bindir = "exe"
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.require_paths = ["lib"]
19
+ spec.licenses = ['BSD-3-Clause']
20
+ spec.add_development_dependency "bundler", "~> 1.12"
21
+ spec.add_development_dependency "rspec", "~> 3.0"
22
+ spec.add_development_dependency "nokogiri", "~> 1.6"
23
+
24
+ end
@@ -0,0 +1,147 @@
1
+ # Copyright (c) 2016-2020, Claudio Bustos Navarrete
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of the copyright holder nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ require 'uri'
29
+ require 'net/http'
30
+ require 'curb'
31
+ module ElsevierApi
32
+ class Connection
33
+ extend ElsevierApi::URIRequest
34
+ include ElsevierApi::URIRequest
35
+ attr_reader :key, :error, :error_msg, :xml_response, :raw_xml
36
+ attr_accessor :use_proxy
37
+ attr_accessor :proxy_host, :proxy_post, :proxy_user, :proxy_pass
38
+ def initialize(key, opts={})
39
+ @key=key
40
+ @use_proxy=false
41
+ @error=false
42
+ @error_msg=nil
43
+ if opts[:proxy_host]
44
+ @use_proxy=true
45
+ @proxy_host=opts[:proxy_host]
46
+ @proxy_port=opts[:proxy_port]
47
+ @proxy_user=opts[:proxy_user]
48
+ @proxy_pass=opts[:proxy_pass]
49
+ end
50
+ end
51
+ def connection
52
+ @connection||=get_connection
53
+ end
54
+ def close
55
+ @connection.close if @connection
56
+ end
57
+
58
+ # Connect to api and retrieve a response based on URI
59
+ def retrieve_response(uri_string)
60
+ @xml_response=nil
61
+ begin
62
+ Curl::Easy.new(uri_string) do |curl|
63
+ if @use_proxy
64
+ curl.proxy_tunnel = true
65
+ curl.proxy_url = "http://#{@proxy_host}:#{@proxy_port}/"
66
+ curl.proxypwd = "#{@proxy_user}:#{proxy_pass}"
67
+ end
68
+ curl.follow_location = true
69
+ curl.ssl_verify_peer = false
70
+ curl.max_redirects = 3
71
+ curl.headers=['Accept: application/xml', "X-ELS-APIKey: #{@key}"]
72
+ curl.perform
73
+ #p curl.body_str
74
+ xml=Nokogiri::XML(curl.body_str)
75
+ if xml.xpath("//service-error").length>0
76
+ @error=true
77
+ @error_msg=xml.xpath("//statusText").text
78
+ elsif xml.xpath("//atom:error",'atom'=>'http://www.w3.org/2005/Atom').length>0
79
+ @error=true
80
+ @error_msg=xml.xpath("//atom:error").text
81
+ elsif xml.children.length==0
82
+ @error=true
83
+ @error_msg="Empty_XML"
84
+ else
85
+ @error=false
86
+ @error_msg=nil
87
+ end
88
+ @xml_response=ElsevierApi.process_xml(xml)
89
+ end
90
+ rescue Exception=>e
91
+ #$log.info(e.message)
92
+ @error=true
93
+ @error_msg=e.message
94
+ end
95
+
96
+ @xml_response
97
+
98
+ end
99
+
100
+ def get_articles_from_uri(uri)
101
+ completo=false
102
+ acumulado=[]
103
+ pagina=1
104
+ until completo do
105
+ #puts "Page:#{pagina}"
106
+ xml_response=retrieve_response(uri)
107
+ if @error
108
+ break
109
+ else
110
+ acumulado=acumulado+xml_response.entries_to_hash
111
+ next_page=xml_response.next_page
112
+ if next_page
113
+ pagina+=1
114
+ uri=next_page.attribute("href").value
115
+ else
116
+ # puts "completo"
117
+ completo=true
118
+ end
119
+ end
120
+ end
121
+ acumulado
122
+ end
123
+
124
+ def get_journal_articles(journal,year=nil)
125
+ uri=get_uri_journal_articles(journal,year)
126
+ completo=false
127
+ acumulado=[]
128
+ until completo do
129
+ xml_response=retrieve_response(uri)
130
+ if @error
131
+ break
132
+ else
133
+ acumulado=acumulado+xml_response.entries_to_ary
134
+ next_page=xml_response.next_page
135
+ if next_page
136
+ uri=next_page.attribute("href").value
137
+ #puts "siguiente pagina"
138
+ else
139
+ #puts "completo"
140
+ completo=true
141
+ end
142
+ end
143
+ end
144
+ acumulado
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,73 @@
1
+ # Copyright (c) 2016-2020, Claudio Bustos Navarrete
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of the copyright holder nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ module ElsevierApi
29
+ module URIRequest
30
+
31
+ def get_uri_author(author_id,view=:light,opts={})
32
+ if author_id.is_a? (Array)
33
+ author_id=author_id.join(",")
34
+ end
35
+ opts={:view=>view.to_s.upcase}.merge(opts)
36
+ opts_s=opts.map {|v| "#{v[0].to_s}=#{v[1]}"}.join("&")
37
+ res=::URI.encode("https://api.elsevier.com/content/author?author_id=#{author_id}&#{opts_s}")
38
+ res
39
+ end
40
+ def get_uri_citation_overview(scopus_id,date,opts={})
41
+ if scopus_id.is_a? (Array)
42
+ scopus_id=scopus_id.join(",")
43
+ end
44
+ opts={:date=>date,:field=>"h-index,dc:identifier,scopus_id,pcc,cc,lcc,rangeCount,rowTotal,sort-year,prevColumnHeading,columnHeading,laterColumnHeading,prevColumnTotal,columnTotal,laterColumnTotal,rangeColumnTotal,grandTotal"}.merge(opts)
45
+ opts_s=opts.map {|v| "#{v[0].to_s}=#{v[1]}"}.join("&")
46
+ res=::URI.encode("https://api.elsevier.com/content/abstract/citations?scopus_id=#{scopus_id}&#{opts_s}")
47
+
48
+ res
49
+ end
50
+
51
+ def get_uri_articles_country_year_area(country,year,area)
52
+ query="AFFILCOUNTRY ( #{country} ) AND PUBYEAR = #{year} AND SUBJAREA ( \"#{area}\" )"
53
+ ::URI.encode("https://api.elsevier.com/content/search/scopus?sort=artnum&query=#{query}")
54
+ end
55
+ # Get URI to obtain list of articles from a specific
56
+ # journal. You could specify year
57
+ def get_uri_journal_articles(journal,year=nil)
58
+ query="EXACTSRCTITLE(\"#{journal}\")"
59
+ query+=" AND PUBYEAR IS #{year}" if year
60
+ ::URI.encode("https://api.elsevier.com/content/search/scopus?apiKey=#{key}&query=#{query}")
61
+ end
62
+ def get_uri_abstract(id,type="scopus_id",opts={:view=>"FULL"})
63
+ raise "Type should be a string" unless type.is_a? String
64
+ if opts[:view]
65
+ opts_s="view=#{opts[:view]}"
66
+ elsif opts[:field]
67
+ opts_s="field=#{opts[:field]}"
68
+ end
69
+ ::URI.encode("https://api.elsevier.com/content/abstract/#{type}/#{id}?#{opts_s}")
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,3 @@
1
+ module ElsevierApi
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,97 @@
1
+ # Copyright (c) 2016-2020, Claudio Bustos Navarrete
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of the copyright holder nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ module ElsevierApi
29
+ module XMLResponse
30
+
31
+ class ElsevierApi::XMLResponse::Abstractcitationsresponse < XMLResponseGeneric
32
+ attr_reader :h_index # How many records are in the xml
33
+ attr_reader :year_range
34
+ attr_reader :prev_total
35
+ attr_reader :later_total
36
+ attr_reader :column_total
37
+ attr_reader :range_total
38
+ attr_reader :grand_total
39
+ attr_reader :records
40
+ attr_reader :n_records
41
+ def process
42
+ #p @xml
43
+ @h_index=process_path(@xml,"//h-index").to_i
44
+ @year_range=@xml.xpath("//columnHeading").map {|xx| xx.text.to_i}
45
+ @prev_total=process_path(@xml,"//prevColumnTotal").to_i
46
+ @later_total=process_path(@xml,"//laterColumnTotal").to_i
47
+ @column_total=@xml.xpath("//columnTotal").map {|xx| xx.text.to_i}
48
+ @range_total=process_path(@xml,"//rangeColumnTotal").to_i
49
+ @grand_total=process_path(@xml,"//grandTotal").to_i
50
+
51
+
52
+ @records=xml.xpath("//citeInfo").map do |x|
53
+ scopus_id=process_path(x,".//dc:identifier")
54
+
55
+ pcc=process_path(x,".//pcc").to_i
56
+ cc=x.xpath(".//cc").map {|xx| xx.text.to_i}
57
+
58
+ lcc=process_path(x,".//lcc").to_i
59
+ #if scopus_id=="SCOPUS_ID:84866769122"
60
+ # p x
61
+ # p({:scopus_id=>scopus_id,:pcc=>pcc,:lcc=>lcc,:cc=>cc})
62
+ #end
63
+ {:scopus_id=>scopus_id,:pcc=>pcc,:lcc=>lcc,:cc=>cc}
64
+ end
65
+ #p @records
66
+ end
67
+ def n_records
68
+ @records.length
69
+ end
70
+
71
+ def scopus_id_a
72
+ @records.map {|r| r[:scopus_id]}
73
+ end
74
+ def get_record(scopus_id)
75
+ record=@records.find {|r| r[:scopus_id]==scopus_id}
76
+ raise("Record doesn't exists") unless record
77
+ record
78
+ end
79
+ def empty_record?(scopus_id)
80
+ record=get_record(scopus_id)
81
+ record[:cc]==[]
82
+ end
83
+ def citations_by_year(scopus_id)
84
+ record=get_record(scopus_id)
85
+ return nil if record[:cc].length==0
86
+ year_range.each_index.inject({}) {|ac,i|
87
+ ac[@year_range[i]]=record[:cc][i]
88
+ ac
89
+ }
90
+ end
91
+ def citations_outside_range?(scopus_id)
92
+ @grand_total!=@range_total
93
+ end
94
+ end
95
+ end
96
+
97
+ end
@@ -0,0 +1,333 @@
1
+ # Copyright (c) 2016-2020, Claudio Bustos Navarrete
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of the copyright holder nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ require 'digest'
30
+
31
+ #
32
+ module ElsevierApi
33
+ module XMLResponse
34
+ class Abstractsretrievalresponse < XMLResponseGeneric
35
+ NA_AFFILIATION="NAFD:**NA**"
36
+ NA_AFFILIATION_NAME="__No affiliation__"
37
+ attr_reader :scopus_id
38
+ attr_reader :cited_by_count
39
+ attr_reader :title
40
+ attr_reader :eid
41
+ attr_reader :type_code
42
+ attr_reader :type
43
+ attr_reader :year
44
+ attr_reader :journal
45
+ attr_reader :authors
46
+ attr_reader :volume
47
+ attr_reader :issue
48
+ attr_reader :starting_page
49
+ attr_reader :ending_page
50
+ attr_reader :doi
51
+ attr_reader :affiliations
52
+ attr_reader :abstract
53
+ attr_reader :subject_areas
54
+ attr_reader :author_keywords
55
+ attr_reader :book_title
56
+ attr_reader :author_groups
57
+ def inspect
58
+ "#<#{self.class}:#{self.object_id} @title=#{@title} @journal=#{@journal} @authors=[#{@authors.keys.join(",")}]>"
59
+ end
60
+ def process
61
+
62
+ @authors={}
63
+ @affiliations={}
64
+ @author_keywords=[]
65
+ @subject_areas=[]
66
+ @author_groups=[]
67
+ process_basic_metadata
68
+ process_taxonomy
69
+ process_affiliations
70
+ process_author_groups
71
+ process_authors
72
+ end
73
+
74
+
75
+ # We can't find the affiliation the ussual way
76
+ # we have to improvise
77
+ # Given the afid, we search on every <affiliation> tag until
78
+ # we find the desired one
79
+ def search_affiliation(afid)
80
+ x=xml.at_xpath("//affiliation[@afid=\"#{afid}\"]")
81
+ if !x
82
+ raise "I can't find affiliation #{afid}"
83
+ else
84
+ name=x.xpath("organization").map { |e| e.text }.join(";")
85
+ city=process_path(xml, "//affiliation[@afid=\"#{afid}\"]/city-group")
86
+ country=process_path(xml, "//affiliation[@afid=\"#{afid}\"]/country")
87
+ country||=x.attribute("country").value
88
+ end
89
+ {:id => afid, :name => name, :city => city, :country => country,:type=>:scopus}
90
+ end
91
+
92
+ # We have to find doi on
93
+ def search_doi
94
+ if xml.at_xpath("//source").text=~/^\s*http:\/\/dx\.doi\.org\/([^\s]+)/
95
+ return $1
96
+
97
+ end
98
+ end
99
+
100
+ def get_affiliation_id(aff)
101
+ if aff.nil?
102
+ nil
103
+ elsif id=aff.attribute('afid')
104
+ id.value
105
+ else
106
+ city, country, id, name = get_affiliation_data(aff)
107
+ id
108
+ end
109
+ end
110
+
111
+ def search_affiliation_country(id)
112
+ return nil if id.nil?
113
+ process_path(xml, "//affiliation[@afid='#{id}']/country")
114
+ end
115
+ def process_affiliations
116
+ xml.xpath("/xmlns:abstracts-retrieval-response/xmlns:affiliation").each do |x|
117
+ id=x.attribute("id").nil? ? "" : x.attribute("id").value
118
+ next if id==""
119
+ name=process_path(x, "xmlns:affilname")
120
+ city=process_path(x, "xmlns:affiliation-city")
121
+ country=process_path(x, "xmlns:affiliation-country")
122
+ country=search_affiliation_country(id) if (country=="")
123
+ @affiliations[id]={
124
+ :id => id,
125
+ :name => name,
126
+ :city => city,
127
+ :country => country,
128
+ :type=>:scopus
129
+ }
130
+ end
131
+ add_unidentified_affilitations
132
+ end
133
+
134
+ # Some affiliations doesn't have an id. We could create it
135
+ # hashing the name and the country on unidentified filliations on
136
+ # head tag
137
+ # The process only add the affiliation if name is not nil
138
+
139
+ def get_id_affiliation(name,city,country)
140
+ "NS:"+Digest::MD5.hexdigest("#{name}|#{city}|#{country}")
141
+ end
142
+ def add_unidentified_affilitations
143
+ xml.xpath("//bibrecord/head/author-group/affiliation").each do |aff|
144
+ next if aff.attribute("afid")
145
+ city, country, id, name = get_affiliation_data(aff)
146
+ next if (name=="" and city=="" and country=="")
147
+
148
+
149
+ @affiliations[id]={
150
+ :id => id,
151
+ :name => name,
152
+ :city => city,
153
+ :country => country,
154
+ :type=>:non_scopus
155
+ }
156
+ end
157
+ end
158
+ def add_no_affiliation_case(auid)
159
+ id=NA_AFFILIATION+":"+Digest::MD5.hexdigest("#{@scopus_id}|#{auid}")
160
+ @affiliations[id]={
161
+ :id => id,
162
+ :name => "#{@scopus_id}|#{auid}",
163
+ :city => "",
164
+ :country => "NO_COUNTRY",
165
+ :type=>:non_scopus
166
+ }
167
+ id
168
+ end
169
+ def get_affiliation_data(aff)
170
+ organization=aff.xpath("organization").map { |e| e.text }.join(";")
171
+ address=aff.xpath("address-part").map { |e| e.text }.join(";")
172
+ name= organization!="" ? organization : address
173
+ city_only=aff.xpath("city").text
174
+ city_part=aff.xpath("city-group").text
175
+ city= city_only!="" ? city_only : city_part
176
+ country=aff.xpath("country").text
177
+
178
+ name="UNKOWN ORG FOR #{@scopus_id} ARTICLE" if name==""
179
+ country="NO_COUNTRY" if country==""
180
+
181
+
182
+ id=get_id_affiliation(name,city,country)
183
+ return city, country, id, name
184
+ end
185
+
186
+ # Author groups gives us information about the authors
187
+ # groups as appears on the head. Could be useful to retrieve
188
+ # information about missing affilitations
189
+ # Author-groups with authors duplicated are eliminated
190
+ def process_author_groups
191
+ author_groups_temp=xml.xpath("//bibrecord/head/author-group").map do |ag|
192
+ process_one_author_group(ag)
193
+ end
194
+
195
+ #authors_list= []
196
+ @author_groups=author_groups_temp
197
+ # @author_groups=[]
198
+ # author_groups_temp.each do |ag|
199
+ # @author_groups.push(ag) unless ag[:authors].any? {|author| authors_list.include? author}
200
+ # authors_list=authors_list | ag[:authors]
201
+ # end
202
+
203
+ end
204
+
205
+
206
+ def process_one_author_group(ag)
207
+ if aff_node = ag.at_xpath("affiliation")
208
+ city, country, afid1, name = get_affiliation_data(aff_node)
209
+ aff_id2 = get_affiliation_id(ag.at_xpath("affiliation"))
210
+ if (name == "" and city == "" and country == "")
211
+ aff_id = nil
212
+ else
213
+ aff_id = aff_id2
214
+ end
215
+ else
216
+ aff_id = nil
217
+ end
218
+ {:authors => ag.xpath("author").map {|auth|
219
+ a = auth.attribute('auid')
220
+ a ? a.value : nil},
221
+ :affiliation => aff_id
222
+ }
223
+ end
224
+
225
+ private :process_one_author_group
226
+
227
+
228
+ def process_authors
229
+ xml.xpath("//xmlns:authors/xmlns:author").each do |x|
230
+ auid=x.attribute("auid").value
231
+ seq=x.attribute("seq").value
232
+ initials =process_path(x, "xmlns:preferred-name/ce:initials")
233
+ indexed_name = process_path(x, "xmlns:preferred-name/ce:indexed-name")
234
+ given_name =process_path(x, "xmlns:preferred-name/ce:given-name")
235
+ surname=process_path(x, "xmlns:preferred-name/ce:surname")
236
+ affiliation=nil
237
+ affiliation_node=x.xpath("xmlns:affiliation")
238
+
239
+ if affiliation_node.length==1
240
+ affiliation=affiliation_node[0].attribute("id").text
241
+ if !affiliation.nil? and @affiliations[affiliation].nil?
242
+ @affiliations[affiliation]=search_affiliation(affiliation)
243
+ end
244
+ elsif affiliation_node.length>1
245
+ affiliation=affiliation_node.map{|af|
246
+ af.attribute("id").text
247
+ }.uniq
248
+ affiliation.each do |af|
249
+ if !af.nil? and @affiliations[af].nil?
250
+ @affiliations[af]=search_affiliation(af)
251
+ end
252
+ end
253
+ else
254
+ # Must search in author-groups for affilitation
255
+ res=@author_groups.find{|ag|
256
+ ag[:authors].include? auid
257
+ }
258
+
259
+ if res
260
+ affiliation=res[:affiliation]
261
+ end
262
+ if affiliation.nil?
263
+ # Affiliation shouldn't be nil. We create a custom affiliation for this cases
264
+ affiliation=add_no_affiliation_case(auid)
265
+ end
266
+
267
+ #
268
+ end
269
+
270
+ #p "#{name} #{apellido}"
271
+ @authors[auid]={
272
+ :auid => auid,
273
+ :seq => seq,
274
+ :initials => initials,
275
+ :indexed_name => indexed_name,
276
+ :given_name => given_name,
277
+ :surname => surname,
278
+ :email => nil,
279
+ :affiliation => affiliation
280
+ }
281
+
282
+
283
+ end
284
+ # Searching for authors e-mails
285
+
286
+ xml.xpath("//bibrecord//head//author-group/author//ce:e-address[@type='email']").each do |email|
287
+ auid=email.parent.attribute("auid").value
288
+ @authors[auid][:email]=email.text
289
+ end
290
+ end
291
+
292
+
293
+ def process_taxonomy
294
+ xml.xpath("//xmlns:authkeywords/xmlns:author-keyword").each do |x|
295
+ @author_keywords.push(x.text)
296
+ end
297
+ xml.xpath("//xmlns:subject-areas/xmlns:subject-area").each do |x|
298
+ @subject_areas.push(
299
+ {:abbrev => x.attribute("abbrev").value,
300
+ :code => x.attribute("code").value.to_i,
301
+ :name => x.text
302
+ }
303
+ )
304
+ end
305
+ end
306
+
307
+ def process_basic_metadata
308
+ @scopus_id = process_path(xml, "//dc:identifier")
309
+ @title = process_path(xml, "//dc:title")
310
+ @doi = process_path(xml, "//prism:doi")
311
+ @doi||=search_doi
312
+ @eid = process_path(xml, "//xmlns:eid")
313
+ @type_code = process_path(xml, "//xmlns:srctype")
314
+ @cited_by_count = process_path(xml,"//xmlns:citedby-count").to_i
315
+ @type = process_path(xml, "//prism:aggregationType").downcase.to_sym
316
+ if @type_code=="j" or @type_code=="p"
317
+ @journal =process_path(xml, "//prism:publicationName")
318
+ @volume =process_path(xml, "//prism:volume")
319
+ @issue =process_path(xml, "//prism:issueIdentifier")
320
+ elsif @type_code=="b"
321
+ @book_title =process_path(xml, "//prism:publicationName")
322
+ end
323
+ @starting_page =process_path(xml, "//prism:startingPage")
324
+ @ending_page =process_path(xml, "//prism:endingPage")
325
+ @year =process_path(xml, "//year")
326
+ @abstract =process_path(xml, "//dc:description/xmlns:abstract[@xml:lang='eng']/ce:para")
327
+ @abstract ||=process_path(xml, "//abstract/ce:para")
328
+ end
329
+
330
+
331
+ end
332
+ end
333
+ end
@@ -0,0 +1,36 @@
1
+ # Copyright (c) 2016-2020, Claudio Bustos Navarrete
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of the copyright holder nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ module ElsevierApi
29
+ module XMLResponse
30
+ class ElsevierApi::XMLResponse::Authorretrievalresponse < XMLResponseGeneric
31
+ def proccess
32
+
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright (c) 2016-2020, Claudio Bustos Navarrete
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of the copyright holder nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ # PENDING
30
+ module ElsevierApi
31
+ module XMLResponse
32
+ class ElsevierApi::XMLResponse::Authorretrievalresponselist < XMLResponseGeneric
33
+ def proccess
34
+
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,54 @@
1
+ # Copyright (c) 2016-2020, Claudio Bustos Navarrete
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of the copyright holder nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ module ElsevierApi
29
+ module XMLResponse
30
+
31
+ class ElsevierApi::XMLResponse::Searchresults < XMLResponseGeneric
32
+ def next_page
33
+ @xml.at_xpath("//atom:link[@ref='next']")
34
+ end
35
+ def entries_to_ary
36
+ @xml.xpath("//atom:entry").map {|v|
37
+ title=v.at_xpath("dc:title").nil? ? nil : v.at_xpath("dc:title").text
38
+ journal=v.at_xpath("prism:publicationName").nil? ? nil : v.at_xpath("prism:publicationName").text
39
+ h={
40
+ :scopus_id=>v.at_xpath("dc:identifier").text,
41
+ :title=>title,
42
+ :journal=>journal
43
+ }
44
+ {:creator=>"dc:creator",:doi=>"prism:doi"}.each_pair {|key,xv|
45
+ h[key]=v.at_xpath(xv).text unless v.at_xpath(xv).nil?
46
+ }
47
+ h
48
+ }
49
+ end
50
+
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,34 @@
1
+ # Copyright (c) 2016-2020, Claudio Bustos Navarrete
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of the copyright holder nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ module ElsevierApi
29
+ module XMLResponse
30
+
31
+ class ElsevierApi::XMLResponse::Serviceerror < XMLResponseGeneric
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,61 @@
1
+ # Copyright (c) 2016-2020, Claudio Bustos Navarrete
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of the copyright holder nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ module ElsevierApi
29
+ module XMLResponse
30
+ class XMLEmpty
31
+ def error
32
+ true
33
+ end
34
+ def error_msg
35
+ I18n::t(:empty_xml_file)
36
+ end
37
+ end
38
+ class XMLResponseGeneric
39
+ attr_reader :xml
40
+ def initialize(xml)
41
+ @xml=xml
42
+ process()
43
+ end
44
+ # Just put anything you want here
45
+ def process
46
+ end
47
+ def process_path(x, path)
48
+ node=x.at_xpath(path)
49
+ (node.nil?) ? nil : node.text
50
+ end
51
+ end
52
+
53
+ end
54
+ end
55
+
56
+ require_relative "xml_response/abstract_retrieval_response"
57
+ require_relative "xml_response/search_results"
58
+ require_relative "xml_response/service_error"
59
+ require_relative "xml_response/abstract_citation_response"
60
+ require_relative "xml_response/author_retrieval_response"
61
+ require_relative "xml_response/author_retrieval_response_list"
@@ -0,0 +1,66 @@
1
+ # Copyright (c) 2016-2020, Claudio Bustos Navarrete
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are met:
6
+ #
7
+ # * Redistributions of source code must retain the above copyright notice, this
8
+ # list of conditions and the following disclaimer.
9
+ #
10
+ # * Redistributions in binary form must reproduce the above copyright notice,
11
+ # this list of conditions and the following disclaimer in the documentation
12
+ # and/or other materials provided with the distribution.
13
+ #
14
+ # * Neither the name of the copyright holder nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+
29
+ require 'nokogiri'
30
+ # Module ElsevierApi
31
+ #
32
+ # Provides access to ElsevierApi dev services
33
+ module ElsevierApi
34
+ # Factory method
35
+ def self.process_xml(xml)
36
+
37
+ xml=Nokogiri::XML(xml) if xml.is_a? String
38
+ if xml.children.length==0
39
+ # Error
40
+ ElsevierApi::XMLResponse::XMLEmpty.new
41
+ else
42
+ name=xml.children[0].name.gsub("-","").capitalize
43
+ ElsevierApi::XMLResponse.const_get(name.to_sym).new(xml)
44
+ end
45
+
46
+ end
47
+
48
+ def self.entries_to_csv(entries,csv_file)
49
+ require 'csv'
50
+ d=Date.today.to_s
51
+ header=["scopus_id","title","journal","creator","doi","date"]
52
+ CSV.open(csv_file,"wb") {|csv|
53
+ csv << header
54
+ entries.each {|e|
55
+ csv << [e[:scopus_id],e[:title],e[:journal], e[:creator],e[:doi],d]
56
+ }
57
+ }
58
+ end
59
+
60
+ end
61
+
62
+ require_relative "elsevier_api/uri_request"
63
+ require_relative "elsevier_api/connection"
64
+ require_relative "elsevier_api/xml_response"
65
+
66
+
metadata ADDED
@@ -0,0 +1,104 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: elsevier_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Claudio Bustos
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-02-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ description: 'A Ruby gem for use with Elsevier''s APIs: Scopus, ScienceDirect, others. '
56
+ email:
57
+ - clbustos@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".idea/vcs.xml"
63
+ - Gemfile
64
+ - Gemfile.lock
65
+ - LICENSE
66
+ - README.md
67
+ - Rakefile
68
+ - bin/elsevier-api-console
69
+ - elsevier_api.gemspec
70
+ - lib/elsevier_api.rb
71
+ - lib/elsevier_api/connection.rb
72
+ - lib/elsevier_api/uri_request.rb
73
+ - lib/elsevier_api/version.rb
74
+ - lib/elsevier_api/xml_response.rb
75
+ - lib/elsevier_api/xml_response/abstract_citation_response.rb
76
+ - lib/elsevier_api/xml_response/abstract_retrieval_response.rb
77
+ - lib/elsevier_api/xml_response/author_retrieval_response.rb
78
+ - lib/elsevier_api/xml_response/author_retrieval_response_list.rb
79
+ - lib/elsevier_api/xml_response/search_results.rb
80
+ - lib/elsevier_api/xml_response/service_error.rb
81
+ homepage: https://github.com/clbustos/elsevier_api
82
+ licenses:
83
+ - BSD-3-Clause
84
+ metadata: {}
85
+ post_install_message:
86
+ rdoc_options: []
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - - ">="
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ requirements: []
100
+ rubygems_version: 3.1.2
101
+ signing_key:
102
+ specification_version: 4
103
+ summary: Ruby gem to interact with Elsevier's APIs
104
+ test_files: []