sax-machine 0.0.16 → 0.0.20

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/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gem 'nokogiri', '>= 1.4.4'
4
- gem 'rspec', '>= 2.4.0'
4
+ gem 'rspec', '>= 2.6.0'
@@ -23,6 +23,7 @@ class AtomEntry
23
23
  element :summary
24
24
  element :content
25
25
  element :published
26
+ parent :parent
26
27
  end
27
28
 
28
29
  # Class for parsing Atom feeds
@@ -43,10 +44,11 @@ feed = Atom.parse(xml_text)
43
44
  feed.title # => whatever the title of the blog is
44
45
  feed.url # => the main url of the blog
45
46
  feed.feed_url # => goes to the feedburner feed
46
-
47
+
47
48
  feed.entries.first.title # => title of the first entry
48
49
  feed.entries.first.author # => the author of the first entry
49
50
  feed.entries.first.url # => the permalink on the blog for this entry
51
+ feed.entries.first.parent # => the Atom parent
50
52
  # etc ...
51
53
 
52
54
  # you can also use the elements method without specifying a class like so
@@ -62,11 +64,11 @@ response.messages.last # => "world"
62
64
  h2. LICENSE
63
65
 
64
66
  (The MIT License)
65
-
66
- Copyright (c) 2009:
67
-
67
+
68
+ Copyright (c) 2009 - 2011:
69
+
68
70
  "Paul Dix":http://pauldix.net
69
-
71
+
70
72
  Permission is hereby granted, free of charge, to any person obtaining
71
73
  a copy of this software and associated documentation files (the
72
74
  'Software'), to deal in the Software without restriction, including
@@ -74,10 +76,10 @@ without limitation the rights to use, copy, modify, merge, publish,
74
76
  distribute, sublicense, and/or sell copies of the Software, and to
75
77
  permit persons to whom the Software is furnished to do so, subject to
76
78
  the following conditions:
77
-
79
+
78
80
  The above copyright notice and this permission notice shall be
79
81
  included in all copies or substantial portions of the Software.
80
-
82
+
81
83
  THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
82
84
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
83
85
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
data/Rakefile CHANGED
@@ -1,5 +1,7 @@
1
1
  require "rspec/core/rake_task"
2
- require 'lib/sax-machine.rb'
2
+
3
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
4
+ require 'sax-machine'
3
5
 
4
6
  desc "Run all specs"
5
7
  RSpec::Core::RakeTask.new do |t|
@@ -0,0 +1,40 @@
1
+ module SAXMachine
2
+ class SAXConfig
3
+
4
+ class AttributeConfig
5
+ attr_reader :name, :setter
6
+
7
+ def initialize(name, options)
8
+ @name = name.to_s
9
+ @as = options[:as]
10
+ @setter = "#{@as}="
11
+ @required = options[:required]
12
+ end
13
+
14
+ def column
15
+ @as || @name.to_sym
16
+ end
17
+
18
+ def required?
19
+ @required
20
+ end
21
+
22
+ def value_from_attrs(attrs)
23
+ attrs.index(@name) ? attrs[attrs.index(@name) + 1] : nil
24
+ end
25
+
26
+ def attrs_match?(attrs)
27
+ attrs.index(@name) ? true : false
28
+ end
29
+
30
+ def has_value_and_attrs_match?(attrs)
31
+ attrs_match?(attrs)
32
+ end
33
+
34
+ def collection?
35
+ false
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -1,47 +1,74 @@
1
+ require "sax-machine/sax_attribute_config"
2
+ require "sax-machine/sax_element_value_config"
1
3
  require "sax-machine/sax_element_config"
2
4
  require "sax-machine/sax_collection_config"
5
+ require "sax-machine/sax_parent_config"
3
6
 
4
7
  module SAXMachine
5
8
  class SAXConfig
6
- attr_accessor :top_level_elements, :collection_elements
7
-
9
+
10
+ attr_accessor :top_level_elements, :top_level_attributes, :top_level_element_value, :collection_elements, :parents
11
+
8
12
  def initialize
