rbook 0.1 → 0.2
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/README +1 -0
- data/Rakefile +3 -2
- data/examples/gbip.rb +12 -0
- data/examples/onix/stream_reader.rb +13 -0
- data/examples/titlepage.rb +1 -1
- data/lib/rbook/bisac.rb +21 -167
- data/lib/rbook/bisac/message.rb +99 -0
- data/lib/rbook/bisac/product.rb +176 -0
- data/lib/rbook/gbip.rb +19 -0
- data/lib/rbook/gbip/pos.rb +40 -0
- data/lib/rbook/onix.rb +2 -0
- data/lib/rbook/onix/message.rb +91 -86
- data/lib/rbook/onix/product.rb +179 -178
- data/lib/rbook/onix/stream_reader.rb +120 -0
- data/lib/rbook/onix/stream_writer.rb +40 -0
- data/lib/rbook/onix/supply_detail.rb +1 -1
- data/lib/rbook/titlepage.rb +5 -65
- data/lib/rbook/titlepage/client.rb +81 -0
- data/lib/rbook/titlepage/titlepage_driver.rb +122 -119
- data/lib/rbook/titlepage/titlepage_utils.rb +375 -370
- data/test/data/valid_bisac.txt +213 -0
- data/test/mocks/titlepage_driver.rb +99 -95
- data/test/unit/bisac_test.rb +68 -29
- data/test/unit/onix/stream_reader_test.rb +22 -0
- data/test/unit/onix/stream_writer_test.rb +32 -0
- data/test/unit/titlepage_test.rb +5 -5
- metadata +41 -26
- data/lib/rbook/titlepage/TitleQueryClient.rb +0 -62
data/lib/rbook/gbip.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + "/../")
|
2
|
+
|
3
|
+
require 'rbook/isbn'
|
4
|
+
require 'rbook/gbip/pos'
|
5
|
+
|
6
|
+
module RBook
|
7
|
+
|
8
|
+
# Ruby classes for searching the globalbooksinprint.com API. This is a
|
9
|
+
# commercial service and requires a registered account to access. More
|
10
|
+
# information on the service can be found at the website.
|
11
|
+
#
|
12
|
+
# = Basic Usage
|
13
|
+
# gbip = RBook::GBIP::POS.new("username", "password")
|
14
|
+
# puts gbip.find("0091835135").inspect
|
15
|
+
#
|
16
|
+
module GBIP
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module RBook
|
4
|
+
|
5
|
+
module GBIP
|
6
|
+
|
7
|
+
# Provides easy access to the globalbooksinprint.com search API.
|
8
|
+
# RBook::GBIP has basic usage examples.
|
9
|
+
class POS
|
10
|
+
|
11
|
+
attr_accessor :username, :password
|
12
|
+
|
13
|
+
POS_SERVER = "pos.bowker.com"
|
14
|
+
POS_PORT = 7052
|
15
|
+
|
16
|
+
# creates a new POS object ready to perform a search
|
17
|
+
def initialize(username, password)
|
18
|
+
@username = username
|
19
|
+
@password = password
|
20
|
+
end
|
21
|
+
|
22
|
+
# search for the specified ISBN on globalbooksinprint.com.
|
23
|
+
# Accepts both ISBN10 and ISBN13's.
|
24
|
+
def find(isbn)
|
25
|
+
isbn = RBook::ISBN::convert_to_isbn10(isbn)
|
26
|
+
return nil if isbn.nil?
|
27
|
+
|
28
|
+
request = "POS\t3\t2\t#{@username}\t#{@password}\t2\t\tbn=#{isbn}\t1|1|1|1|1|1|1|1|1|1\t10,0\t1\t\t"
|
29
|
+
gbip = TCPSocket.new(POS_SERVER, POS_PORT)
|
30
|
+
gbip.print request
|
31
|
+
response = gbip.gets(nil)
|
32
|
+
gbip.close
|
33
|
+
return response.split("\t")
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
data/lib/rbook/onix.rb
CHANGED
data/lib/rbook/onix/message.rb
CHANGED
@@ -2,100 +2,105 @@ require 'rubygems'
|
|
2
2
|
require 'rexml/document'
|
3
3
|
|
4
4
|
module RBook
|
5
|
-
module Onix
|
5
|
+
module Onix
|
6
6
|
|
7
|
-
class Message
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
VERSION = 0.1
|
7
|
+
class Message
|
8
|
+
attr_reader :products
|
9
|
+
attr_accessor :from_company, :from_person, :from_email, :message_note, :sent_date, :to_person, :to_company
|
12
10
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@products = []
|
17
|
-
end
|
11
|
+
VERSION = 0.1
|
12
|
+
ONIX_DTD_URL = "http://www.editeur.org/onix/2.1/reference/onix-international.dtd"
|
18
13
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
if REXML::XPath.first(doc, '/ONIXMessage/').nil? ||
|
23
|
-
REXML::XPath.first(doc, '/ONIXMessage/Header').nil? ||
|
24
|
-
REXML::XPath.first(doc, '/ONIXMessage/Product').nil?
|
25
|
-
raise LoadError, 'supplied REXML document object does not appear to be a valid ONIX file'
|
26
|
-
end
|
27
|
-
|
28
|
-
msg = Onix::Message.new
|
29
|
-
|
30
|
-
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/FromCompany')
|
31
|
-
msg.from_company = tmpelement.text if tmpelement != nil
|
32
|
-
|
33
|
-
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/FromPerson')
|
34
|
-
msg.from_person = tmpelement.text if tmpelement != nil
|
35
|
-
|
36
|
-
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/FromEmail')
|
37
|
-
msg.from_email = tmpelement.text if tmpelement != nil
|
38
|
-
|
39
|
-
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/SentDate')
|
40
|
-
tmpdate = Date.civil(tmpelement.text[0,4].to_i, tmpelement.text[4,2].to_i, tmpelement.text[6,2].to_i) if tmpelement != nil
|
41
|
-
msg.sent_date = tmpdate if tmpdate != nil
|
42
|
-
|
43
|
-
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/ToCompany')
|
44
|
-
msg.to_company = tmpelement.text if tmpelement != nil
|
45
|
-
|
46
|
-
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/ToPerson')
|
47
|
-
msg.to_person = tmpelement.text if tmpelement != nil
|
48
|
-
|
49
|
-
products = REXML::XPath.each(doc, '/ONIXMessage/Product') { |product|
|
50
|
-
msg.add_product(Onix::Product.load_from_element(product))
|
51
|
-
}
|
52
|
-
|
53
|
-
return msg
|
54
|
-
end
|
14
|
+
def initialize
|
15
|
+
@products = []
|
16
|
+
end
|
55
17
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
18
|
+
# Attempts to create a message object using thge supplied xml document
|
19
|
+
def Message.load_from_xmldoc(doc)
|
20
|
+
raise ArgumentError, 'load_from_xmldoc expects a REXML document object' unless doc.class == REXML::Document
|
21
|
+
if REXML::XPath.first(doc, '/ONIXMessage/').nil? ||
|
22
|
+
REXML::XPath.first(doc, '/ONIXMessage/Header').nil? ||
|
23
|
+
REXML::XPath.first(doc, '/ONIXMessage/Product').nil?
|
24
|
+
raise LoadError, 'supplied REXML document object does not appear to be a valid ONIX file'
|
25
|
+
end
|
61
26
|
|
62
|
-
|
63
|
-
def to_s
|
64
|
-
doc = to_xml
|
65
|
-
output = ''
|
66
|
-
doc.write(output, 0)
|
67
|
-
return output
|
68
|
-
end
|
27
|
+
msg = Onix::Message.new
|
69
28
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
29
|
+
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/FromCompany')
|
30
|
+
msg.from_company = tmpelement.text if tmpelement != nil
|
31
|
+
|
32
|
+
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/FromPerson')
|
33
|
+
msg.from_person = tmpelement.text if tmpelement != nil
|
34
|
+
|
35
|
+
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/FromEmail')
|
36
|
+
msg.from_email = tmpelement.text if tmpelement != nil
|
37
|
+
|
38
|
+
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/SentDate')
|
39
|
+
tmpdate = Date.civil(tmpelement.text[0,4].to_i, tmpelement.text[4,2].to_i, tmpelement.text[6,2].to_i) if tmpelement != nil
|
40
|
+
msg.sent_date = tmpdate if tmpdate != nil
|
41
|
+
|
42
|
+
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/ToCompany')
|
43
|
+
msg.to_company = tmpelement.text if tmpelement != nil
|
44
|
+
|
45
|
+
tmpelement = REXML::XPath.first(doc, '/ONIXMessage/Header/ToPerson')
|
46
|
+
msg.to_person = tmpelement.text if tmpelement != nil
|
47
|
+
|
48
|
+
products = REXML::XPath.each(doc, '/ONIXMessage/Product') { |product|
|
49
|
+
msg.add_product(Onix::Product.load_from_element(product))
|
50
|
+
}
|
51
|
+
|
52
|
+
return msg
|
53
|
+
end
|
54
|
+
|
55
|
+
# Adds a new product to this message
|
56
|
+
def add_product(product)
|
57
|
+
raise ArgumentError, 'Argument must be a Onix::Product' if product.class != Onix::Product
|
58
|
+
@products << product
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns an XML string representing this message
|
62
|
+
def to_s
|
63
|
+
doc = to_xml
|
64
|
+
output = ''
|
65
|
+
doc.write(output, 0)
|
66
|
+
return output
|
67
|
+
end
|
90
68
|
|
91
|
-
|
92
|
-
|
93
|
-
|
69
|
+
def header
|
70
|
+
raise 'from_compnay must be set to create an onix message' if from_company == nil
|
71
|
+
raise 'from_person must be set to create an onix message' if from_person == nil
|
94
72
|
|
95
|
-
|
96
|
-
|
73
|
+
header = REXML::Element.new('Header')
|
74
|
+
header.add_element('FromCompany').text = from_company.to_xs
|
75
|
+
header.add_element('FromPerson').text = from_person.to_xs
|
76
|
+
header.add_element('FromEmail').text = from_email.to_xs unless from_email.nil?
|
77
|
+
header.add_element('MessageNote').text = message_note.to_xs unless message_note.nil?
|
78
|
+
header.add_element('ToCompany').text = to_company.to_xs unless to_company.nil?
|
79
|
+
header.add_element('ToPerson').text = to_person.to_xs unless to_person.nil?
|
97
80
|
|
98
|
-
|
81
|
+
now = Time.now
|
82
|
+
header.add_element('SentDate').text = "%.4d%.2d%.2d" % [ now.year, now.month, now.day ]
|
83
|
+
return header
|
84
|
+
end
|
85
|
+
|
86
|
+
# Returns an XML document representing this message
|
87
|
+
def to_xml
|
88
|
+
raise 'There must be at least 1 product to burn' if @products.size < 1
|
99
89
|
|
100
|
-
|
90
|
+
doc = REXML::Document.new
|
91
|
+
doc << REXML::XMLDecl.new
|
92
|
+
doc << REXML::DocType.new('ONIXMessage', "SYSTEM \"#{ONIX_DTD_URL}\"")
|
93
|
+
msg = doc.add_element('ONIXMessage')
|
94
|
+
msg.add_element(header)
|
95
|
+
|
96
|
+
@products.each do |product|
|
97
|
+
prod = msg.add_element(product.to_element)
|
98
|
+
end
|
99
|
+
|
100
|
+
return doc
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
101
106
|
end
|
data/lib/rbook/onix/product.rb
CHANGED
@@ -2,187 +2,188 @@ require 'rexml/document'
|
|
2
2
|
require 'rubygems'
|
3
3
|
|
4
4
|
module RBook
|
5
|
-
module Onix
|
6
|
-
class Product
|
7
|
-
|
8
|
-
attr_accessor :record_reference, :notification_type, :product_identifier, :title, :subtitle, :pages, :publication_date, :price, :description, :form, :bicmainsubject, :publisher, :supplier, :website, :edition
|
9
|
-
attr_reader :contributors, :sales_restrictions, :supply_details
|
10
|
-
|
11
|
-
def initialize
|
12
|
-
@contributors = []
|
13
|
-
@supply_details = []
|
14
|
-
@sales_restrictions = []
|
15
|
-
end
|
16
|
-
|
17
|
-
# Attempts to create a product object using the supplied xml element
|
18
|
-
def Product.load_from_element(element)
|
19
|
-
raise ArgumentError, 'load_from_element expects a REXML element object' unless element.class == REXML::Element
|
20
|
-
|
21
|
-
if REXML::XPath.first(element, '//Product').nil?
|
22
|
-
raise LoadError, 'supplied REXML document object does not appear contain a valid product fragment'
|
23
|
-
end
|
24
|
-
|
25
|
-
product = Product.new
|
26
|
-
|
27
|
-
tmp = REXML::XPath.first(element, '//Product/RecordReference')
|
28
|
-
product.record_reference = tmp.text if tmp != nil
|
29
|
-
|
30
|
-
tmp = REXML::XPath.first(element, '//Product/NotificationType')
|
31
|
-
product.notification_type = tmp.text if tmp != nil
|
32
|
-
|
33
|
-
# TODO: load ProductIdentifier from the fragment
|
34
|
-
|
35
|
-
tmp = REXML::XPath.first(element, '//Product/ProductForm')
|
36
|
-
product.form = tmp.text if tmp != nil
|
37
|
-
|
38
|
-
tmp = REXML::XPath.first(element, '//Product/NumberOfPages')
|
39
|
-
product.pages = tmp.text if tmp != nil
|
40
|
-
|
41
|
-
tmp = REXML::XPath.first(element, '//Product/BICMainSubject')
|
42
|
-
product.bicmainsubject = tmp.text if tmp != nil
|
43
|
-
|
44
|
-
tmp = REXML::XPath.first(element, '//Product/DistinctiveTitle')
|
45
|
-
if !tmp.nil?
|
46
|
-
product.title = tmp.text
|
47
|
-
tmp = REXML::XPath.first(element, '//Product/Subtitle') if !tmp.nil?
|
48
|
-
product.subtitle = tmp.text
|
49
|
-
else
|
50
|
-
tmp = REXML::XPath.first(element, '//Product/Title/TitleText')
|
51
|
-
product.title = tmp.text unless tmp.nil?
|
52
|
-
tmp = REXML::XPath.first(element, '//Product/Title/Subtitle')
|
53
|
-
product.subtitle = tmp.text unless tmp.nil?
|
54
|
-
end
|
55
|
-
|
56
|
-
tmp = REXML::XPath.first(element, '//Product/EditionNumber')
|
57
|
-
product.edition = tmp.text if tmp != nil
|
58
|
-
|
59
|
-
tmp = REXML::XPath.first(element, '//Product/PublicationDate')
|
60
|
-
tmpdate = Date.civil(tmp.text[0,4].to_i, tmp.text[4,2].to_i, tmp.text[6,2].to_i) if tmp != nil
|
61
|
-
product.publication_date = tmpdate if tmpdate != nil
|
62
|
-
|
63
|
-
tmp = REXML::XPath.first(element, '//Product/Publisher/PublisherName')
|
64
|
-
product.publisher = tmp.text if tmp != nil
|
65
|
-
|
66
|
-
REXML::XPath.each(element, '//Product/Contributor') { |contributor|
|
67
|
-
product.add_contributor(Onix::Contributor.load_from_element(contributor))
|
68
|
-
}
|
69
|
-
|
70
|
-
REXML::XPath.each(element, '//Product/SupplyDetail') { |detail|
|
71
|
-
product.add_supply_detail(Onix::SupplyDetail.load_from_element(detail))
|
72
|
-
}
|
73
|
-
|
74
|
-
return product
|
75
|
-
end
|
76
|
-
|
77
|
-
# Add a new contributor to this product
|
78
|
-
def add_contributor(newAuthor)
|
79
|
-
raise ArgumentError, 'Argument to add_contributor must be an ONIX::Contributor' if newAuthor.class != Contributor
|
80
|
-
@contributors << newAuthor
|
81
|
-
end
|
82
|
-
|
83
|
-
# Add a new contributor to this product
|
84
|
-
def add_sales_restriction(restriction)
|
85
|
-
raise ArgumentError, 'Argument to add_sales_restriction must be an ONIX::SalesRestriction' if restriction.class != SalesRestriction
|
86
|
-
@sales_restrictions << restriction
|
87
|
-
end
|
88
|
-
|
89
|
-
# Add a new contributor to this product
|
90
|
-
def add_supply_detail(detail)
|
91
|
-
raise ArgumentError, 'Argument to add_supply_detail must be an ONIX::SupplyDetail' if detail.class != SupplyDetail
|
92
|
-
@supply_details << detail
|
93
|
-
end
|
94
|
-
|
95
|
-
# Return an xml element representing this contributor
|
96
|
-
def to_element
|
97
|
-
raise 'product_identifier must be set' if self.product_identifier.nil?
|
98
|
-
|
99
|
-
product = REXML::Element.new('Product')
|
100
|
-
|
101
|
-
if self.record_reference
|
102
|
-
product.add_element('RecordReference').text = self.record_reference
|
103
|
-
else
|
104
|
-
product.add_element('RecordReference').text = self.product_identifier
|
105
|
-
end
|
106
|
-
|
107
|
-
product.add_element('NotificationType').text = '03'
|
108
|
-
|
109
|
-
product_identifier = REXML::Element.new('ProductIdentifier')
|
110
|
-
if ISBN::valid_isbn13?(self.product_identifier)
|
111
|
-
product_identifier.add_element('ProductIDType').text = '03'
|
112
|
-
elsif ISBN::valid_isbn10?(self.product_identifier)
|
113
|
-
product_identifier.add_element('ProductIDType').text = '02'
|
114
|
-
else
|
115
|
-
product_identifier.add_element('ProductIDType').text = '01'
|
116
|
-
end
|
117
|
-
product_identifier.add_element('IDValue').text = self.product_identifier.to_xs
|
118
|
-
product.add_element(product_identifier)
|
119
|
-
|
120
|
-
if form != nil
|
121
|
-
product.add_element('ProductForm').text = self.form.to_xs
|
122
|
-
end
|
123
|
-
|
124
|
-
product.add_element('NoSeries')
|
125
|
-
|
126
|
-
title = REXML::Element.new('Title')
|
127
|
-
title.add_element('TitleType').text = '01'
|
128
|
-
title.add_element('TitleText').text = self.title.to_xs unless self.title.nil?
|
129
|
-
title.add_element('Subtitle').text = self.subtitle.to_xs unless self.subtitle.nil?
|
130
|
-
product.add_element(title)
|
131
|
-
|
132
|
-
if website != nil
|
133
|
-
product_website = REXML::Element.new('Website')
|
134
|
-
product_website.add_element('WebsiteLink').text = self.website.to_xs
|
135
|
-
product.add_element(product_website)
|
136
|
-
end
|
137
|
-
|
138
|
-
contributors.each do |contributor|
|
139
|
-
product.add_element(contributor.to_element)
|
140
|
-
end
|
141
|
-
|
142
|
-
product.add_element('NoEdition')
|
143
|
-
|
144
|
-
product.add_element('NumberOfPages').text = self.pages.to_s unless self.pages.nil?
|
145
|
-
|
146
|
-
if bicmainsubject != nil
|
147
|
-
product.add_element('BICMainSubject').text = self.bicmainsubject.to_xs
|
148
|
-
end
|
5
|
+
module Onix
|
6
|
+
class Product
|
149
7
|
|
150
|
-
|
151
|
-
|
152
|
-
other_text.add_element('TextTypeCode').text = '01'
|
153
|
-
other_text.add_element('Text').text = self.description.to_xs
|
154
|
-
product.add_element(other_text)
|
155
|
-
end
|
156
|
-
|
157
|
-
if publisher != nil
|
158
|
-
publisher = REXML::Element.new('Publisher')
|
159
|
-
publisher.add_element('PublishingRole').text = '01'
|
160
|
-
publisher.add_element('PublisherName').text = self.publisher.to_xs
|
161
|
-
product.add_element(publisher)
|
162
|
-
end
|
8
|
+
attr_accessor :record_reference, :notification_type, :product_identifier, :title, :subtitle, :pages, :publication_date, :price, :description, :form, :bicmainsubject, :publisher, :supplier, :website, :edition
|
9
|
+
attr_reader :contributors, :sales_restrictions, :supply_details
|
163
10
|
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
11
|
+
def initialize
|
12
|
+
@contributors = []
|
13
|
+
@supply_details = []
|
14
|
+
@sales_restrictions = []
|
15
|
+
end
|
16
|
+
|
17
|
+
# Attempts to create a product object using the supplied xml element
|
18
|
+
def Product.load_from_element(element)
|
19
|
+
raise ArgumentError, 'load_from_element expects a REXML element object' unless element.class == REXML::Element
|
20
|
+
|
21
|
+
if REXML::XPath.first(element, '//Product').nil?
|
22
|
+
raise LoadError, 'supplied REXML document object does not appear contain a valid product fragment'
|
23
|
+
end
|
24
|
+
|
25
|
+
product = Product.new
|
26
|
+
|
27
|
+
tmp = REXML::XPath.first(element, '//Product/RecordReference')
|
28
|
+
product.record_reference = tmp.text if tmp != nil
|
29
|
+
|
30
|
+
tmp = REXML::XPath.first(element, '//Product/NotificationType')
|
31
|
+
product.notification_type = tmp.text if tmp != nil
|
32
|
+
|
33
|
+
tmp = REXML::XPath.first(element, '//Product/ProductIdentifier/IDValue')
|
34
|
+
product.product_identifier = tmp.text if tmp != nil
|
35
|
+
|
36
|
+
tmp = REXML::XPath.first(element, '//Product/ProductForm')
|
37
|
+
product.form = tmp.text if tmp != nil
|
38
|
+
|
39
|
+
tmp = REXML::XPath.first(element, '//Product/NumberOfPages')
|
40
|
+
product.pages = tmp.text if tmp != nil
|
41
|
+
|
42
|
+
tmp = REXML::XPath.first(element, '//Product/BICMainSubject')
|
43
|
+
product.bicmainsubject = tmp.text if tmp != nil
|
44
|
+
|
45
|
+
tmp = REXML::XPath.first(element, '//Product/DistinctiveTitle')
|
46
|
+
if !tmp.nil?
|
47
|
+
product.title = tmp.text
|
48
|
+
tmp = REXML::XPath.first(element, '//Product/Subtitle') if !tmp.nil?
|
49
|
+
product.subtitle = tmp.text
|
50
|
+
else
|
51
|
+
tmp = REXML::XPath.first(element, '//Product/Title/TitleText')
|
52
|
+
product.title = tmp.text unless tmp.nil?
|
53
|
+
tmp = REXML::XPath.first(element, '//Product/Title/Subtitle')
|
54
|
+
product.subtitle = tmp.text unless tmp.nil?
|
55
|
+
end
|
56
|
+
|
57
|
+
tmp = REXML::XPath.first(element, '//Product/EditionNumber')
|
58
|
+
product.edition = tmp.text if tmp != nil
|
59
|
+
|
60
|
+
tmp = REXML::XPath.first(element, '//Product/PublicationDate')
|
61
|
+
tmpdate = Date.civil(tmp.text[0,4].to_i, tmp.text[4,2].to_i, tmp.text[6,2].to_i) if tmp != nil
|
62
|
+
product.publication_date = tmpdate if tmpdate != nil
|
63
|
+
|
64
|
+
tmp = REXML::XPath.first(element, '//Product/Publisher/PublisherName')
|
65
|
+
product.publisher = tmp.text if tmp != nil
|
66
|
+
|
67
|
+
REXML::XPath.each(element, '//Product/Contributor') { |contributor|
|
68
|
+
product.add_contributor(Onix::Contributor.load_from_element(contributor))
|
69
|
+
}
|
70
|
+
|
71
|
+
REXML::XPath.each(element, '//Product/SupplyDetail') { |detail|
|
72
|
+
product.add_supply_detail(Onix::SupplyDetail.load_from_element(detail))
|
73
|
+
}
|
74
|
+
|
75
|
+
return product
|
76
|
+
end
|
77
|
+
|
78
|
+
# Add a new contributor to this product
|
79
|
+
def add_contributor(newAuthor)
|
80
|
+
raise ArgumentError, 'Argument to add_contributor must be an ONIX::Contributor' if newAuthor.class != Contributor
|
81
|
+
@contributors << newAuthor
|
82
|
+
end
|
83
|
+
|
84
|
+
# Add a new contributor to this product
|
85
|
+
def add_sales_restriction(restriction)
|
86
|
+
raise ArgumentError, 'Argument to add_sales_restriction must be an ONIX::SalesRestriction' if restriction.class != SalesRestriction
|
87
|
+
@sales_restrictions << restriction
|
88
|
+
end
|
89
|
+
|
90
|
+
# Add a new contributor to this product
|
91
|
+
def add_supply_detail(detail)
|
92
|
+
raise ArgumentError, 'Argument to add_supply_detail must be an ONIX::SupplyDetail' if detail.class != SupplyDetail
|
93
|
+
@supply_details << detail
|
94
|
+
end
|
95
|
+
|
96
|
+
# Return an xml element representing this contributor
|
97
|
+
def to_element
|
98
|
+
raise 'product_identifier must be set' if self.product_identifier.nil?
|
99
|
+
|
100
|
+
product = REXML::Element.new('Product')
|
101
|
+
|
102
|
+
if self.record_reference
|
103
|
+
product.add_element('RecordReference').text = self.record_reference
|
104
|
+
else
|
105
|
+
product.add_element('RecordReference').text = self.product_identifier
|
106
|
+
end
|
107
|
+
|
108
|
+
product.add_element('NotificationType').text = '03'
|
109
|
+
|
110
|
+
product_identifier = REXML::Element.new('ProductIdentifier')
|
111
|
+
if ISBN::valid_isbn13?(self.product_identifier)
|
112
|
+
product_identifier.add_element('ProductIDType').text = '03'
|
113
|
+
elsif ISBN::valid_isbn10?(self.product_identifier)
|
114
|
+
product_identifier.add_element('ProductIDType').text = '02'
|
115
|
+
else
|
116
|
+
product_identifier.add_element('ProductIDType').text = '01'
|
117
|
+
end
|
118
|
+
product_identifier.add_element('IDValue').text = self.product_identifier.to_xs
|
119
|
+
product.add_element(product_identifier)
|
120
|
+
|
121
|
+
if form != nil
|
122
|
+
product.add_element('ProductForm').text = self.form.to_xs
|
123
|
+
end
|
124
|
+
|
125
|
+
product.add_element('NoSeries')
|
126
|
+
|
127
|
+
title = REXML::Element.new('Title')
|
128
|
+
title.add_element('TitleType').text = '01'
|
129
|
+
title.add_element('TitleText').text = self.title.to_xs unless self.title.nil?
|
130
|
+
title.add_element('Subtitle').text = self.subtitle.to_xs unless self.subtitle.nil?
|
131
|
+
product.add_element(title)
|
132
|
+
|
133
|
+
if website != nil
|
134
|
+
product_website = REXML::Element.new('Website')
|
135
|
+
product_website.add_element('WebsiteLink').text = self.website.to_xs
|
136
|
+
product.add_element(product_website)
|
137
|
+
end
|
138
|
+
|
139
|
+
contributors.each do |contributor|
|
140
|
+
product.add_element(contributor.to_element)
|
141
|
+
end
|
142
|
+
|
143
|
+
product.add_element('NoEdition')
|
144
|
+
|
145
|
+
product.add_element('NumberOfPages').text = self.pages.to_s unless self.pages.nil?
|
146
|
+
|
147
|
+
if bicmainsubject != nil
|
148
|
+
product.add_element('BICMainSubject').text = self.bicmainsubject.to_xs
|
149
|
+
end
|
150
|
+
|
151
|
+
if description != nil
|
152
|
+
other_text = REXML::Element.new('OtherText')
|
153
|
+
other_text.add_element('TextTypeCode').text = '01'
|
154
|
+
other_text.add_element('Text').text = self.description.to_xs
|
155
|
+
product.add_element(other_text)
|
156
|
+
end
|
157
|
+
|
158
|
+
if publisher != nil
|
159
|
+
publisher = REXML::Element.new('Publisher')
|
160
|
+
publisher.add_element('PublishingRole').text = '01'
|
161
|
+
publisher.add_element('PublisherName').text = self.publisher.to_xs
|
162
|
+
product.add_element(publisher)
|
163
|
+
end
|
164
|
+
|
165
|
+
supply_details.each do |detail|
|
166
|
+
product.add_element(detail.to_element)
|
167
|
+
end
|
168
|
+
|
169
|
+
sales_restrictions.each do |restriction|
|
170
|
+
product.add_element(restriction.to_element)
|
171
|
+
end
|
172
|
+
|
173
|
+
if publication_date != nil
|
174
|
+
product.add_element('PublicationDate').text = "%.4d%.2d%.2d" % [ publication_date.year, publication_date.month, publication_date.day ]
|
175
|
+
end
|
176
|
+
|
177
|
+
return product
|
178
|
+
end
|
179
|
+
|
180
|
+
# return an XML string representing this contributor
|
181
|
+
def to_s
|
182
|
+
output = ''
|
183
|
+
to_element.write(output, 0)
|
184
|
+
return output
|
185
|
+
end
|
174
186
|
end
|
175
187
|
|
176
|
-
return product
|
177
188
|
end
|
178
|
-
|
179
|
-
# return an XML string representing this contributor
|
180
|
-
def to_s
|
181
|
-
output = ''
|
182
|
-
to_element.write(output, 0)
|
183
|
-
return output
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
end
|
188
189
|
end
|