enju_ndl 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,12 +5,11 @@ class NdlBook
5
5
  cnt = self.per_page
6
6
  page = 1 if page.to_i < 1
7
7
  idx = (page.to_i - 1) * cnt + 1
8
- url = "http://api.porta.ndl.go.jp/servicedp/opensearch?dpid=zomoku&any=#{URI.encode(query.strip)}&cnt=#{cnt}&idx=#{idx}"
9
- Rails.logger.debug url
10
- xml = open(url).read
11
- doc = Nokogiri::XML(xml)
8
+ doc = Nokogiri::XML(Manifestation.search_ndl(query, {:cnt => cnt, :page => page, :idx => idx, :raw => true}).to_s)
9
+ # raise doc.to_s
12
10
  items = doc.xpath('//channel/item')
13
11
  total_entries = doc.at('//channel/openSearch:totalResults').content.to_i
12
+
14
13
  {:items => items, :total_entries => total_entries}
15
14
  else
16
15
  {:items => [], :total_entries => 0}
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <%= render 'page/include' %>
6
6
  <%= render 'page/portlets' %>
7
- <title><%= t('enju_ndl.import_from_porta') %></title>
7
+ <title><%= t('enju_ndl.import_from_ndl_search') %></title>
8
8
  </head>
9
9
  <body itemscope itemtype="http://schema.org/WebPage">
10
10
 
@@ -1,5 +1,5 @@
1
1
  <div id="content_detail" class="ui-corner-all">
2
- <h1 class="title">PORTA検索によるインポート</h1>
2
+ <h1 class="title">NDLサーチ検索によるインポート</h1>
3
3
  <div id="content_list">
4
4
  <p id="notice"><%= notice %></p>
5
5
 
@@ -26,9 +26,10 @@
26
26
  <td>
27
27
  <%= link_to book.at('./title').content, book.at('./link').content %>
28
28
  <br />
29
- <%= book.xpath('./dc:creator[@xsi:type="dcndl:NDLNH"]').collect(&:content).join(' ') %>
29
+ <%= book.xpath('./dc:creator').collect(&:content).join(' ') %>
30
30
  <%= book.xpath('./dc:publisher').collect(&:content).join(' ') %>
31
- ISBN: <%= book.at('./dc:identifier[@xsi:type="dcndl:ISBN"]').try(:content).to_s %>
31
+ (<%= Time.zone.parse(book.at('./pubDate').content).year %>,
32
+ ISBN: <%= book.at('./dc:identifier[@xsi:type="dcndl:ISBN"]').try(:content).to_s %>)
32
33
  </td>
33
34
  </tr>
34
35
  <% end %>
@@ -1,3 +1,3 @@
1
1
  en:
2
2
  enju_ndl:
3
- import_from_porta: Import from PORTA
3
+ import_from_ndl_search: Import from NDL Search
@@ -1,3 +1,3 @@
1
1
  ja:
2
2
  enju_ndl:
3
- import_from_porta: PORTA検索によるインポート
3
+ import_from_ndl_search: NDLサーチ検索によるインポート
data/lib/enju_ndl.rb CHANGED
@@ -3,7 +3,6 @@ require "enju_ndl/engine"
3
3
  require 'open-uri'
4
4
  require 'enju_ndl/ndl_search'
5
5
  require 'enju_ndl/crd'
6
- require 'enju_ndl/porta'
7
6
 
8
7
  module EnjuNdl
9
8
  module ActsAsMethods
@@ -19,10 +18,6 @@ module EnjuNdl
19
18
  def enju_ndl_crd
20
19
  include EnjuNdl::Crd
21
20
  end
22
-
23
- def enju_ndl_porta
24
- include EnjuNdl::Porta
25
- end
26
21
  end
27
22
  end
28
23
 
@@ -1,3 +1,8 @@
1
+ require 'devise'
2
+ require 'nokogiri'
3
+ require 'rss'
4
+ require 'isbn/tools'
5
+
1
6
  module EnjuNdl
2
7
  class Engine < Rails::Engine
3
8
  end