9
- @top_level_elements = {}
10
- @collection_elements = {}
13
+ # Default value is an empty array
14
+ @top_level_elements = Hash.new { |hash, key| hash[key] = [] }
15
+ @top_level_attributes = []
16
+ @top_level_element_value = []
17
+ @collection_elements = Hash.new { |hash, key| hash[key] = [] }
18
+ @parents = []
11
19
  end
12
-
20
+
13
21
  def columns
14
22
  @top_level_elements.map {|name, ecs| ecs }.flatten
15
23
  end
16
-
24
+
17
25
  def initialize_copy(sax_config)
26
+ super
18
27
  @top_level_elements = sax_config.top_level_elements.clone
28
+ @top_level_attributes = sax_config.top_level_attributes.clone
29
+ @top_level_element_value = sax_config.top_level_element_value.clone
19
30
  @collection_elements = sax_config.collection_elements.clone
31
+ @parents = sax_config.parents.clone
20
32
  end
21
33
 
22
34
  def add_top_level_element(name, options)
23
- @top_level_elements[name.to_s] = [] unless @top_level_elements[name.to_s]
24
35
  @top_level_elements[name.to_s] << ElementConfig.new(name, options)
25
36
  end
26
37
 
38
+ def add_top_level_attribute(name, options)
39
+ @top_level_attributes << AttributeConfig.new(options.delete(:name), options)
40
+ end
41
+
42
+ def add_top_level_element_value(name, options)
43
+ @top_level_element_value << ElementValueConfig.new(options.delete(:name), options)
44
+ end
45
+
27
46
  def add_collection_element(name, options)
28
- @collection_elements[name.to_s] = [] unless @collection_elements[name.to_s]
29
47
  @collection_elements[name.to_s] << CollectionConfig.new(name, options)
30
48
  end
31
49
 
50
+ def add_parent(name, options)
51
+ @parents << ParentConfig.new(name, options)
52
+ end
53
+
32
54
  def collection_config(name, attrs)
33
- ces = @collection_elements[name.to_s]
34
- ces && ces.detect { |cc| cc.attrs_match?(attrs) }
55
+ @collection_elements[name.to_s].detect { |cc| cc.attrs_match?(attrs) }
56
+ end
57
+
58
+ def attribute_configs_for_element(attrs)
59
+ @top_level_attributes.select { |aa| aa.attrs_match?(attrs) }
60
+ end
61
+
62
+ def element_values_for_element
63
+ @top_level_element_value
35
64
  end
36
65
 
37
66
  def element_configs_for_attribute(name, attrs)
38
- tes = @top_level_elements[name.to_s]
39
- tes && tes.select { |ec| ec.has_value_and_attrs_match?(attrs) } || []
67
+ @top_level_elements[name.to_s].select { |ec| ec.has_value_and_attrs_match?(attrs) }
40
68
  end
41
69
 
42
70
  def element_config_for_tag(name, attrs)
43
- tes = @top_level_elements[name.to_s]
44
- tes && tes.detect { |ec| ec.attrs_match?(attrs) }
71
+ @top_level_elements[name.to_s].detect { |ec| ec.attrs_match?(attrs) }
45
72
  end
46
73
  end
47
74
  end
@@ -1,33 +1,50 @@
1
1
  require "nokogiri"
2
2
 
3
3
  module SAXMachine
4
-
4
+
5
5
  def self.included(base)
6
6
  base.extend ClassMethods
7
7
  end
8
-
9
- def parse(xml_text)
10
- sax_handler = SAXHandler.new(self)
8
+
9
+ def parse(xml_text, on_error = nil, on_warning = nil)
10
+ sax_handler = SAXHandler.new(self, on_error, on_warning)
11
11
  parser = Nokogiri::XML::SAX::Parser.new(sax_handler)
12
12
  parser.parse(xml_text)
13
13
  self
14
14
  end
15
-
15
+
16
16
  module ClassMethods
17
17
 
18
- def parse(xml_text)
19
- new.parse(xml_text)
18
+ def inherited(subclass)
19
+ subclass.sax_config.send(:initialize_copy, self.sax_config)
20
20
  end
21
-
21
+
22
+ def parse(xml_text, on_error = nil, on_warning = nil)
23
+ new.parse(xml_text, on_error, on_warning)
24
+ end
25
+
22
26
  def element(name, options = {})
