rbook-onix 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,80 @@
1
+ <?xml version='1.0'?>
2
+ <!DOCTYPE ONIXMessage SYSTEM "http://www.editeur.org/onix/2.1/reference/onix-international.dtd">
3
+ <ONIXMessage>
4
+ <Header>
5
+ <FromCompany>Chalice</FromCompany>
6
+ <FromPerson>James Healy</FromPerson>
7
+ <SentDate>20060521</SentDate>
8
+ </Header>
9
+ <Product>
10
+ <RecordReference>0827200528</RecordReference>
11
+ <NotificationType>03</NotificationType>
12
+ <ProductIdentifier>
13
+ <ProductIDType>02</ProductIDType>
14
+ <IDValue>0827200528</IDValue>
15
+ </ProductIdentifier>
16
+ <ProductForm>BA</ProductForm>
17
+ <NoSeries/>
18
+ <Title>
19
+ <TitleType>01</TitleType>
20
+ <TitleText>And Their Eyes Are Opened</TitleText>
21
+ <Subtitle>Story Sermons Embracing the World</Subtitle>
22
+ </Title>
23
+ <Contributor>
24
+ <SequenceNumber>0</SequenceNumber>
25
+ <ContributorRole>A01</ContributorRole>
26
+ <PersonNameInverted>Healy, James</PersonNameInverted>
27
+ </Contributor>
28
+ <NoEdition/>
29
+ <BICMainSubject>YFH</BICMainSubject>
30
+ <MediaFile>
31
+ <MediaFileTypeCode>04</MediaFileTypeCode>
32
+ <MediaFileLinkTypeCode>01</MediaFileLinkTypeCode>
33
+ <MediaFileLink>http://www.example.com/0827200528.jpg</MediaFileLink>
34
+ </MediaFile>
35
+ <NumberOfPages>0</NumberOfPages>
36
+ <Publisher>
37
+ <PublishingRole>01</PublishingRole>
38
+ <PublisherName>Chalice</PublisherName>
39
+ </Publisher>
40
+ <PublicationDate>20050303</PublicationDate>
41
+ <SalesRestriction>
42
+ <SalesRestrictionType>00</SalesRestrictionType>
43
+ <SalesRestrictionDetail>Unknown</SalesRestrictionDetail>
44
+ </SalesRestriction>
45
+ <SupplyDetail>
46
+ <SupplierName>Chalice</SupplierName>
47
+ <AvailabilityCode>CS</AvailabilityCode>
48
+ <IntermediaryAvailabilityCode>99</IntermediaryAvailabilityCode>
49
+ <Price>
50
+ <PriceTypeCode>02</PriceTypeCode>
51
+ <PriceAmount>29.95</PriceAmount>
52
+ </Price>
53
+ </SupplyDetail>
54
+ </Product>
55
+ <Product>
56
+ <RecordReference>0827200528</RecordReference>
57
+ <NotificationType>03</NotificationType>
58
+ <ProductIdentifier>
59
+ <ProductIDType>02</ProductIDType>
60
+ <IDValue>0827200528</IDValue>
61
+ </ProductIdentifier>
62
+ <ProductForm>BA</ProductForm>
63
+ <NoSeries/>
64
+ <Title>
65
+ <TitleType>01</TitleType>
66
+ <TitleText>And Their Eyes Are Opened</TitleText>
67
+ <Subtitle>Story Sermons Embracing the World</Subtitle>
68
+ </Title>
69
+ <Contributor>
70
+ <SequenceNumber>0</SequenceNumber>
71
+ <ContributorRole>A01</ContributorRole>
72
+ <PersonNameInverted>Healy, James</PersonNameInverted>
73
+ </Contributor>
74
+ <NoEdition/>
75
+ <BICMainSubject>YFH</BICMainSubject>
76
+ <MediaFile>
77
+ <MediaFileTypeCode>04</MediaFileTypeCode>
78
+ <MediaFileLinkTypeCode>01</MediaFileLinkTypeCode>
79
+ <MediaFileLink>http://www.example.com/0827200528.jpg</MediaFileLink>
80
+ </MediaFile>
@@ -0,0 +1,111 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE ONIXMessage SYSTEM "http://www.editeur.org/onix/2.1/01/reference/onix-international.dtd">
3
+ <ONIXMessage>
4
+ <Header>
5
+ <FromCompany>Allen &amp;amp; Unwin</FromCompany>
6
+ <FromPerson>Allen &amp;amp; Unwin</FromPerson>
7
+ <SentDate>20071015</SentDate>
8
+ </Header>
9
+ <Product>
10
+ <RecordReference>1741753856</RecordReference>
11
+ <NotificationType>01</NotificationType>
12
+ <ProductIdentifier>
13
+ <ProductIDType>02</ProductIDType>
14
+ <IDValue>1741753856</IDValue>
15
+ </ProductIdentifier>
16
+ <ProductIdentifier>
17
+ <ProductIDType>03</ProductIDType>
18
+ <IDValue>9781741753851</IDValue>
19
+ </ProductIdentifier>
20
+ <ProductIdentifier>
21
+ <ProductIDType>15</ProductIDType>
22
+ <IDValue>9781741753851</IDValue>
23
+ </ProductIdentifier>
24
+ <ProductForm>BC</ProductForm>
25
+ <ProductFormDetail>B105</ProductFormDetail>
26
+ <Title>
27
+ <TitleType>00</TitleType>
28
+ <TitleText>Mr Wong Goes West</TitleText>
29
+ <Subtitle>A Feng Shui Detective Novel</Subtitle>
30
+ </Title>
31
+ <Contributor>
32
+ <ContributorRole>A01</ContributorRole>
33
+ <PersonNameInverted>Vittachi, Nury</PersonNameInverted>
34
+ </Contributor>
35
+ <EditionNumber>1</EditionNumber>
36
+ <NumberOfPages>264</NumberOfPages>
37
+ <BICMainSubject>FF</BICMainSubject>
38
+ <OtherText>
39
+ <TextTypeCode>02</TextTypeCode>
40
+ <Text>Get ready to laugh - the Feng Shui Detective is back in an all new adventure. Feng Shui master CF Wong's skills and charms are again in desperate need, this time in London. But is the West ready for our Feng Shui crime-fighting hero?</Text>
41
+ </OtherText>
42
+ <OtherText>
43
+ <TextTypeCode>03</TextTypeCode>
44
+ <Text>The world's biggest and most expensive aircraft - Skyparc's 'office in the sky' which apparently runs on 'green' fuel - flies into Hong Kong. The Europeans want to sell the plane to the Chinese and Mr Wong is hired to make sure there is nothing on the plane that might upset visiting Chinese aviation officials. But things go wrong. An oil company executive is murdered and a young greenie, who happens to be a friend of Mr Wong's assistant, Joyce McQuinnie, is arrested.Mr Wong is delighted. The fact that a murder has taken place means that his job is now far more important and he can charge a much higher price. But as he flies to London to confer with officials, Skyparc's wheel assemblages are blown off and it's revealed there is a bomb on board. Wong must not only solve the mystery, but (almost) land the plane himself.Can Wong save the day? And will he make it to London where an anxious royal client awaits him, convinced that some terrible form of bad luck is responsible for years of Windsor family woe? In this third instalment of the eccentric and wildly entertaining Feng Shui Detectiveseries, the stakes for Mr Wong are higher than they've ever been.</Text>
45
+ </OtherText>
46
+ <MediaFile>
47
+ <MediaFileTypeCode>04</MediaFileTypeCode>
48
+ <MediaFileLinkTypeCode>01</MediaFileLinkTypeCode>
49
+ <MediaFileLink>http://www.allenandunwin.com/BookCovers/resized_9781741753851_224_297_FitSquare.jpg</MediaFileLink>
50
+ </MediaFile>
51
+ <Imprint>
52
+ <ImprintName>Allen &amp; Unwin</ImprintName>
53
+ </Imprint>
54
+ <Publisher>
55
+ <PublishingRole>01</PublishingRole>
56
+ <PublisherName>Allen &amp; Unwin</PublisherName>
57
+ </Publisher>
58
+ <PublishingStatus>02</PublishingStatus>
59
+ <PublicationDate>20080201</PublicationDate>
60
+ <YearFirstPublished>2008</YearFirstPublished>
61
+ <Measure>
62
+ <MeasureTypeCode>01</MeasureTypeCode>
63
+ <Measurement>195</Measurement>
64
+ <MeasureUnitCode>mm</MeasureUnitCode>
65
+ </Measure>
66
+ <Measure>
67
+ <MeasureTypeCode>02</MeasureTypeCode>
68
+ <Measurement>130</Measurement>
69
+ <MeasureUnitCode>mm</MeasureUnitCode>
70
+ </Measure>
71
+ <Measure>
72
+ <MeasureTypeCode>08</MeasureTypeCode>
73
+ <Measurement>300</Measurement>
74
+ <MeasureUnitCode>gr</MeasureUnitCode>
75
+ </Measure>
76
+ <SupplyDetail>
77
+ <SupplierName>Alliance Distribution Services</SupplierName>
78
+ <ProductAvailability>10</ProductAvailability>
79
+ <ExpectedShipDate>20080201</ExpectedShipDate>
80
+ <Stock>
81
+ <OnHand>NYP</OnHand>
82
+ <OnOrder>No</OnOrder>
83
+ </Stock>
84
+ <Price>
85
+ <PriceTypeCode>02</PriceTypeCode>
86
+ <PriceAmount>22.95</PriceAmount>
87
+ <CurrencyCode>AUD</CurrencyCode>
88
+ </Price>
89
+ <Price>
90
+ <PriceTypeCode>01</PriceTypeCode>
91
+ <PriceAmount>20.86</PriceAmount>
92
+ <CurrencyCode>AUD</CurrencyCode>
93
+ </Price>
94
+ <Price>
95
+ <PriceTypeCode>02</PriceTypeCode>
96
+ <PriceAmount>27.99</PriceAmount>
97
+ <CurrencyCode>NZD</CurrencyCode>
98
+ </Price>
99
+ </SupplyDetail>
100
+ <MarketRepresentation>
101
+ <AgentName>Allen &amp; Unwin</AgentName>
102
+ <AgentRole>07</AgentRole>
103
+ <MarketCountry>AU</MarketCountry>
104
+ <MarketPublishingStatus>02</MarketPublishingStatus>
105
+ <MarketDate>
106
+ <MarketDateRole>01</MarketDateRole>
107
+ <Date>20080201</Date>
108
+ </MarketDate>
109
+ </MarketRepresentation>
110
+ </Product>
111
+ </ONIXMessage>
@@ -91,10 +91,17 @@ context "The message class" do
91
91
  end