@@ -6,43 +6,162 @@ module EnjuNdl
6
6
  end
7
7
 
8
8
  module ClassMethods
9
- def rss_import(url)
10
- doc = Nokogiri::XML(open(url))
11
- ns = {"dc" => "http://purl.org/dc/elements/1.1/", "xsi" => "http://www.w3.org/2001/XMLSchema-instance", "dcndl" => "http://ndl.go.jp/dcndl/terms/"}
12
- doc.xpath('//item', ns).each do |item|
13
- isbn = item.at('./dc:identifier[@xsi:type="dcndl:ISBN"]').try(:content)
14
- ndl_bib_id = item.at('./dc:identifier[@xsi:type="dcndl:NDLBibID"]').try(:content)
15
- manifestation = Manifestation.where(:ndl_bib_id => ndl_bib_id).first
16
- manifestation = Manifestation.find_by_isbn(isbn) unless manifestation
17
- # FIXME: 日本語決めうち?
18
- language_id = Language.where(:iso_639_2 => 'jpn').first.id rescue 1
19
- unless manifestation
20
- manifestation = self.new(
21
- :original_title => item.at('./dc:title').content,
22
- :title_transcription => item.at('./dcndl:titleTranscription').try(:content),
23
- :isbn => isbn,
24
- :ndl_bib_id => ndl_bib_id,
25
- :description => item.at('./dc:description').try(:content),
26
- :pub_date => item.at('./dc:date').try(:content).try(:gsub, '.', '-'),
27
- :language_id => language_id
28
- )
29
- if manifestation.valid?
30
- item.xpath('./dc:creator').each_with_index do |creator, i|
31
- next if i == 0
32
- patron = Patron.where(:full_name => creator.try(:content)).first
33
- patron = Patron.new(:full_name => creator.try(:content)) unless patron
34
- manifestation.creators << patron if patron.valid?
35
- end
36
- item.xpath('./dc:publisher').each_with_index do |publisher, i|
37
- patron = Patron.where(:full_name => publisher.try(:content)).first
38
- patron = Patron.new(:full_name => publisher.try(:content)) unless patron
39
- manifestation.publishers << patron if patron.valid?
40
- end
9
+ def import_isbn(isbn)
10
+ isbn = ISBN_Tools.cleanup(isbn)
11
+ raise EnjuNdl::InvalidIsbn unless ISBN_Tools.is_valid?(isbn)
12
+
13
+ manifestation = Manifestation.find_by_isbn(isbn)
14
+ return manifestation if manifestation
15
+
16
+ doc = return_xml(isbn)
17
+ #raise EnjuNdl::RecordNotFound if doc.at('//openSearch:totalResults').content.to_i == 0
18
+ raise EnjuNdl::RecordNotFound unless doc
19
+
20
+ pub_date, language, nbn = nil, nil, nil
21
+
22
+ publishers = get_publishers(doc).zip([]).map{|f,t| {:full_name => f, :full_name_transcription => t}}
23
+
24
+ # title
25
+ title = get_title(doc)
26
+
27
+ # date of publication
28
+ pub_date = doc.at('//dcterms:date').content.to_s.gsub(/\./, '-')
29
+ unless pub_date =~ /^\d+(-\d{0,2}){0,2}$/
30
+ pub_date = nil
31
+ end
32
+
33
+ language = get_language(doc)
34
+ nbn = doc.at('//dcterms:identifier[@rdf:datatype="http://ndl.go.jp/dcndl/terms/JPNO"]').content
35
+ classification_urls = doc.xpath('//dcterms:subject[@rdf:resource]').map{|subject| subject.attributes['resource'].value}
36
+ ndc = classification_urls.map{|url| URI.parse(url)}.select{|url| url.path.split('/').reverse[1] == 'ndc9'}.first.path.split('/').last
37
+
38
+ Patron.transaction do
39
+ publisher_patrons = Patron.import_patrons(publishers)
40
+ language_id = Language.where(:iso_639_2 => language).first.id rescue 1
41
+
42
+ manifestation = Manifestation.new(
43
+ :original_title => title[:manifestation],
44
+ :title_transcription => title[:transcription],
45
+ # TODO: NDLサーチに入っている図書以外の資料を調べる
46
+ #:carrier_type_id => CarrierType.where(:name => 'print').first.id,
47
+ :language_id => language_id,
48
+ :isbn => isbn,
49
+ :pub_date => pub_date,
50
+ :nbn => nbn,
51
+ :ndc => ndc
52
+ )
53
+ manifestation.ndc = ndc
54
+ manifestation.publishers << publisher_patrons
55
+ end
56
+
57
+ #manifestation.send_later(:create_frbr_instance, doc.to_s)
58
+ create_frbr_instance(doc, manifestation)
59
+ return manifestation
60
+ end
61
+
62
+ def import_isbn!(isbn)
63
+ manifestation = import_isbn(isbn)
64
+ manifestation.save!
65
+ manifestation
66
+ end
67
+
68
+ def create_frbr_instance(doc, manifestation)
69
+ title = get_title(doc)
70
+ creators = get_creators(doc).zip([]).map{|f,t| {:full_name => f, :full_name_transcription => t}}
71
+ language = get_language(doc)
72
+ subjects = get_subjects(doc)
73
+
74
+ Patron.transaction do
75
+ creator_patrons = Patron.import_patrons(creators)
76
+ language_id = Language.where(:iso_639_2 => language).first.id rescue 1
77
+ content_type_id = ContentType.where(:name => 'text').first.id rescue 1
78
+ manifestation.creators << creator_patrons
79
+ if defined?(Subject)
80
+ subjects.each do |term|
81
+ subject = Subject.where(:term => term).first
82
+ manifestation.subjects << subject if subject
41
83
  end