23
- options[:as] ||= name
27
+ real_name = (options[:as] ||= name).to_s
24
28
  sax_config.add_top_level_element(name, options)
25
-
26
- # we only want to insert the getter and setter if they haven't defined it from elsewhere.
27
- # this is how we allow custom parsing behavior. So you could define the setter
28
- # and have it parse the string into a date or whatever.
29
- attr_reader options[:as] unless instance_methods.include?(options[:as].to_s)
30
- attr_writer options[:as] unless instance_methods.include?("#{options[:as]}=")
29
+ create_attr real_name
30
+ end
31
+
32
+ def attribute(name, options = {})
33
+ real_name = (options[:as] ||= name).to_s
34
+ sax_config.add_top_level_attribute(self.class.to_s, options.merge(:name => name))
35
+ create_attr real_name
36
+ end
37
+
38
+ def value(name, options = {})
39
+ real_name = (options[:as] ||= name).to_s
40
+ sax_config.add_top_level_element_value(self.class.to_s, options.merge(:name => name))
41
+ create_attr real_name
42
+ end
43
+
44
+ def parent(name, options = {})
45
+ real_name = (options[:as] ||= name).to_s
46
+ sax_config.add_parent(name, options)
47
+ create_attr(real_name)
31
48
  end
32
49
 
33
50
  def columns
@@ -35,7 +52,7 @@ module SAXMachine
35
52
  end
36
53
 
37
54
  def column(sym)
38
- columns.select{|c| c.column == sym}[0]
55
+ columns.select { |c| c.column == sym }[0]
39
56
  end
40
57
 
41
58
  def data_class(sym)
@@ -47,9 +64,9 @@ module SAXMachine
47
64
  end
48
65
 
49
66
  def column_names
50
- columns.map{|e| e.column}
67
+ columns.map { |e| e.column }
51
68
  end
52
-
69
+
53
70
  def elements(name, options = {})
54
71
  options[:as] ||= name
55
72
  if options[:class]
@@ -62,21 +79,29 @@ module SAXMachine
62
79
  SRC
63
80
  sax_config.add_top_level_element(name, options.merge(:collection => true))
64
81
  end
65
-
66
- if !instance_methods.include?(options[:as].to_s)
67
- class_eval <<-SRC
82
+
83
+ if !method_defined?(options[:as].to_s)
84
+ class_eval <<-SRC
68
85
  def #{options[:as]}
69
86
  @#{options[:as]} ||= []
70
87
  end
71
88
  SRC
72
89
  end
73
-
74
- attr_writer options[:as] unless instance_methods.include?("#{options[:as]}=")
90
+
91
+ attr_writer options[:as] unless method_defined?("#{options[:as]}=")
75
92
  end
76
-
93
+
77
94
  def sax_config
78
95
  @sax_config ||= SAXConfig.new
79
96
  end
97
+
98
+ # we only want to insert the getter and setter if they haven't defined it from elsewhere.
99
+ # this is how we allow custom parsing behavior. So you could define the setter
100
+ # and have it parse the string into a date or whatever.
101
+ def create_attr real_name
102
+ attr_reader real_name unless method_defined?(real_name)
103
+ attr_writer real_name unless method_defined?("#{real_name}=")
104
+ end
80
105
  end
81
-
82
- end
106
+
107
+ end
@@ -31,6 +31,14 @@ module SAXMachine
31
31
  @data_class = options[:class]
32
32
  @required = options[:required]
33
33
  end
34
+
35
+ def value_configured?
36
+ !@value.nil?
37
+ end
38
+
39
+ def to_s
40
+ "name: #{@name} dataclass: #{@data_class} setter: #{@setter} required: #{@required} value: #{@value} as:#{@as} collection: #{@collection} with: #{@with}"
41
+ end
34
42
 
35
43
  def column
36
44
  @as || @name.to_sym
@@ -62,4 +70,4 @@ module SAXMachine
62
70
  end
63
71
 
64
72
  end