92
92
 
93
93
  # test loading an xml file that's is invalid (an open tag)
94
- specify "should raise an exception if attempting to load an XML file with an open tag" do
95
- doc = File.read(File.dirname(__FILE__)+"/data/invalid_xml.xml")
94
+ specify "should parse as much data as possible when a tag has been left open" do
95
+ str = File.read(File.dirname(__FILE__)+"/data/invalid_xml.xml")
96
+ msg = RBook::Onix::Message.load_from_string(str)
97
+
98
+ #check header elements
99
+ msg.from_company.should eql("Chalice")
100
+ msg.from_person.should eql("James Healy")
101
+ msg.sent_date.should eql(Date.civil(2006, 5, 21))
96
102
 
97
- lambda { msg = RBook::Onix::Message.load_from_string(doc) }.should raise_error(LoadError)
103
+ #check product count
104
+ msg.products.size.should eql(1)
98
105
  end
99
106
 
100
107
  # test loading a non XML file
@@ -20,7 +20,7 @@ context "A message object with valid data" do
20
20
  product.product_identifier = '0977616606'
21
21
  msg.add_product(product)
22
22
 
23
- doc = msg.to_xml
23
+ doc = REXML::Document.new(msg.to_s)
24
24
 
25
25
  REXML::XPath.first(doc, '/ONIXMessage/Header/FromPerson').should_not be_nil