42
84
  end
43
85
  end
44
- Sunspot.commit
45
86
  end
87
+
88
+ def search_ndl(query, options = {})
89
+ options = {:dpid => 'iss-ndl-opac', :item => 'any', :startrecord => 1, :per_page => 10, :raw => false}.merge(options)
90
+ doc = nil
91
+ results = {}
92
+ startrecord = options[:startrecord].to_i
93
+ if startrecord == 0
94
+ startrecord = 1
95
+ end
96
+ url = "http://iss.ndl.go.jp/api/opensearch?dpid=#{options[:dpid]}&#{options[:item]}=#{URI.escape(query)}&cnt=#{options[:per_page]}&idx=#{startrecord}"
97
+ if options[:raw] == true
98
+ open(url).read
99
+ else
100
+ RSS::Rss::Channel.install_text_element("openSearch:totalResults", "http://a9.com/-/spec/opensearchrss/1.0/", "?", "totalResults", :text, "openSearch:totalResults")
101
+ RSS::BaseListener.install_get_text_element "http://a9.com/-/spec/opensearchrss/1.0/", "totalResults", "totalResults="
102
+ feed = RSS::Parser.parse(url, false)
103
+ end
104
+ end
105
+
106
+ def normalize_isbn(isbn)
107
+ if isbn.length == 10
108
+ ISBN_Tools.isbn10_to_isbn13(isbn)
109
+ else
110
+ ISBN_Tools.isbn13_to_isbn10(isbn)
111
+ end
112
+ end
113
+
114
+ def return_xml(isbn)
115
+ rss = self.search_ndl(isbn, {:dpid => 'iss-ndl-opac', :item => 'isbn'})
116
+ if rss.channel.totalResults.to_i == 0
117
+ isbn = normalize_isbn(isbn)
118
+ rss = self.search_ndl(isbn, {:dpid => 'iss-ndl-opac', :item => 'isbn'})
119
+ end
120
+ if rss.items.first
121
+ doc = Nokogiri::XML(open("#{rss.items.first.link}.rdf").read)
122
+ end
123
+ end
124
+
125
+ private
126
+ def get_title(doc)
127
+ title = {
128
+ :manifestation => doc.xpath('//dc:title/rdf:Description/rdf:value').collect(&:content).join(' ').tr('a-zA-Z0-9 ', 'a-zA-Z0-9 ').squeeze(' '),
129
+ :transcription => doc.xpath('//dc:title/dcndl:transcription').collect(&:content).join(' ').tr('a-zA-Z0-9 ', 'a-zA-Z0-9 ').squeeze(' '),
130
+ :original => doc.xpath('//dcterms:alternative/rdf:Rescription/rdf:value').collect(&:content).join(' ').tr('a-zA-Z0-9 ', 'a-zA-Z0-9 ').squeeze(' ')
131
+ }
132
+ end
133
+
134
+ def get_creators(doc)
135
+ creators = []
136
+ doc.xpath('//dcterms:creator/foaf:Agent/foaf:name').each do |creator|
137
+ creators << creator.content.gsub('‖', '').tr('a-zA-Z0-9 ', 'a-zA-Z0-9 ')
138
+ end
139
+ creators
140
+ end
141
+
142
+ def get_subjects(doc)
143
+ subjects = []
144
+ doc.xpath('//dcterms:subject/rdf:Description/rdf:value').each do |subject|
145
+ subjects << subject.content.tr('a-zA-Z0-9 ‖', 'a-zA-Z0-9 ')
146
+ end
147
+ return subjects
148
+ end
149
+
150
+ def get_language(doc)
151
+ # TODO: 言語が複数ある場合
152
+ language = doc.xpath('//dcterms:language').first.content.downcase
153
+ end
154
+
155
+ def get_publishers(doc)
156
+ publishers = []
157
+ doc.xpath('//dcterms:publisher/foaf:Agent/foaf:name').each do |publisher|
158
+ publishers << publisher.content.tr('a-zA-Z0-9 ‖', 'a-zA-Z0-9 ')
159
+ end
160
+ return publishers
161
+ end
162
+ end
163
+
164
+ class AlreadyImported < StandardError
46
165
  end