65
- end
73
+ end
@@ -0,0 +1,24 @@
1
+ module SAXMachine
2
+ class SAXConfig
3
+
4
+ class ElementValueConfig
5
+ attr_reader :name, :setter
6
+
7
+ def initialize(name, options)
8
+ @name = name.to_s
9
+ @as = options[:as]
10
+ @setter = "#{@as}="
11
+ @required = options[:required]
12
+ end
13
+
14
+ def column
15
+ @as || @name.to_sym
16
+ end
17
+
18
+ def required?
19
+ @required
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -4,9 +4,11 @@ module SAXMachine
4
4
  class SAXHandler < Nokogiri::XML::SAX::Document
5
5
  attr_reader :stack
6
6
 
7
- def initialize(object)
8
- @stack = [[object, nil, ""]]
7
+ def initialize(object, on_error = nil, on_warning = nil)
8
+ @stack = [[object, nil, String.new]]
9
9
  @parsed_configs = {}
10
+ @on_error = on_error
11
+ @on_warning = on_warning
10
12
  end
11
13
 
12
14
  def characters(string)
@@ -25,8 +27,12 @@ module SAXMachine
25
27
 
26
28
  if sax_config
27
29
  if collection_config = sax_config.collection_config(name, attrs)
28
- stack.push [object = collection_config.data_class.new, collection_config, ""]
30
+ stack.push [object = collection_config.data_class.new, collection_config, String.new]
29
31
  object, sax_config, is_collection = object, object.class.sax_config, true
32
+
33
+ if (attribute_config = object.class.respond_to?(:sax_config) && object.class.sax_config.attribute_configs_for_element(attrs))
34
+ attribute_config.each { |ac| object.send(ac.setter, ac.value_from_attrs(attrs)) }
35
+ end
30
36
  end
31
37
  sax_config.element_configs_for_attribute(name, attrs).each do |ec|
32
38
  unless parsed_config?(object, ec)
@@ -35,7 +41,12 @@ module SAXMachine
35
41
  end
36
42
  end
37
43
  if !collection_config && element_config = sax_config.element_config_for_tag(name, attrs)
38
- stack.push [element_config.data_class ? element_config.data_class.new : object, element_config, ""]
44
+ new_object = element_config.data_class ? element_config.data_class.new : object
45
+ stack.push [new_object, element_config, String.new]
46
+
47
+ if (attribute_config = new_object.class.respond_to?(:sax_config) && new_object.class.sax_config.attribute_configs_for_element(attrs))
48
+ attribute_config.each { |ac| new_object.send(ac.setter, ac.value_from_attrs(attrs)) }
49
+ end
39
50
  end
40
51
  end
41
52
  end
@@ -45,13 +56,29 @@ module SAXMachine
45
56
  return unless stack.size > 1 && config && config.name.to_s == name.to_s
46
57
 
47
58
  unless parsed_config?(object, config)
59
+ if (element_value_config = config.data_class.respond_to?(:sax_config) && config.data_class.sax_config.element_values_for_element)
60
+ element_value_config.each { |evc| element.send(evc.setter, value) }
61
+ end
62
+
48
63
  if config.respond_to?(:accessor)
64
+ subconfig = element.class.sax_config if element.class.respond_to?(:sax_config)
65
+ if econf = subconfig.element_config_for_tag(name, [])
66
+ element.send(econf.setter, value) unless econf.value_configured?
67
+ end
49
68
  object.send(config.accessor) << element
50
69
  else
51
70
  value = config.data_class ? element : value
52
71
  object.send(config.setter, value) unless value == ""
53
72
  mark_as_parsed(object, config)
54
73
  end
74
+
75
+ # try to set the parent
76
+ sax_config = element.class.respond_to?(:sax_config) ? element.class.sax_config : nil
77
+ if sax_config
78
+ sax_config.parents.each do |parent|
79
+ element.send(parent.setter, object)
80
+ end
81
+ end
55
82
  end
56
83
  stack.pop
57
84
  end
@@ -63,5 +90,18 @@ module SAXMachine
63
90
  def parsed_config?(object, element_config)
64
91
  @parsed_configs[[object.object_id, element_config.object_id]]
65
92
  end