26
26
  REXML::XPath.first(doc, '/ONIXMessage/Header/FromPerson').text.should eql("James Healy")
@@ -39,10 +39,10 @@ context "A message object with valid data" do
39
39
  msg.to_person = "RSpec"
40
40
 
41
41
  # TODO: fix this to use a RBook custom error
42
- lambda { msg.to_xml }.should raise_error(RuntimeError)
42
+ lambda { msg.to_s }.should raise_error(RuntimeError)
43
43
  end
44
44
 
45
- specify "should output a valid string" do
45
+ specify "should output a valid string with the correct indentation" do
46
46
  msg = RBook::Onix::Message.new
47
47
  msg.from_person = "James Healy"
48
48
  msg.from_company = "Healy Inc."
@@ -52,7 +52,28 @@ context "A message object with valid data" do
52
52
  product.product_identifier = '0977616606'
53
53
  msg.add_product(product)
54
54
 
55
+ # check string generation
55
56
  msg.to_s.should be_a_kind_of(String)
57
+
58
+ # check indenting
59
+ lines = msg.to_s.split("\n")
60
+ (lines.size > 3).should eql(true)
61
+ lines[0][0,5].should eql("<?xml")
62
+ lines[1][0,9].should eql("<!DOCTYPE")
63
+ lines[2][0,13].should eql("<ONIXMessage>")
64
+ end
65
+
66
+ specify "should output a valid REXML::Document object" do
67
+ msg = RBook::Onix::Message.new
68
+ msg.from_person = "James Healy"
69
+ msg.from_company = "Healy Inc."
70
+ msg.to_person = "RSpec"
71
+
72
+ product = RBook::Onix::Product.new
73
+ product.product_identifier = '0977616606'
74
+ msg.add_product(product)
75
+
76
+ msg.to_xml.should be_a_kind_of(REXML::Document)
56
77
  end