47
166
  end
48
167
  end
@@ -1,3 +1,3 @@
1
1
  module EnjuNdl
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: enju_ndl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,55 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-01 00:00:00.000000000 Z
12
+ date: 2012-01-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70201338394300 !ruby/object:Gem::Requirement
16
+ requirement: &70123411904400 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 3.1.3
21
+ version: '3'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70201338394300
24
+ version_requirements: *70123411904400
25
+ - !ruby/object:Gem::Dependency
26
+ name: devise
27
+ requirement: &70123411918620 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70123411918620
36
+ - !ruby/object:Gem::Dependency
37
+ name: nokogiri
38
+ requirement: &70123411945180 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :runtime
45
+ prerelease: false
46
+ version_requirements: *70123411945180
47
+ - !ruby/object:Gem::Dependency
48
+ name: will_paginate
49
+ requirement: &70123411964080 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: *70123411964080
25
58
  - !ruby/object:Gem::Dependency
26
59
  name: sqlite3
27
- requirement: &70201338393660 !ruby/object:Gem::Requirement
60
+ requirement: &70123412083020 !ruby/object:Gem::Requirement
28
61
  none: false
29
62
  requirements:
30
63
  - - ! '>='
@@ -32,10 +65,10 @@ dependencies:
32
65
  version: '0'
33
66
  type: :development
34
67
  prerelease: false
35
- version_requirements: *70201338393660
68
+ version_requirements: *70123412083020
36
69
  - !ruby/object:Gem::Dependency
37
70
  name: rspec-rails
38
- requirement: &70201338392740 !ruby/object:Gem::Requirement
71
+ requirement: &70123412079920 !ruby/object:Gem::Requirement
39
72
  none: false
40
73
  requirements:
41
74
  - - ! '>='
@@ -43,7 +76,7 @@ dependencies:
43
76
  version: '0'
44
77
  type: :development
45
78
  prerelease: false
46
- version_requirements: *70201338392740
79
+ version_requirements: *70123412079920
47
80
  description: NDL WebAPI wrapper for Next-L Enju
48
81
  email:
49
82
  - tanabe@mwr.mediacom.keio.ac.jp