93
+
94
+ def warning string
95
+ if @on_warning
96
+ @on_warning.call(string)
97
+ end
98
+ end
99
+
100
+ def error string
101
+ if @on_error
102
+ @on_error.call(string)
103
+ end
104
+ end
105
+
66
106
  end
67
- end
107
+ end
@@ -0,0 +1,21 @@
1
+ module SAXMachine
2
+ class SAXConfig
3
+
4
+ class ParentConfig
5
+ attr_reader :name, :setter
6
+
7
+ def initialize(name, options)
8
+ @name = name.to_s
9
+
10
+ @as = options[:as]
11
+ @setter = "#{@as}="
12
+ end
13
+
14
+ def column
15
+ @as || @name.to_sym
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
@@ -20,11 +20,26 @@ describe "SAXMachine" do
20
20
  @klass.column_names.should =~ [:title]
21
21
  end
22
22
 
23
+ it "should not overwrite the getter is there is already one present" do
24
+ @klass = Class.new do
25
+ def title
26
+ "#{@title} ***"
27
+ end
28
+
29
+ include SAXMachine
30
+ element :title
31
+ end
32
+ document = @klass.new
33
+ document.title = "Title"
34
+ document.title.should == "Title ***"
35
+ end
36
+
23
37
  it "should not overwrite the setter if there is already one present" do
24
38
  @klass = Class.new do
25
39
  def title=(val)
26
40
  @title = "#{val} **"
27
41
  end
42
+
28
43
  include SAXMachine
29
44
  element :title
30
45
  end
@@ -105,6 +120,36 @@ describe "SAXMachine" do
105
120
  document.name.should == "Paul"
106
121
  document.title.should == "My Title"
107
122
  end
123
+
124
+
125
+ it "should not overwrite the getter is there is already one present" do
126
+ @klass = Class.new do
127
+ def items
128
+ []
129
+ end
130
+
131
+ include SAXMachine
132
+ elements :items
133
+ end
134
+ document = @klass.new
135
+ document.items = [1, 2, 3, 4]
136
+ document.items.should == []
137
+ end
138
+
139
+ it "should not overwrite the setter if there is already one present" do
140
+ @klass = Class.new do
141
+ def items=(val)
142
+ @items = [1, *val]
143
+ end
144
+
145
+ include SAXMachine
146
+ elements :items
147
+ end
148
+ document = @klass.new
149
+ document.items = [2, 3]
150
+ document.items.should == [1, 2, 3]
151
+ end
152
+
108
153
  end
109
154
 
110
155
  describe "when using options for parsing elements" do
@@ -382,6 +427,23 @@ describe "SAXMachine" do
382
427
  document.entries.first.title.should == "correct title"
383
428
  end
384
429
 
430
+ it "should parse elements, and make attributes and inner text available" do
431
+ class Related
432
+ include SAXMachine
433
+ element 'related', :as=>:item
434
+ element 'related', :as=>:attr, :value=>'attr'
435
+ end
436
+ class Foo
437
+ elements 'related', :as=>'items', :class=>Related
438
+ end
439
+
440
+ doc = Foo.parse(%{<xml><collection><related attr='baz'>something</related><related>somethingelse</related></collection></xml>})
441
+ doc.items.first.should_not be_nil
442
+ doc.items.size.should == 2
443
+ doc.items.first.item.should == 'something'
444
+ doc.items.last.item.should == 'somethingelse'
445
+ end
446
+
385
447
  it "should parse out an attribute value from the tag that starts the collection" do
386
448
  class Foo
387
449
  element :entry, :value => :href, :as => :url
@@ -392,7 +454,6 @@ describe "SAXMachine" do
392
454
  document.entries.first.url.should == "http://pauldix.net"
393
455
  end
394
456
  end
395
-
396
457
  end
397
458
 
398
459
  describe "full example" do
@@ -437,13 +498,15 @@ describe "SAXMachine" do
437
498
  </category>
438
499
  </categories>
439
500
  ]
440
- class CategoryCollection; end
501
+ class CategoryCollection;
502
+ end
441
503
  class Category
442
504
  include SAXMachine
443
505
  attr_accessor :id
444
506
  element :category, :value => :id, :as => :id
445
507
  element :title
446
508
  element :categories, :as => :collection, :class => CategoryCollection