57
78
 
58
79
  specify "should output a valid string with no line breaks between tags and content" do
@@ -102,6 +123,6 @@ context "A message object with valid data" do
102
123
  product.product_identifier = '0977616606'
103
124
  msg.add_product(product)
104
125
 
105
- msg.to_s[0,128].include?("encoding='UTF-8'").should be_true
126
+ msg.to_s[0,128].include?("encoding=\"UTF-8\"").should be_true
106
127
  end
107
128
  end
@@ -31,6 +31,16 @@ context "The product class" do
31
31
  product.supply_details.size.should eql(1)
32
32
  end
33
33
 
34
+ specify "should return the correct ID when there are multiple IDs specified" do
35
+ product = nil
36
+ File.open(File.dirname(__FILE__)+"/data/2_ids.xml", "r") do |f|
37
+ doc = REXML::Document.new(f)
38
+ product = RBook::Onix::Product.load_from_element(REXML::XPath.first(doc, '/ONIXMessage/Product'))
39
+ end
40
+
41
+ product.product_identifier.should eql("9789900036708")
42
+ end
43
+
34
44
  specify "should raise an exception when atytempting to load from a non Product XML fragment" do
35
45
  element = REXML::Element.new('NonProduct')
36
46
  element.add_element('NonContributor').text = 'blah'
@@ -28,16 +28,37 @@ context "A product object with valid data" do
28
28
  supply_detail.price = 29.95
29
29
  product.add_supply_detail(supply_detail)
30
30
 
31
- doc = product.to_element
31
+ doc = REXML::Document.new(product.to_s)
32
32
 