@@ -62,7 +95,6 @@ files:
62
95
  - lib/enju_ndl/crd.rb
63
96
  - lib/enju_ndl/engine.rb
64
97
  - lib/enju_ndl/ndl_search.rb
65
- - lib/enju_ndl/porta.rb
66
98
  - lib/enju_ndl/version.rb
67
99
  - lib/enju_ndl.rb
68
100
  - lib/tasks/enju_ndl_tasks.rake
@@ -98,4 +130,3 @@ summary: enju_ndl plugin
98
130
  test_files:
99
131
  - test/enju_ndl_test.rb
100
132
  - test/test_helper.rb
101
- has_rdoc:
@@ -1,165 +0,0 @@
1
- # -*- encoding: utf-8 -*-
2
- module EnjuNdl
3
- module Porta
4
- def self.included(base)
5
- base.extend ClassMethods
6
- end
7
-
8
- module ClassMethods
9
- def import_isbn(isbn)
10
- isbn = ISBN_Tools.cleanup(isbn)
11
- raise EnjuNdl::InvalidIsbn unless ISBN_Tools.is_valid?(isbn)
12
-
13
- manifestation = Manifestation.find_by_isbn(isbn)
14
- return manifestation if manifestation
15
-
16
- doc = return_xml(isbn)
17
- raise EnjuNdl::RecordNotFound if doc.at('//openSearch:totalResults').content.to_i == 0
18
-
19
- pub_date, language, nbn = nil, nil, nil
20
-
21
- publishers = get_publishers(doc).zip([]).map{|f,t| {:full_name => f, :full_name_transcription => t}}
22
-
23
- # title
24
- title = get_title(doc)
25
-
26
- # date of publication
27
- pub_date = doc.at('//dcterms:issued').content.try(:tr, '0-9.', '0-9-').to_s.gsub(/(.*)/, '')
28
- unless pub_date =~ /^\d+(-\d{0,2}){0,2}$/
29
- pub_date = nil
30
- end
31
-
32
- language = get_language(doc)
33
- nbn = doc.at('//dc:identifier[@xsi:type="dcndl:JPNO"]').content
34
- ndc = doc.at('//dc:subject[@xsi:type="dcndl:NDC"]').try(:content)
35
-
36
- Patron.transaction do
37
- publisher_patrons = Patron.import_patrons(publishers)
38
- language_id = Language.where(:iso_639_2 => language).first.id rescue 1
39
-
40
- manifestation = Manifestation.new(
41
- :original_title => title[:manifestation],
42
- :title_transcription => title[:transcription],
43
- # TODO: PORTAに入っている図書以外の資料を調べる
44
- #:carrier_type_id => CarrierType.where(:name => 'print').first.id,
45
- :language_id => language_id,
46
- :isbn => isbn,
47
- :pub_date => pub_date,
48
- :nbn => nbn,
49
- :ndc => ndc
50
- )
51
- manifestation.ndc = ndc
52
- manifestation.publishers << publisher_patrons
53
- end
54
-
55
- #manifestation.send_later(:create_frbr_instance, doc.to_s)
56
- create_frbr_instance(doc, manifestation)
57
- return manifestation
58
- end
59
-
60
- def import_isbn!(isbn)
61
- manifestation = import_isbn(isbn)
62
- manifestation.save!
63
- manifestation
64
- end
65
-
66
- def create_frbr_instance(doc, manifestation)
67
- title = get_title(doc)
68
- creators = get_creators(doc).zip([]).map{|f,t| {:full_name => f, :full_name_transcription => t}}
69
- language = get_language(doc)
70
- subjects = get_subjects(doc)
71
-
72
- Patron.transaction do
73
- creator_patrons = Patron.import_patrons(creators)
74
- language_id = Language.where(:iso_639_2 => language).first.id rescue 1
75
- content_type_id = ContentType.where(:name => 'text').first.id rescue 1
76
- manifestation.creators << creator_patrons
77
- if defined?(Subject)
78
- subjects.each do |term|
79
- subject = Subject.where(:term => term).first
80
- manifestation.subjects << subject if subject
81
- end
82
- end
83
- end
84
- end
85
-
86
- def search_porta(query, options = {})
87
- options = {:item => 'any', :startrecord => 1, :per_page => 10, :raw => false}.merge(options)
88
- doc = nil
89
- results = {}
90
- startrecord = options[:startrecord].to_i
91
- if startrecord == 0
92
- startrecord = 1
93
- end
94
- url = "http://api.porta.ndl.go.jp/servicedp/opensearch?dpid=#{options[:dpid]}&#{options[:item]}=#{URI.escape(query)}&cnt=#{options[:per_page]}&idx=#{startrecord}"
95
- if options[:raw] == true
96
- open(url).read
97
- else
98
- RSS::Rss::Channel.install_text_element("openSearch:totalResults", "http://a9.com/-/spec/opensearchrss/1.0/", "?", "totalResults", :text, "openSearch:totalResults")
99
- RSS::BaseListener.install_get_text_element "http://a9.com/-/spec/opensearchrss/1.0/", "totalResults", "totalResults="
100
- feed = RSS::Parser.parse(url, false)
101
- end
102
- end
103
-
104
- def normalize_isbn(isbn)
105
- if isbn.length == 10
106
- ISBN_Tools.isbn10_to_isbn13(isbn)
107
- else
108
- ISBN_Tools.isbn13_to_isbn10(isbn)
109
- end
110
- end
111
-
112
- def return_xml(isbn)
113
- xml = self.search_porta(isbn, {:dpid => 'zomoku', :item => 'isbn', :raw => true}).to_s
114
- doc = Nokogiri::XML(xml)
115
- if doc.at('//openSearch:totalResults').content.to_i == 0
116
- isbn = normalize_isbn(isbn)
117
- xml = self.search_porta(isbn, {:dpid => 'zomoku', :item => 'isbn', :raw => true}).to_s
118
- doc = Nokogiri::XML(xml)
119
- end
120
- doc
121
- end
122
-
123
- private
124
- def get_title(doc)
125
- title = {
126
- :manifestation => doc.xpath('//item[1]/title').collect(&:content).join(' ').tr('a-zA-Z0-9 ', 'a-zA-Z0-9 ').squeeze(' '),
127
- :transcription => doc.xpath('//item[1]/dcndl:titleTranscription').collect(&:content).join(' ').tr('a-zA-Z0-9 ', 'a-zA-Z0-9 ').squeeze(' '),
128
- :original => doc.xpath('//dcterms:alternative').collect(&:content).join(' ').tr('a-zA-Z0-9 ', 'a-zA-Z0-9 ').squeeze(' ')
129
- }
130
- end
131
-
132
- def get_creators(doc)
133
- creators = []
134
- doc.xpath('//item[1]/dc:creator[@xsi:type="dcndl:NDLNH"]').each do |creator|
135
- creators << creator.content.gsub('‖', '').tr('a-zA-Z0-9 ', 'a-zA-Z0-9 ')
136
- end
137
- creators
138
- end
139
-
140
- def get_subjects(doc)
141
- subjects = []
142
- doc.xpath('//item[1]/dc:subject[@xsi:type="dcndl:NDLSH"]').each do |subject|
143
- subjects << subject.content.tr('a-zA-Z0-9 ‖', 'a-zA-Z0-9 ')
144
- end
145
- return subjects
146
- end
147
-
148
- def get_language(doc)
149
- # TODO: 言語が複数ある場合
150
- language = doc.xpath('//item[1]/dc:language[@xsi:type="dcterms:ISO639-2"]').first.content.downcase
151
- end
152
-
153
- def get_publishers(doc)
154
- publishers = []
155
- doc.xpath('//item[1]/dc:publisher').each do |publisher|
156
- publishers << publisher.content.tr('a-zA-Z0-9 ‖', 'a-zA-Z0-9 ')
157
- end
158
- return publishers
159
- end
160
- end
161
-
162
- class AlreadyImported < StandardError
163
- end
164
- end
165
- end