509
+ parent :parent
447
510
  end
448
511
  class CategoryCollection
449
512
  include SAXMachine
@@ -455,6 +518,7 @@ describe "SAXMachine" do
455
518
  it "should parse the first category" do
456
519
  @collection.categories.first.id.should == "1"
457
520
  @collection.categories.first.title.should == "First"
521
+ @collection.categories.first.parent.should == @collection
458
522
  end
459
523
 
460
524
  it "should parse the nested category" do
@@ -524,4 +588,151 @@ describe "SAXMachine" do
524
588
  @item.title.should == "Hello"
525
589
  end
526
590
  end
591
+
592
+ describe "with config to pull multiple attributes" do
593
+ before do
594
+ @xml = %[
595
+ <item id="1">
596
+ <author name="John Doe" role="writer" />
597
+ </item>
598
+ ]
599
+ class AuthorElement
600
+ include SAXMachine
601
+ attribute :name
602
+ attribute :role
603
+ end
604
+ class ItemElement
605
+ include SAXMachine
606
+ element :author, :class => AuthorElement
607
+ end
608
+ @item = ItemElement.parse(@xml)
609
+ end
610
+
611
+ it 'should have the child element' do
612
+ @item.author.should_not be_nil
613
+ end
614
+
615
+ it 'should have the author name' do
616
+ @item.author.name.should == 'John Doe'
617
+ end
618
+
619
+ it 'should have the author role' do
620
+ @item.author.role.should == 'writer'
621
+ end
622
+ end
623
+
624
+ describe "with multiple elements and multiple attributes" do
625
+ before do
626
+ @xml = %[
627
+ <item id="1">
628
+ <author name="John Doe" role="writer" />
629
+ <author name="Jane Doe" role="artist" />
630
+ </item>
631
+ ]
632
+ class AuthorElement2
633
+ include SAXMachine
634
+ attribute :name
635
+ attribute :role
636
+ end
637
+ class ItemElement2
638
+ include SAXMachine
639
+ elements :author, :as => :authors, :class => AuthorElement2
640
+ end
641
+ @item = ItemElement2.parse(@xml)
642
+ end
643
+
644
+ it 'should have the child elements' do
645
+ @item.authors.should_not be_nil
646
+ @item.authors.count.should == 2
647
+ end
648
+
649
+ it 'should have the author names' do
650
+ @item.authors.first.name.should == 'John Doe'
651
+ @item.authors.last.name.should == 'Jane Doe'
652
+ end
653
+
654
+ it 'should have the author roles' do
655
+ @item.authors.first.role.should == 'writer'
656
+ @item.authors.last.role.should == 'artist'
657
+ end
658
+ end
659
+
660
+ describe "with mixed attributes and element values" do
661
+ before do
662
+ @xml = %[
663
+ <item id="1">
664
+ <author role="writer">John Doe</author>
665
+ </item>
666
+ ]
667
+ class AuthorElement3
668
+ include SAXMachine
669
+ value :name
670
+ attribute :role
671
+ end
672
+ class ItemElement3
673
+ include SAXMachine
674
+ element :author, :class => AuthorElement3
675
+ end
676
+ @item = ItemElement3.parse(@xml)
677
+ end
678
+
679
+ it 'should have the child elements' do
680
+ @item.author.should_not be_nil
681
+ end
682
+
683
+ it 'should have the author names' do
684
+ @item.author.name.should == 'John Doe'
685
+ end
686
+
687
+ it 'should have the author roles' do
688
+ @item.author.role.should == 'writer'
689
+ end
690
+ end
691
+
692
+ describe "with multiple mixed attributes and element values" do
693
+ before do
694
+ @xml = %[
695
+ <item id="1">
696
+ <title>sweet</title>
697
+ <author role="writer">John Doe</author>
698
+ <author role="artist">Jane Doe</author>
699
+ </item>
700
+ ]
701
+ class AuthorElement4
702
+ include SAXMachine
703
+ value :name
704
+ attribute :role
705
+ end
706
+ class ItemElement4
707
+ include SAXMachine
708
+ element :title
709
+ elements :author, :as => :authors, :class => AuthorElement4
710
+
711
+ def title=(blah)
712
+ #raise 'woo'
713
+ @title = blah
714
+ end
715
+ end
716
+ @item = ItemElement4.parse(@xml)
717
+ end
718
+
719
+ it 'should have the title' do
720
+ @item.title.should == 'sweet'
721
+ end
722
+
723
+ it 'should have the child elements' do
724
+ @item.authors.should_not be_nil
725
+ @item.authors.count.should == 2
726
+ end
727
+
728
+ it 'should have the author names' do
729
+ @item.authors.first.name.should == 'John Doe'
730
+ @item.authors.last.name.should == 'Jane Doe'
731
+ end
732
+
733
+ it 'should have the author roles' do
734
+ @item.authors.first.role.should == 'writer'
735
+ @item.authors.last.role.should == 'artist'
736
+ end
737
+ end
527
738
  end