33
- REXML::XPath.first(doc, '/ProductIdentifier/IDValue').should_not be_nil
34
- REXML::XPath.first(doc, '/ProductIdentifier/IDValue').text.should eql("0977616606")
35
- REXML::XPath.first(doc, '/Title/TitleText').should_not be_nil
36
- REXML::XPath.first(doc, '/Title/TitleText').text.should eql("This is a title")
37
- REXML::XPath.first(doc, '/Contributor').should_not be_nil
38
- REXML::XPath.first(doc, '/Publisher/PublisherName').should_not be_nil
39
- REXML::XPath.first(doc, '/Publisher/PublisherName').text.should eql("Chalice")
40
- REXML::XPath.first(doc, '/SupplyDetail').should_not be_nil
33
+ REXML::XPath.first(doc, '//ProductIdentifier/IDValue').should_not be_nil
34
+ REXML::XPath.first(doc, '//ProductIdentifier/IDValue').text.should eql("0977616606")
35
+ REXML::XPath.first(doc, '//Title/TitleText').should_not be_nil
36
+ REXML::XPath.first(doc, '//Title/TitleText').text.should eql("This is a title")
37
+ REXML::XPath.first(doc, '//Contributor').should_not be_nil
38
+ REXML::XPath.first(doc, '//Publisher/PublisherName').should_not be_nil
39
+ REXML::XPath.first(doc, '//Publisher/PublisherName').text.should eql("Chalice")
40
+ REXML::XPath.first(doc, '//SupplyDetail').should_not be_nil
41
+ end
42
+
43
+ specify "should output to a valid REXML::Element object" do
44
+ product = RBook::Onix::Product.new
45
+ product.product_identifier = '0977616606'
46
+ product.title = 'This is a title'
47
+ product.publisher = 'Chalice'
48
+
49
+ contributor = RBook::Onix::Contributor.new
50
+ contributor.sequence_number = '0'
51
+ contributor.name_inverted = 'Healy, James'
52
+ contributor.role = 'A01'
53
+ product.add_contributor(contributor)
54
+
55
+ supply_detail = RBook::Onix::SupplyDetail.new
56
+ supply_detail.supplier_name = 'Walker'
57
+ supply_detail.availability_code = 'CS'
58
+ supply_detail.price = 29.95
59
+ product.add_supply_detail(supply_detail)
60
+
61
+ product.to_element.should be_a_kind_of(REXML::Element)
41
62
  end
42
63
 
43
64
  # ensure all output is cleansed UTF-8
@@ -12,12 +12,12 @@ context "A sales restriction object with valid data" do
12
12
  restriction.type = '00'
13
13
  restriction.detail = 'Unknown'
14
14
 
15
- doc = restriction.to_element
15
+ doc = REXML::Document.new(restriction.to_s)
16
16
 
17
- REXML::XPath.first(doc, '/SalesRestrictionType').should_not be_nil
18
- REXML::XPath.first(doc, '/SalesRestrictionType').text.should eql("00")
19
- REXML::XPath.first(doc, '/SalesRestrictionDetail').should_not be_nil
20
- REXML::XPath.first(doc, '/SalesRestrictionDetail').text.should eql("Unknown")
17
+ REXML::XPath.first(doc, '//SalesRestrictionType').should_not be_nil
18
+ REXML::XPath.first(doc, '//SalesRestrictionType').text.should eql("00")
19
+ REXML::XPath.first(doc, '//SalesRestrictionDetail').should_not be_nil
20
+ REXML::XPath.first(doc, '//SalesRestrictionDetail').text.should eql("Unknown")
21
21
  end
22
22
 
23
23
  specify "should output a valid string" do
@@ -26,6 +26,13 @@ context "A sales restriction object with valid data" do
26
26
  restriction.detail = 'Unknown'
27
27
 
28
28
  restriction.to_s.should be_a_kind_of(String)
29
+ end
29
30
 
31
+ specify "should output a valid REXML::Element object" do
32
+ restriction = RBook::Onix::SalesRestriction.new
33
+ restriction.type = '00'
34
+ restriction.detail = 'Unknown'
35
+
36
+ restriction.to_element.should be_a_kind_of(REXML::Element)
30
37
  end
31
38
  end
@@ -28,4 +28,61 @@ context "The stream reader class" do
28
28
 
29
29
  counter.should eql(10)
30
30
  end
