milkfarm-onix 0.7.7
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +136 -0
- data/README.markdown +40 -0
- data/TODO +14 -0
- data/dtd/2.1r3/iso-amsa.ent +173 -0
- data/dtd/2.1r3/iso-amsb.ent +146 -0
- data/dtd/2.1r3/iso-amsc.ent +49 -0
- data/dtd/2.1r3/iso-amsn.ent +117 -0
- data/dtd/2.1r3/iso-amso.ent +77 -0
- data/dtd/2.1r3/iso-amsr.ent +205 -0
- data/dtd/2.1r3/iso-box.ent +67 -0
- data/dtd/2.1r3/iso-cyr1.ent +94 -0
- data/dtd/2.1r3/iso-cyr2.ent +53 -0
- data/dtd/2.1r3/iso-dia.ent +41 -0
- data/dtd/2.1r3/iso-grk3.ent +70 -0
- data/dtd/2.1r3/iso-lat1.ent +89 -0
- data/dtd/2.1r3/iso-lat2.ent +148 -0
- data/dtd/2.1r3/iso-mfrk.ent +79 -0
- data/dtd/2.1r3/iso-mopf.ent +53 -0
- data/dtd/2.1r3/iso-mscr.ent +79 -0
- data/dtd/2.1r3/iso-num.ent +103 -0
- data/dtd/2.1r3/iso-num.old.ent +103 -0
- data/dtd/2.1r3/iso-pub.ent +110 -0
- data/dtd/2.1r3/iso-tech.ent +183 -0
- data/dtd/2.1r3/onix-international.dtd +1012 -0
- data/dtd/2.1r3/onix-xhtml.elt +672 -0
- data/dtd/2.1r3/reference.elt +4758 -0
- data/dtd/2.1r3/xhtml-special.ent +79 -0
- data/dtd/2.1r3/xhtml-symbol.ent +242 -0
- data/lib/onix/addressee_identifier.rb +12 -0
- data/lib/onix/apa_product.rb +731 -0
- data/lib/onix/audience_range.rb +26 -0
- data/lib/onix/common.rb +26 -0
- data/lib/onix/contributor.rb +27 -0
- data/lib/onix/header.rb +46 -0
- data/lib/onix/imprint.rb +15 -0
- data/lib/onix/language.rb +14 -0
- data/lib/onix/lists/audience_code.rb +17 -0
- data/lib/onix/lists/country_code.rb +257 -0
- data/lib/onix/lists/language_code.rb +498 -0
- data/lib/onix/lists/language_role.rb +18 -0
- data/lib/onix/lists/notification_type.rb +19 -0
- data/lib/onix/lists/product_availability.rb +32 -0
- data/lib/onix/lists/product_form.rb +99 -0
- data/lib/onix/lists/product_form_detail.rb +157 -0
- data/lib/onix/market_representation.rb +19 -0
- data/lib/onix/measure.rb +14 -0
- data/lib/onix/media_file.rb +16 -0
- data/lib/onix/normaliser.rb +187 -0
- data/lib/onix/other_text.rb +17 -0
- data/lib/onix/price.rb +21 -0
- data/lib/onix/product.rb +73 -0
- data/lib/onix/product_identifier.rb +13 -0
- data/lib/onix/publisher.rb +16 -0
- data/lib/onix/reader.rb +187 -0
- data/lib/onix/sales_restriction.rb +12 -0
- data/lib/onix/sender_identifier.rb +14 -0
- data/lib/onix/series.rb +57 -0
- data/lib/onix/series_identifier.rb +13 -0
- data/lib/onix/simple_product.rb +47 -0
- data/lib/onix/sl_product.rb +131 -0
- data/lib/onix/stock.rb +15 -0
- data/lib/onix/subject.rb +16 -0
- data/lib/onix/supply_detail.rb +32 -0
- data/lib/onix/title.rb +17 -0
- data/lib/onix/website.rb +14 -0
- data/lib/onix/writer.rb +86 -0
- data/lib/onix.rb +114 -0
- data/spec/apa_product_spec.rb +59 -0
- data/spec/audience_range_spec.rb +46 -0
- data/spec/contributor_spec.rb +42 -0
- data/spec/header_spec.rb +123 -0
- data/spec/imprint_spec.rb +39 -0
- data/spec/language_spec.rb +42 -0
- data/spec/market_representation_spec.rb +41 -0
- data/spec/measure_spec.rb +43 -0
- data/spec/media_file_spec.rb +42 -0
- data/spec/normaliser_spec.rb +125 -0
- data/spec/other_text_spec.rb +40 -0
- data/spec/price_spec.rb +40 -0
- data/spec/product_identifier_spec.rb +40 -0
- data/spec/product_spec.rb +96 -0
- data/spec/publisher_spec.rb +38 -0
- data/spec/reader_spec.rb +131 -0
- data/spec/sales_restriction_spec.rb +35 -0
- data/spec/sender_identifier.rb +40 -0
- data/spec/series_identifier_spec.rb +38 -0
- data/spec/series_spec.rb +34 -0
- data/spec/sl_product_spec.rb +48 -0
- data/spec/stock_spec.rb +44 -0
- data/spec/subject_spec.rb +40 -0
- data/spec/supply_detail_spec.rb +53 -0
- data/spec/title_spec.rb +43 -0
- data/spec/website_spec.rb +41 -0
- data/spec/writer_spec.rb +81 -0
- data/support/entities.txt +1499 -0
- data/support/extract.rb +25 -0
- data/support/switch-onix-2.1-short-to-reference.xsl +23 -0
- data/support/switch-onix-tagnames-1.1.xsl +25 -0
- data/support/switch-onix-tagnames-2.0.xsl +37 -0
- metadata +209 -0
data/lib/onix/reader.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
module ONIX
|
6
|
+
|
7
|
+
# This is the primary class for reading data from an ONIX file, and there's
|
8
|
+
# really not much to it
|
9
|
+
#
|
10
|
+
# Each file should contain a single header, and 1 or more products:
|
11
|
+
#
|
12
|
+
# reader = ONIX::Reader.new("somefile.xml")
|
13
|
+
#
|
14
|
+
# puts reader.header.inspect
|
15
|
+
#
|
16
|
+
# reader.each do |product|
|
17
|
+
# puts product.inspect
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# The header will be returned as an ONIX::Header object, and the product will
|
21
|
+
# be an ONIX::Product.
|
22
|
+
#
|
23
|
+
# The ONIX::Product class can be a bit of a hassle to work with, as data can be
|
24
|
+
# nested in it fairly deeply. To wrap all the products returned by the reader
|
25
|
+
# in a shim that provides simple accessor access to common attributes, pass the
|
26
|
+
# shim class as a second argument
|
27
|
+
#
|
28
|
+
# reader = ONIX::Reader.new("somefile.xml", ONIX::APAProduct)
|
29
|
+
#
|
30
|
+
# puts reader.header.inspect
|
31
|
+
#
|
32
|
+
# reader.each do |product|
|
33
|
+
# puts product.inspect
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# APAProduct stands for Australian Publishers Association and provides simple
|
37
|
+
# access to the ONIX attributes that are commonly used in the Australian market.
|
38
|
+
#
|
39
|
+
# As well as accessing the file header, there are handful of other read only
|
40
|
+
# attributes that might be useful
|
41
|
+
#
|
42
|
+
# reader = ONIX::Reader.new("somefile.xml", ONIX::APAProduct)
|
43
|
+
#
|
44
|
+
# puts reader.version
|
45
|
+
# puts reader.xml_lang
|
46
|
+
# puts reader.xml_version
|
47
|
+
# puts reader.encoding
|
48
|
+
#
|
49
|
+
# The version attribute is particuarly useful. There are multiple revisions of the
|
50
|
+
# ONIX spec, and you may need to handle the file differently based on what
|
51
|
+
# version it is.
|
52
|
+
#
|
53
|
+
class Reader
|
54
|
+
include Enumerable
|
55
|
+
|
56
|
+
attr_reader :header , :version, :xml_lang, :xml_version, :encoding
|
57
|
+
|
58
|
+
def initialize(input, product_klass = ::ONIX::Product)
|
59
|
+
if input.kind_of?(String)
|
60
|
+
@reader = LibXML::XML::Reader.file(input)
|
61
|
+
elsif input.kind_of?(IO)
|
62
|
+
@reader = LibXML::XML::Reader.io(input)
|
63
|
+
else
|
64
|
+
raise ArgumentError, "Unable to read from file or IO stream"
|
65
|
+
end
|
66
|
+
|
67
|
+
@product_klass = product_klass
|
68
|
+
|
69
|
+
@header = read_next
|
70
|
+
|
71
|
+
@xml_lang ||= @reader.xml_lang
|
72
|
+
@xml_version ||= @reader.xml_version.to_f
|
73
|
+
@encoding ||= encoding_const_to_name(@reader.encoding)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Iterate over all the products in an ONIX file
|
77
|
+
#
|
78
|
+
def each(&block)
|
79
|
+
while obj = read_next
|
80
|
+
yield obj
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def close
|
85
|
+
@reader.close if @reader
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# Walk the ONIX file, and grab the next header or product fragment.
|
91
|
+
#
|
92
|
+
def read_next
|
93
|
+
while @reader.read
|
94
|
+
|
95
|
+
if @reader.node_type == LibXML::XML::Reader::TYPE_DOCUMENT_TYPE
|
96
|
+
# TODO restore ONIX version extraction. The following expand()
|
97
|
+
# call is triggering unpredictable behaviour in libxml-ruby
|
98
|
+
# 1.1.3 with libxml2 2.7.3. Sometimes segfaults, othertimes
|
99
|
+
# cryptic errors about the input file being truncated or
|
100
|
+
# incomplete
|
101
|
+
#uri = @reader.expand.to_s.dup
|
102
|
+
#m, major, minor, rev = *uri.match(/.+(\d)\.(\d)\/(\d*).*/)
|
103
|
+
#@version = [major.to_i, minor.to_i, rev.to_i]
|
104
|
+
elsif @reader.node_type == LibXML::XML::Reader::TYPE_ELEMENT
|
105
|
+
if @reader.name == "Header"
|
106
|
+
str = normalise_string_encoding(@reader.read_outer_xml.to_s.dup)
|
107
|
+
if str.size == 0
|
108
|
+
return ONIX::Header.new
|
109
|
+
else
|
110
|
+
return ONIX::Header.from_xml(str)
|
111
|
+
end
|
112
|
+
elsif @reader.name == "Product"
|
113
|
+
str = normalise_string_encoding(@reader.read_outer_xml.to_s.dup)
|
114
|
+
if str.size == 0
|
115
|
+
return @product_klass.new
|
116
|
+
else
|
117
|
+
return @product_klass.from_xml(str)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
return nil
|
124
|
+
rescue LibXML::XML::Error => e
|
125
|
+
return nil
|
126
|
+
end
|
127
|
+
|
128
|
+
# XML::Reader seems to transparently convert all input data to utf-8, howver
|
129
|
+
# on Ruby 1.9 it fails to correctly set the encoding on the strings.
|
130
|
+
#
|
131
|
+
def normalise_string_encoding(str)
|
132
|
+
if RUBY_VERSION >= "1.9"
|
133
|
+
return str.dup.force_encoding("utf-8")
|
134
|
+
else
|
135
|
+
str
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# simple mapping of encoding constants to a string
|
140
|
+
#
|
141
|
+
def encoding_const_to_name(const)
|
142
|
+
return nil if const.nil?
|
143
|
+
case const
|
144
|
+
when LibXML::XML::Encoding::UTF_8
|
145
|
+
"utf-8"
|
146
|
+
when LibXML::XML::Encoding::UTF_16LE
|
147
|
+
"utf-16le"
|
148
|
+
when LibXML::XML::Encoding::UTF_16BE
|
149
|
+
"utf-16be"
|
150
|
+
when LibXML::XML::Encoding::UCS_4LE
|
151
|
+
"ucs-4le"
|
152
|
+
when LibXML::XML::Encoding::UCS_4BE
|
153
|
+
"ucs-4be"
|
154
|
+
when LibXML::XML::Encoding::UCS_2
|
155
|
+
"ucs-2"
|
156
|
+
when LibXML::XML::Encoding::ISO_8859_1
|
157
|
+
"iso-8859-1"
|
158
|
+
when LibXML::XML::Encoding::ISO_8859_2
|
159
|
+
"iso-8859-2"
|
160
|
+
when LibXML::XML::Encoding::ISO_8859_3
|
161
|
+
"iso-8859-3"
|
162
|
+
when LibXML::XML::Encoding::ISO_8859_4
|
163
|
+
"iso-8859-4"
|
164
|
+
when LibXML::XML::Encoding::ISO_8859_5
|
165
|
+
"iso-8859-5"
|
166
|
+
when LibXML::XML::Encoding::ISO_8859_6
|
167
|
+
"iso-8859-6"
|
168
|
+
when LibXML::XML::Encoding::ISO_8859_7
|
169
|
+
"iso-8859-7"
|
170
|
+
when LibXML::XML::Encoding::ISO_8859_8
|
171
|
+
"iso-8859-8"
|
172
|
+
when LibXML::XML::Encoding::ISO_8859_9
|
173
|
+
"iso-8859-9"
|
174
|
+
when LibXML::XML::Encoding::ISO_2022_JP
|
175
|
+
"iso-2022-jp"
|
176
|
+
when LibXML::XML::Encoding::SHIFT_JIS
|
177
|
+
"shift-jis"
|
178
|
+
when LibXML::XML::Encoding::EUC_JP
|
179
|
+
"euc-jp"
|
180
|
+
when LibXML::XML::Encoding::ASCII
|
181
|
+
"ascii"
|
182
|
+
else
|
183
|
+
nil
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
class SalesRestriction
|
5
|
+
include ROXML
|
6
|
+
include ONIX::Common
|
7
|
+
|
8
|
+
xml_name "SalesRestriction"
|
9
|
+
|
10
|
+
xml_accessor :sales_restriction_type, :from =>"SalesRestrictionType", :as => Fixnum, :to_xml => ONIX::Formatters.two_digit
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
class SenderIdentifier
|
5
|
+
include ROXML
|
6
|
+
include ONIX::Common
|
7
|
+
|
8
|
+
xml_name "SenderIdentifier"
|
9
|
+
|
10
|
+
xml_accessor :sender_id_type, :from => "SenderIDType", :as => Fixnum, :to_xml => ONIX::Formatters.two_digit
|
11
|
+
xml_accessor :id_type_name, :from => "IDTypeName"
|
12
|
+
xml_accessor :id_value, :from => "IDValue"
|
13
|
+
end
|
14
|
+
end
|
data/lib/onix/series.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
class Series
|
5
|
+
include ROXML
|
6
|
+
include ONIX::Common
|
7
|
+
|
8
|
+
xml_name "Series"
|
9
|
+
|
10
|
+
xml_accessor :series_identifiers, :from => "SeriesIdentifier", :as => [ONIX::SeriesIdentifier]
|
11
|
+
xml_accessor :title_of_series, :from => "TitleOfSeries"
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
self.series_identifiers = []
|
15
|
+
end
|
16
|
+
|
17
|
+
# retrieve the proprietary series ID
|
18
|
+
def proprietary_series_id
|
19
|
+
series_identifier(1).andand.id_value
|
20
|
+
end
|
21
|
+
|
22
|
+
# set a new proprietary series ID
|
23
|
+
def proprietary_series_id=(id)
|
24
|
+
series_identifier_set(1, id)
|
25
|
+
end
|
26
|
+
|
27
|
+
# retrieve the issn
|
28
|
+
def issn
|
29
|
+
series_identifier(2).andand.id_value
|
30
|
+
end
|
31
|
+
|
32
|
+
# set a new issn
|
33
|
+
def issn=(id)
|
34
|
+
series_identifier_set(2, id)
|
35
|
+
end
|
36
|
+
|
37
|
+
# retrieve the value of a particular ID
|
38
|
+
def series_identifier(type)
|
39
|
+
identifier = series_identifiers.find { |id| id.series_id_type == type }
|
40
|
+
end
|
41
|
+
|
42
|
+
# set the value of a particular ID
|
43
|
+
def series_identifier_set(type, value)
|
44
|
+
series_indentifier_id = series_identifiers.find { |id| id.series_id_type == type }
|
45
|
+
|
46
|
+
# create a new series identifier record if we need to
|
47
|
+
if series_indentifier_id.nil?
|
48
|
+
series_indentifier_id = ONIX::SeriesIdentifier.new
|
49
|
+
end
|
50
|
+
|
51
|
+
series_indentifier_id.series_id_type = type
|
52
|
+
series_indentifier_id.id_value = value
|
53
|
+
|
54
|
+
series_identifiers << series_indentifier_id
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
class SeriesIdentifier
|
5
|
+
include ROXML
|
6
|
+
include ONIX::Common
|
7
|
+
|
8
|
+
xml_name "SeriesIdentifier"
|
9
|
+
|
10
|
+
xml_accessor :series_id_type, :from => "SeriesIDType", :as => Fixnum, :to_xml => ONIX::Formatters.two_digit
|
11
|
+
xml_accessor :id_value, :from => "IDValue"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
module ONIX
|
6
|
+
# super class for some simplified ONIX::Product wrappers
|
7
|
+
class SimpleProduct
|
8
|
+
|
9
|
+
def initialize(product = nil)
|
10
|
+
@product = product || ::ONIX::Product.new
|
11
|
+
end
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
include Forwardable
|
16
|
+
|
17
|
+
def from_xml(xml)
|
18
|
+
self.new(::ONIX::Product.from_xml(xml))
|
19
|
+
end
|
20
|
+
|
21
|
+
def parse_file(filename)
|
22
|
+
self.new(::ONIX::Product.parse(File.read(filename)))
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse(xml)
|
26
|
+
self.new(::ONIX::Product.parse(xml))
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def delegate(*args)
|
32
|
+
def_delegators :@product, *args
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def product
|
37
|
+
@product
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_xml
|
41
|
+
product.to_xml
|
42
|
+
end
|
43
|
+
|
44
|
+
# TODO: add method missing magic to proxy through to the underlying product?
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
class SLProduct < APAProduct
|
5
|
+
|
6
|
+
delegate :audience_code, :audience_code=
|
7
|
+
delegate :copyright_year, :copyright_year=
|
8
|
+
delegate :product_form_detail, :product_form_detail=
|
9
|
+
|
10
|
+
alias_method :old_initialize, :initialize
|
11
|
+
def initialize(*args)
|
12
|
+
result = old_initialize(*args)
|
13
|
+
result.audience_code = 4 # Primary & secondary/elementary & high school
|
14
|
+
result
|
15
|
+
end
|
16
|
+
|
17
|
+
# retrieve the value of a particular ID
|
18
|
+
def series(str)
|
19
|
+
product.series.find { |id| id.title_of_series == str }
|
20
|
+
end
|
21
|
+
|
22
|
+
# set the value of a particular ID
|
23
|
+
def series=(value)
|
24
|
+
# process based on value type
|
25
|
+
if value.is_a?(Series)
|
26
|
+
str = value.title_of_series
|
27
|
+
series_id = value
|
28
|
+
else
|
29
|
+
str = value
|
30
|
+
series_id = ONIX::Series.new
|
31
|
+
series_id.title_of_series = value
|
32
|
+
end
|
33
|
+
# check if exists already
|
34
|
+
unless series(str)
|
35
|
+
product.series << series_id
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# retrieve the "language of text" (role=1) language code for this particular product
|
40
|
+
def language_code
|
41
|
+
language(1).andand.language_code
|
42
|
+
end
|
43
|
+
|
44
|
+
# set a new "language of text" (role=1) language code for this particular product
|
45
|
+
def language_code=(str)
|
46
|
+
language_set(1, str)
|
47
|
+
end
|
48
|
+
|
49
|
+
# retrieve the "language of text" (role=1) country code for this particular product
|
50
|
+
def country_code
|
51
|
+
language(1).andand.country_code
|
52
|
+
end
|
53
|
+
|
54
|
+
# set a new "language of text" (role=1) country code for this particular product
|
55
|
+
def country_code=(str)
|
56
|
+
language_set(1, language_code, str)
|
57
|
+
end
|
58
|
+
|
59
|
+
# retrieve the value of a particular language
|
60
|
+
def language(type)
|
61
|
+
product.languages.find { |l| l.language_role == type }
|
62
|
+
end
|
63
|
+
|
64
|
+
# set the value of a particular language
|
65
|
+
def language_set(type, value, value2=nil)
|
66
|
+
l = language(type)
|
67
|
+
|
68
|
+
# create a new language record if we need to
|
69
|
+
if l.nil?
|
70
|
+
l = ONIX::Language.new
|
71
|
+
l.language_role = type
|
72
|
+
product.languages << l
|
73
|
+
end
|
74
|
+
|
75
|
+
# cannot set country_code without language_code
|
76
|
+
unless value.nil?
|
77
|
+
l.language_code = value.to_s # mandatory
|
78
|
+
l.country_code = value2.to_s if value2 # optional
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# retrieve the dewey for this title
|
83
|
+
def dewey
|
84
|
+
product.subjects.find { |sub| sub.subject_scheme_id.to_i == 1 } # dewey = 1, abridged dewey = 2
|
85
|
+
end
|
86
|
+
|
87
|
+
# add a dewey to the product
|
88
|
+
def dewey=(code)
|
89
|
+
add_subject code, "1" # dewey = 1, abridged dewey = 2
|
90
|
+
end
|
91
|
+
|
92
|
+
# audience_range_qualifier: 11 = US school grades
|
93
|
+
# audience_range_precision: 1 = exact, 3 = from, 4 = to
|
94
|
+
def us_grade_range
|
95
|
+
audience_range(11)
|
96
|
+
end
|
97
|
+
|
98
|
+
# set a new "audience of text" (role=1) country code for this particular product
|
99
|
+
def us_grade_range=(range=[])
|
100
|
+
audience_range_set(11, range[0], range[1])
|
101
|
+
end
|
102
|
+
|
103
|
+
# retrieve the value of a particular audience range
|
104
|
+
def audience_range(type)
|
105
|
+
product.audience_ranges.find { |a| a.audience_range_qualifier == type }
|
106
|
+
end
|
107
|
+
|
108
|
+
# set the value of a particular audience_range
|
109
|
+
def audience_range_set(type, min=nil, max=nil)
|
110
|
+
a = audience_range(type)
|
111
|
+
|
112
|
+
# create a new audience_range record if we need to
|
113
|
+
if a.nil?
|
114
|
+
a = ONIX::AudienceRange.new
|
115
|
+
a.audience_range_qualifier = type
|
116
|
+
product.audience_ranges << a
|
117
|
+
end
|
118
|
+
|
119
|
+
unless min.nil?
|
120
|
+
a.audience_range_precisions << "03"
|
121
|
+
a.audience_range_values << min
|
122
|
+
end
|
123
|
+
unless max.nil?
|
124
|
+
a.audience_range_precisions << "04"
|
125
|
+
a.audience_range_values << max
|
126
|
+
end
|
127
|
+
a.audience_range_precisions = ["01"] if min.nil? || max.nil?
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|
data/lib/onix/stock.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
class Stock
|
5
|
+
include ROXML
|
6
|
+
include ONIX::Common
|
7
|
+
|
8
|
+
xml_name "Stock"
|
9
|
+
|
10
|
+
# NOTE: these *should* be numeric fields according to the spec,
|
11
|
+
# but heaps of ONIX files in the wild use text
|
12
|
+
xml_accessor :on_hand, :from => "OnHand"
|
13
|
+
xml_accessor :on_order, :from => "OnOrder"
|
14
|
+
end
|
15
|
+
end
|
data/lib/onix/subject.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
class Subject
|
5
|
+
include ROXML
|
6
|
+
include ONIX::Common
|
7
|
+
|
8
|
+
xml_name "Subject"
|
9
|
+
|
10
|
+
xml_accessor :subject_scheme_id, :from => "SubjectSchemeIdentifier", :as => Fixnum, :to_xml => ONIX::Formatters.two_digit
|
11
|
+
xml_accessor :subject_scheme_name, :from => "SubjectSchemeName"
|
12
|
+
xml_accessor :subject_scheme_version, :from => "SubjectSchemeVersion"
|
13
|
+
xml_accessor :subject_code, :from => "SubjectCode"
|
14
|
+
xml_accessor :subject_heading_text, :from => "SubjectHeadingText"
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
class SupplyDetail
|
5
|
+
include ROXML
|
6
|
+
include ONIX::Common
|
7
|
+
|
8
|
+
xml_name "SupplyDetail"
|
9
|
+
|
10
|
+
xml_accessor :supplier_ean_location_number, :from => "SupplierEANLocationNumber"
|
11
|
+
xml_accessor :supplier_san, :from => "SupplierSAN"
|
12
|
+
xml_accessor :supplier_name, :from => "SupplierName"
|
13
|
+
xml_accessor :telephone_number, :from => "TelephoneNumber"
|
14
|
+
xml_accessor :fax_number, :from => "FaxNumber"
|
15
|
+
xml_accessor :email_address, :from => "EmailAddress"
|
16
|
+
xml_accessor :websites, :from => "Website", :as => [ONIX::Website]
|
17
|
+
xml_accessor :supplier_role, :from => "SupplierRole", :as => Fixnum, :to_xml => ONIX::Formatters.two_digit
|
18
|
+
xml_accessor :supply_to_country, :from => "SupplyToCountry"
|
19
|
+
xml_accessor :supply_to_territory, :from => "SupplyToTerritory"
|
20
|
+
xml_accessor :availability_status_code, :from => "AvailabilityStatusCode", :as => Fixnum, :to_xml => ONIX::Formatters.two_digit
|
21
|
+
xml_accessor :product_availability, :from => "ProductAvailability", :as => Fixnum, :to_xml => ONIX::Formatters.two_digit
|
22
|
+
xml_accessor :stock, :from => "Stock", :as => [ONIX::Stock]
|
23
|
+
xml_accessor :pack_quantity, :from => "PackQuantity", :as => Fixnum
|
24
|
+
xml_accessor :prices, :from => "Price", :as => [ONIX::Price]
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
self.websites = []
|
28
|
+
self.stock = []
|
29
|
+
self.prices = []
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/onix/title.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
class Title
|
5
|
+
include ROXML
|
6
|
+
include ONIX::Common
|
7
|
+
|
8
|
+
xml_name "Title"
|
9
|
+
|
10
|
+
xml_accessor :title_type, :from => "TitleType", :as => Fixnum, :to_xml => ONIX::Formatters.two_digit
|
11
|
+
xml_accessor :title_text, :from => "TitleText"
|
12
|
+
xml_accessor :title_prefix, :from => "TitlePrefix"
|
13
|
+
xml_accessor :title_without_prefix, :from => "TitleWithoutPrefix"
|
14
|
+
xml_accessor :subtitle, :from => "Subtitle"
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
data/lib/onix/website.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
class Website
|
5
|
+
include ROXML
|
6
|
+
include ONIX::Common
|
7
|
+
|
8
|
+
xml_name "Website"
|
9
|
+
|
10
|
+
xml_accessor :website_role, :from => "WebsiteRole", :as => Fixnum, :to_xml => ONIX::Formatters.two_digit
|
11
|
+
xml_accessor :website_description, :from => "WebsiteDescription"
|
12
|
+
xml_accessor :website_link, :from => "WebsiteLink"
|
13
|
+
end
|
14
|
+
end
|
data/lib/onix/writer.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module ONIX
|
4
|
+
# The primary way to write a new ONIX file.
|
5
|
+
#
|
6
|
+
# Heres a quick example. The generated file will be nice and boring, as the
|
7
|
+
# header and product objects have no data in them, but you get the idea.
|
8
|
+
#
|
9
|
+
# File.open("output.xml","w") do |output|
|
10
|
+
# header = ONIX::Header.new
|
11
|
+
# ONIX::Writer.open(output, header) do |writer|
|
12
|
+
# writer << ONIX::Product.new
|
13
|
+
# writer << ONIX::Product.new
|
14
|
+
# end
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# If you prefer, you can build your products using the APAProduct shim layer.
|
18
|
+
#
|
19
|
+
# File.open("output.xml","w") do |output|
|
20
|
+
# header = ONIX::Header.new
|
21
|
+
# ONIX::Writer.open(output, header) do |writer|
|
22
|
+
# writer << ONIX::APAProduct.new
|
23
|
+
# writer << ONIX::APAProduct.new
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
class Writer
|
28
|
+
|
29
|
+
DOCTYPE = "http://www.editeur.org/onix/2.1/03/reference/onix-international.dtd"
|
30
|
+
|
31
|
+
# Default constructor.
|
32
|
+
def initialize(output, header)
|
33
|
+
raise ArgumentError, 'msg must be an ONIX::Header object' unless header.kind_of?(ONIX::Header)
|
34
|
+
@output = output
|
35
|
+
@header = header
|
36
|
+
@finished = false
|
37
|
+
|
38
|
+
start_document
|
39
|
+
end
|
40
|
+
|
41
|
+
# deprecated
|
42
|
+
def start_document
|
43
|
+
puts "ONIX::StreamWriter#start_document is no longer required"
|
44
|
+
end
|
45
|
+
|
46
|
+
def << (product)
|
47
|
+
unless product.kind_of?(ONIX::Product) || product.kind_of?(ONIX::SimpleProduct)
|
48
|
+
raise ArgumentError, 'product must be an ONIX::Product or ONIX::SimpleProduct'
|
49
|
+
end
|
50
|
+
raise "Can't add products to a finished writer" if finished?
|
51
|
+
|
52
|
+
@output.write(product.to_xml.to_s)
|
53
|
+
@output.write("\n")
|
54
|
+
end
|
55
|
+
|
56
|
+
def end_document
|
57
|
+
@output.write("</ONIXMessage>\n")
|
58
|
+
@finished = true
|
59
|
+
end
|
60
|
+
|
61
|
+
def finished?
|
62
|
+
@finished
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.open(output, header)
|
66
|
+
if block_given?
|
67
|
+
writer = self.new(output, header)
|
68
|
+
yield writer
|
69
|
+
writer.end_document
|
70
|
+
else
|
71
|
+
self.new(output, header)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def start_document
|
78
|
+
@output.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
|
79
|
+
@output.write("<!DOCTYPE ONIXMessage SYSTEM \"#{DOCTYPE}\">\n")
|
80
|
+
@output.write("<ONIXMessage>\n")
|
81
|
+
@output.write(@header.to_xml.to_s)
|
82
|
+
@output.write("\n")
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|