onix 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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