31
+
32
+ specify "should read in all the objects from an ONIX file with ampersands in the data" do
33
+ counter = 0
34
+
35
+ reader = RBook::Onix::StreamReader.new(File.dirname(__FILE__)+"/data/with_ampersands.xml")
36
+ reader.each do |product|
37
+ product.should be_a_kind_of(RBook::Onix::Product)
38
+ counter += 1
39
+ end
40
+
41
+ counter.should eql(1)
42
+ end
43
+
44
+ specify "should handle non-XML files gracefully" do
45
+ counter = 0
46
+
47
+ reader = RBook::Onix::StreamReader.new(File.dirname(__FILE__)+"/data/not_xml.csv")
48
+ reader.each do |product|
49
+ counter += 1
50
+ end
51
+
52
+ counter.should eql(0)
53
+ end
54
+
55
+ specify "should handle XML files that aren't ONIX gracefully" do
56
+ counter = 0
57
+
58
+ reader = RBook::Onix::StreamReader.new(File.dirname(__FILE__)+"/data/xml_not_onix.xml")
59
+ reader.each do |product|
60
+ counter += 1
61
+ end
62
+
63
+ counter.should eql(0)
64
+ end
65
+
66
+ specify "should read in as many products as possible if a file has been truncated" do
67
+ counter = 0
68
+
69
+ reader = RBook::Onix::StreamReader.new(File.dirname(__FILE__)+"/data/truncated.xml")
70
+ reader.each do |product|
71
+ product.should be_a_kind_of(RBook::Onix::Product)
72
+ counter += 1
73
+ end
74
+
75
+ counter.should eql(1)
76
+ end
77
+
78
+ specify "should fail gracefully if an xml declaration is found in the middle of the file" do
79
+ counter = 0
80
+
81
+ reader = RBook::Onix::StreamReader.new(File.dirname(__FILE__)+"/data/leading_garbage.xml")
82
+ reader.each do |product|
83
+ counter += 1
84
+ end
85
+
86
+ counter.should eql(0)
87
+ end
31
88
  end
@@ -17,16 +17,16 @@ context "A product object with valid data" do
17
17
  supply_detail.availability_code = 'CS'
18
18
  supply_detail.price = 38.05
19
19
 
20
- doc = supply_detail.to_element
20
+ doc = REXML::Document.new(supply_detail.to_s)
21
21
 
22
- REXML::XPath.first(doc, '/SupplierName').should_not be_nil
23
- REXML::XPath.first(doc, '/SupplierName').text.should eql("Walker")
24
- REXML::XPath.first(doc, '/AvailabilityCode').should_not be_nil
25
- REXML::XPath.first(doc, '/AvailabilityCode').text.should eql("CS")
26
- REXML::XPath.first(doc, '/Price/PriceAmount').should_not be_nil
27
- REXML::XPath.first(doc, '/Price/PriceAmount').text.should eql("38.05")
28
- REXML::XPath.first(doc, '/Price/PriceTypeCode').should_not be_nil
29
- REXML::XPath.first(doc, '/Price/PriceTypeCode').text.should eql("02")
22
+ REXML::XPath.first(doc, '//SupplierName').should_not be_nil
23
+ REXML::XPath.first(doc, '//SupplierName').text.should eql("Walker")
24
+ REXML::XPath.first(doc, '//AvailabilityCode').should_not be_nil
25
+ REXML::XPath.first(doc, '//AvailabilityCode').text.should eql("CS")
26
+ REXML::XPath.first(doc, '//Price/PriceAmount').should_not be_nil
27
+ REXML::XPath.first(doc, '//Price/PriceAmount').text.should eql("38.05")
28
+ REXML::XPath.first(doc, '//Price/PriceTypeCode').should_not be_nil
29
+ REXML::XPath.first(doc, '//Price/PriceTypeCode').text.should eql("02")
30
30
 
31
31
  end
32
32
 
@@ -37,6 +37,15 @@ context "A product object with valid data" do
37
37
  supply_detail.price = 38.05
38
38
 
39
39
  supply_detail.to_s.should be_a_kind_of(String)
40
+ end
40
41
 
42
+ specify "should output a valid REXML::Element object" do
43
+ supply_detail = RBook::Onix::SupplyDetail.new
44
+ supply_detail.supplier_name = 'Walker'
45
+ supply_detail.availability_code = 'CS'
46
+ supply_detail.price = 38.05
47
+
48
+ supply_detail.to_element.should be_a_kind_of(REXML::Element)
41
49
  end
50
+
42
51
  end