onix 0.4.0

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.
@@ -0,0 +1,7 @@
1
+ module ONIX
2
+ class SalesRestriction
3
+ include ROXML
4
+
5
+ xml_accessor :sales_restriction_type, :twodigit, :from =>"SalesRestrictionType"
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module ONIX
2
+ class SenderIdentifier
3
+ include ROXML
4
+
5
+ xml_accessor :sender_id_type, :from => "SenderIDType"
6
+ xml_accessor :id_type_name, :from => "IDTypeName"
7
+ xml_accessor :id_value, :from => "IDValue"
8
+ end
9
+ end
@@ -0,0 +1,41 @@
1
+ require 'forwardable'
2
+
3
+ module ONIX
4
+ # super class for some simplified ONIX::Product wrappers
5
+ class SimpleProduct
6
+
7
+ def initialize(product = nil)
8
+ @product = product || ::ONIX::Product.new
9
+ end
10
+
11
+ class << self
12
+
13
+ include Forwardable
14
+
15
+ def parse_file(filename)
16
+ self.new(::ONIX::Product.parse(File.read(filename)))
17
+ end
18
+
19
+ def parse(xml)
20
+ self.new(::ONIX::Product.parse(xml))
21
+ end
22
+
23
+ protected
24
+
25
+ def delegate(*args)
26
+ def_delegators :@product, *args
27
+ end
28
+ end
29
+
30
+ def product
31
+ @product
32
+ end
33
+
34
+ def to_xml
35
+ product.to_xml
36
+ end
37
+
38
+ # TODO: add method missing magic to proxy through to the underlying product?
39
+
40
+ end
41
+ end
data/lib/onix/stock.rb ADDED
@@ -0,0 +1,10 @@
1
+ module ONIX
2
+ class Stock
3
+ include ROXML
4
+
5
+ # NOTE: these *should* be numeric fields according to the spec,
6
+ # but heaps of ONIX files in the wild use text
7
+ xml_accessor :on_hand, :from => "OnHand"
8
+ xml_accessor :on_order, :from => "OnOrder"
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module ONIX
2
+ class Subject
3
+ include ROXML
4
+
5
+ xml_accessor :subject_scheme_id, :twodigit, :from => "SubjectSchemeIdentifier"
6
+ xml_accessor :subject_scheme_name, :from => "SubjectSchemeName"
7
+ xml_accessor :subject_scheme_version, :from => "SubjectSchemeVersion"
8
+ xml_accessor :subject_code, :from => "SubjectCode"
9
+ xml_accessor :subject_heading_text, :from => "SubjectHeadingText"
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ module ONIX
2
+ class SupplyDetail
3
+ include ROXML
4
+
5
+ xml_accessor :supplier_ean_location_number, :from => "SupplierEANLocationNumber"
6
+ xml_accessor :supplier_san, :from => "SupplierSAN"
7
+ xml_accessor :supplier_name, :from => "SupplierName"
8
+ xml_accessor :telephone_number, :from => "TelephoneNumber"
9
+ xml_accessor :fax_number, :from => "FaxNumber"
10
+ xml_accessor :email_address, :from => "EmailAddress"
11
+ xml_accessor :websites, [ONIX::Website], :from => "Website"
12
+ xml_accessor :supplier_role, :twodigit, :from => "SupplierRole"
13
+ xml_accessor :supply_to_country, :from => "SupplyToCountry"
14
+ xml_accessor :supply_to_territory, :from => "SupplyToTerritory"
15
+ xml_accessor :availability_status_code, :twodigit, :from => "AvailabilityStatusCode"
16
+ xml_accessor :product_availability, :twodigit, :from => "ProductAvailability"
17
+ xml_accessor :stock, [ONIX::Stock], :from => "Stock"
18
+ xml_accessor :prices, [ONIX::Price], :from => "Price"
19
+
20
+ end
21
+ end
data/lib/onix/title.rb ADDED
@@ -0,0 +1,10 @@
1
+ module ONIX
2
+ class Title
3
+ include ROXML
4
+
5
+ xml_accessor :title_type, :twodigit, :from => "TitleType"
6
+ xml_accessor :title_text, :etext, :from => "TitleText"
7
+ xml_accessor :subtitle, :etext, :from => "Subtitle"
8
+
9
+ end
10
+ end
@@ -0,0 +1,57 @@
1
+
2
+ module ONIX
3
+
4
+ # Internal class representing 2-digit XML content
5
+ #
6
+ # In context:
7
+ # <element attribute="XMLAttributeRef">
8
+ # XMLTwoDigitRef
9
+ # </element>
10
+ class TwoDigitType < ROXML::XMLRef # ::nodoc::
11
+ attr_reader :cdata, :content
12
+
13
+ def initialize(accessor, args, &block)
14
+ super(accessor, args, &block)
15
+ @content = args.content?
16
+ @cdata = args.cdata?
17
+ end
18
+
19
+ # Updates the text in the given _xml_ block to
20
+ # the _value_ provided.
21
+ def update_xml(xml, value)
22
+ parent = wrap(xml)
23
+ value = value.to_i
24
+ if value < 10
25
+ value = "0#{value}"
26
+ elsif value < 100
27
+ value = value.to_s
28
+ else
29
+ value = "00"
30
+ end
31
+ add(parent.child_add(LibXML::XML::Node.new_element(name)), value)
32
+ xml
33
+ end
34
+
35
+ def value(xml)
36
+ if content
37
+ value = xml.content.to_i
38
+ else
39
+ child = xml.search(name).first
40
+ value = child.content.to_i if child
41
+ end
42
+ block ? block.call(value) : value
43
+ end
44
+
45
+ private
46
+
47
+ def add(dest, value)
48
+ if cdata
49
+ dest.child_add(LibXML::XML::Node.new_cdata(value.to_utf))
50
+ else
51
+ dest.content = value.to_utf
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ ROXML::TypeRegistry.register(:twodigit, ONIX::TwoDigitType)
@@ -0,0 +1,9 @@
1
+ module ONIX
2
+ class Website
3
+ include ROXML
4
+
5
+ xml_accessor :website_role, :twodigit, :from => "WebsiteRole"
6
+ xml_accessor :website_description, :from => "WebsiteDescription"
7
+ xml_accessor :website_link, :from => "WebsiteLink"
8
+ end
9
+ end
@@ -0,0 +1,87 @@
1
+ module ONIX
2
+ # The primary way to write a new ONIX file.
3
+ #
4
+ # Heres a quick example. The generated file will be nice and boring, as the
5
+ # header and product objects have no data in them, but you get the idea.
6
+ #
7
+ # File.open("output.xml","w") do |output|
8
+ # header = ONIX::Header.new
9
+ # ONIX::Writer.open(output, header) do |writer|
10
+ # writer << ONIX::Product.new
11
+ # writer << ONIX::Product.new
12
+ # end
13
+ # end
14
+ #
15
+ # If you prefer, you can build your products using the APAProduct shim layer.
16
+ #
17
+ # File.open("output.xml","w") do |output|
18
+ # header = ONIX::Header.new
19
+ # ONIX::Writer.open(output, header) do |writer|
20
+ # writer << ONIX::APAProduct.new
21
+ # writer << ONIX::APAProduct.new
22
+ # end
23
+ # end
24
+ #
25
+ class Writer
26
+
27
+ DOCTYPE = "http://www.editeur.org/onix/2.1/03/reference/onix-international.dtd"
28
+
29
+ # Default constructor.
30
+ def initialize(output, header)
31
+ raise ArgumentError, 'msg must be an ONIX::Header object' unless header.kind_of?(ONIX::Header)
32
+ @output = output
33
+ @header = header
34
+ @finished = false
35
+
36
+ start_document
37
+ end
38
+
39
+ # deprecated
40
+ def start_document
41
+ puts "ONIX::StreamWriter#start_document is no longer required"
42
+ end
43
+
44
+ def << (product)
45
+ unless product.kind_of?(ONIX::Product) || product.kind_of?(ONIX::SimpleProduct)
46
+ raise ArgumentError, 'product must be an ONIX::Product or ONIX::SimpleProduct'
47
+ end
48
+ raise "Can't add products to a finished writer" if finished?
49
+
50
+ @output.write(product.to_xml.to_s)
51
+ @output.write("\n")
52
+ end
53
+
54
+ def end_document
55
+ @output.write("</ONIXMessage>\n")
56
+ @finished = true
57
+ end
58
+
59
+ def finished?
60
+ @finished
61
+ end
62
+
63
+ def self.open(output, header)
64
+ if block_given?
65
+ writer = self.new(output, header)
66
+ yield writer
67
+ writer.end_document
68
+ else
69
+ self.new(output, header)
70
+ end
71
+ end
72
+
73
+ private
74
+
75
+ def start_document
76
+ decl = REXML::XMLDecl.new
77
+ doctype = REXML::DocType.new('ONIXMessage', "SYSTEM \"#{DOCTYPE}\"")
78
+ decl.encoding = "utf-8"
79
+ @output.write(decl.to_s+"\n")
80
+ @output.write(doctype.to_s+"\n")
81
+ @output.write("<ONIXMessage>\n")
82
+ @output.write(@header.to_xml.to_s)
83
+ @output.write("\n")
84
+ end
85
+
86
+ end
87
+ end
@@ -0,0 +1,111 @@
1
+ # coding: utf-8
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
4
+
5
+ require 'onix'
6
+
7
+ context "ONIX::Header" do
8
+
9
+ before(:each) do
10
+ data_path = File.join(File.dirname(__FILE__),"..","data")
11
+ file1 = File.join(data_path, "header.xml")
12
+ @doc = LibXML::XML::Document.file(file1)
13
+ @header_node = @doc.root
14
+ end
15
+
16
+ specify "should correctly convert to a string" do
17
+ header = ONIX::Header.parse(@header_node.to_s)
18
+ header.to_xml.to_s[0,8].should eql("<Header>")
19
+ end
20
+
21
+ specify "should provide read access to first level attibutes" do
22
+ header = ONIX::Header.parse(@header_node.to_s)
23
+
24
+ header.from_ean_number.should eql("1111111111111")
25
+ header.from_san.should eql("1111111")
26
+ header.from_company.should eql("Text Company")
27
+ header.from_email.should eql("james@rainbowbooks.com.au")
28
+ header.from_person.should eql("James")
29
+
30
+ header.to_ean_number.should eql("2222222222222")
31
+ header.to_san.should eql("2222222")
32
+ header.to_company.should eql("Company 2")
33
+ header.to_person.should eql("Chris")
34
+
35
+ header.message_note.should eql("A Message")
36
+ header.message_repeat.should eql(1)
37
+ header.sent_date.should eql(Date.civil(2008,5,19))
38
+
39
+ header.default_language_of_text.should eql("aaa")
40
+ header.default_price_type_code.should eql(1)
41
+ header.default_currency_code.should eql("ccc")
42
+ header.default_linear_unit.should eql("dd")
43
+ header.default_weight_unit.should eql("ee")
44
+ header.default_class_of_trade.should eql("f")
45
+ end
46
+
47
+ specify "should provide write access to first level attibutes" do
48
+ header = ONIX::Header.new
49
+
50
+ header.from_ean_number = "1111111111111"
51
+ header.from_ean_number.should eql("1111111111111")
52
+
53
+ header.from_san = "1111111"
54
+ header.from_san.should eql("1111111")
55
+
56
+ header.from_company = "Text Company"
57
+ header.from_company.should eql("Text Company")
58
+
59
+ header.from_email = "james@rainbowbooks.com.au"
60
+ header.from_email.should eql("james@rainbowbooks.com.au")
61
+
62
+ header.from_person = "James"
63
+ header.from_person.should eql("James")
64
+
65
+ header.to_ean_number = "2222222222222"
66
+ header.to_ean_number.should eql("2222222222222")
67
+
68
+ header.to_san = "2222222"
69
+ header.to_san.should eql("2222222")
70
+
71
+ header.to_company = "Company 2"
72
+ header.to_company.should eql("Company 2")
73
+
74
+ header.to_person = "Chris"
75
+ header.to_person.should eql("Chris")
76
+
77
+ header.message_note = "A Message"
78
+ header.message_note.should eql("A Message")
79
+
80
+ header.message_repeat = 1
81
+ header.message_repeat.should eql(1)
82
+
83
+ header.sent_date = Date.civil(2008,5,19)
84
+ header.sent_date.should eql(Date.civil(2008,5,19))
85
+
86
+ header.default_language_of_text = "aaa"
87
+ header.default_language_of_text.should eql("aaa")
88
+
89
+ header.default_price_type_code = 1
90
+ header.default_price_type_code.should eql(1)
91
+
92
+ header.default_currency_code = "ccc"
93
+ header.default_currency_code.should eql("ccc")
94
+
95
+ header.default_class_of_trade = "f"
96
+ header.default_class_of_trade.should eql("f")
97
+ end
98
+
99
+ specify "should correctly handle text with & < and >" do
100
+ header = ONIX::Header.new
101
+
102
+ header.from_company = "James & Healy"
103
+ header.to_xml.to_s.include?("James &amp; Healy").should be_true
104
+
105
+ header.from_company = "James < Healy"
106
+ header.to_xml.to_s.include?("James &lt; Healy").should be_true
107
+
108
+ header.from_company = "James > Healy"
109
+ header.to_xml.to_s.include?("James &gt; Healy").should be_true
110
+ end
111
+ end
@@ -0,0 +1,75 @@
1
+ # coding: utf-8
2
+
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
4
+
5
+ require 'onix'
6
+ require 'date'
7
+
8
+ context "ONIX::Product" do
9
+
10
+ before(:each) do
11
+ data_path = File.join(File.dirname(__FILE__),"..","data")
12
+ file1 = File.join(data_path, "product.xml")
13
+ @doc = LibXML::XML::Document.file(file1)
14
+ @product_node = @doc.root
15
+ end
16
+
17
+ specify "should provide read access to first level attibutes" do
18
+ product = ONIX::Product.parse(@product_node.to_s)
19
+
20
+ product.record_reference.should eql("365-9780194351898")
21
+ product.notification_type.should eql(3)
22
+ product.product_form.should eql("BC")
23
+ product.edition_number.should eql(1)
24
+ product.number_of_pages.should eql(100)
25
+ product.bic_main_subject.should eql("EB")
26
+ product.publishing_status.should eql(4)
27
+ product.publication_date.should eql(Date.civil(1998,9,1))
28
+ product.year_first_published.should eql(1998)
29
+ end
30
+
31
+ specify "should provide read access to product IDs" do
32
+ product = ONIX::Product.parse(@product_node.to_s)
33
+ product.product_identifiers.size.should eql(3)
34
+ end
35
+
36
+ specify "should provide read access to titles" do
37
+ product = ONIX::Product.parse(@product_node.to_s)
38
+ product.titles.size.should eql(1)
39
+ end
40
+
41
+ specify "should provide read access to subjects" do
42
+ product = ONIX::Product.parse(@product_node.to_s)
43
+ product.subjects.size.should eql(1)
44
+ end
45
+
46
+ specify "should provide write access to first level attibutes" do
47
+ product = ONIX::Product.new
48
+
49
+ product.notification_type = 3
50
+ product.notification_type.should eql(3)
51
+ product.record_reference = "365-9780194351898"
52
+ product.record_reference.should eql("365-9780194351898")
53
+
54
+ product.product_form = "BC"
55
+ product.product_form.should eql("BC")
56
+
57
+ product.edition_number = 1
58
+ product.edition_number.should eql(1)
59
+
60
+ product.number_of_pages = 100
61
+ product.number_of_pages.should eql(100)
62
+
63
+ product.bic_main_subject = "EB"
64
+ product.bic_main_subject.should eql("EB")
65
+
66
+ product.publishing_status = 4
67
+ product.publishing_status.should eql(4)
68
+
69
+ product.publication_date = Date.civil(1998,9,1)
70
+ product.publication_date.should eql(Date.civil(1998,9,1))
71
+
72
+ product.year_first_published = 1998
73
+ product.year_first_published.should eql(1998)
74
+ end
75
+ end