@@ -1,12 +1,11 @@
1
1
  require 'date'
2
2
 
3
3
  # gem install redgreen for colored test output
4
- begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end
4
+ begin require "redgreen" unless ENV['TM_CURRENT_LINE']
5
+ rescue LoadError
6
+ end
5
7
 
6
8
  path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
7
9
  $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
8
10
 
9
- require "lib/sax-machine"
10
-
11
- # Spec::Runner.configure do |config|
12
- # end
11
+ require "sax-machine"
metadata CHANGED
@@ -1,22 +1,22 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sax-machine
3
3
  version: !ruby/object:Gem::Version
4
- hash: 63
5
- prerelease: false
4
+ hash: 55
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 16
10
- version: 0.0.16
9
+ - 20
10
+ version: 0.0.20
11
11
  platform: ruby
12
12
  authors:
13
13
  - Paul Dix
14
+ - Julien Kirch
14
15
  autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2009-01-13 00:00:00 -05:00
19
- default_executable:
19
+ date: 2011-07-20 00:00:00 Z
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
22
  name: nokogiri
@@ -44,19 +44,19 @@ extra_rdoc_files: []
44
44
 
45
45
  files:
46
46
  - lib/sax-machine.rb
47
+ - lib/sax-machine/sax_attribute_config.rb
47
48
  - lib/sax-machine/sax_config.rb
49
+ - lib/sax-machine/sax_document.rb
48
50
  - lib/sax-machine/sax_collection_config.rb
49
51
  - lib/sax-machine/sax_element_config.rb
50
- - lib/sax-machine/sax_document.rb
52
+ - lib/sax-machine/sax_element_value_config.rb
51
53
  - lib/sax-machine/sax_handler.rb
54
+ - lib/sax-machine/sax_parent_config.rb
52
55
  - README.textile
53
56
  - Rakefile
54
- - .rspec
55
57
  - Gemfile
56
- - Gemfile.lock
57
58
  - spec/spec_helper.rb
58
59
  - spec/sax-machine/sax_document_spec.rb
59
- has_rdoc: true
60
60
  homepage: http://github.com/pauldix/sax-machine
61
61
  licenses: []
62
62
 
@@ -86,7 +86,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  requirements: []
87
87
 
88
88
  rubyforge_project:
89
- rubygems_version: 1.3.7
89
+ rubygems_version: 1.8.5
90
90
  signing_key:
91
91
  specification_version: 2
92
92
  summary: Declarative SAX Parsing with Nokogiri
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --require=./spec/spec_helper.rb
2
- --color
@@ -1,20 +0,0 @@
1
- GEM
2
- remote: http://rubygems.org/
3
- specs:
4
- diff-lcs (1.1.2)
5
- nokogiri (1.4.4)
6
- rspec (2.4.0)
7
- rspec-core (~> 2.4.0)
8
- rspec-expectations (~> 2.4.0)
9
- rspec-mocks (~> 2.4.0)
10
- rspec-core (2.4.0)
11
- rspec-expectations (2.4.0)
12
- diff-lcs (~> 1.1.2)
13
- rspec-mocks (2.4.0)
14
-
15
- PLATFORMS
16
- ruby
17
-
18
- DEPENDENCIES
19
- nokogiri (>= 1.4.4)
20
- rspec (>= 2.4.0)