sax-machine 0.0.16 → 0.0.20

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