sxrb 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,14 @@
1
+ 08 Aug 2012 (ver. 0.3.0)
2
+ * New constructors are available
3
+ * Parsing rules can be now reused
4
+ * YARD Documentation
5
+
6
+ 07 Aug 2012 (ver. 0.2.2)
7
+ * Fixed gem dependencies
8
+
9
+ 06 Aug 2012 (ver. 0.2.0)
10
+ * Added file and IO inputs support
11
+ * Project is now continously tested with Travis
12
+
13
+ 05 Aug 2012 (ver. 0.1.0)
14
+ * Release!
@@ -1,4 +1,5 @@
1
1
  require 'sxrb/parser'
2
2
  require 'sxrb/errors'
3
3
 
4
+ # Main module of gem.
4
5
  module SXRB; end
@@ -2,17 +2,25 @@ require 'libxml'
2
2
  require 'sxrb/node'
3
3
  require 'sxrb/text_node'
4
4
 
5
- # This class provides callbacks for SAX API which are configured with sxrb DSL.
6
5
 
7
6
  module SXRB
7
+
8
+ # This class provides callbacks for SAX API which are configured with sxrb
9
+ # DSL. It's behavior is configured by DSL via Proxy class objects, and should
10
+ # not be used outside of this scope. Currently it has only been tested with
11
+ # LibXML implementation of SAX, but set of method that object needs to
12
+ # provide is defined by standard, so using it with different backend should
13
+ # be automatic.
8
14
  class Callbacks
9
15
  #include LibXML::XML::SaxParser::VerboseCallbacks
10
16
  include LibXML::XML::SaxParser::Callbacks
17
+ # @api private
11
18
  def initialize
12
19
  @stack = []
13
20
  @rules_map = Hash.new {|h,k| h[k] = Rules.new}
14
21
  end
15
22
 
23
+ # @api private
16
24
  def on_start_element_ns(name, attributes, prefix, uri, namespaces)
17
25
  Node.new(name, attributes, prefix, uri, namespaces).tap do |node|
18
26
  @stack.push(node)
@@ -22,6 +30,7 @@ module SXRB
22
30
  end
23
31
  end
24
32
 
33
+ # @api private
25
34
  def on_characters(chars)
26
35
  if @stack.last.is_a? TextNode
27
36
  @stack.last.append_text chars
@@ -34,6 +43,7 @@ module SXRB
34
43
  end
35
44
  end
36
45
 
46
+ # @api private
37
47
  def on_end_element_ns(name, prefix, uri)
38
48
  @stack.pop if @stack.last.is_a? TextNode
39
49
 
@@ -48,6 +58,7 @@ module SXRB
48
58
  end
49
59
  end
50
60
 
61
+ # @api private
51
62
  def add_callback(type, rule_path, &block)
52
63
  @rules_map[Regexp.new "^#{rule_path}$"].tap do |rules|
53
64
  rules.rules[type] = block
@@ -55,9 +66,7 @@ module SXRB
55
66
  end
56
67
  end
57
68
 
58
- # options:
59
- # recursive
60
- #
69
+ # @api private
61
70
  def add_rule(rule, rule_path, options)
62
71
  operator = options[:recursive] ? '.*' : ' '
63
72
  new_rule = rule_path + operator + rule
@@ -66,23 +75,28 @@ module SXRB
66
75
 
67
76
  private
68
77
 
78
+ # @api private
69
79
  def invoke_callback(type, *args)
70
80
  current_matching_rules.
71
81
  map {|value| value.rules[type]}.
72
82
  compact.each {|callback| callback.call(*args)}
73
83
  end
74
84
 
85
+ # @api private
75
86
  def current_matching_rules
76
87
  @rules_map.each_pair.
77
88
  select {|rule, value| current_rule_path =~ rule}.
78
89
  map {|rule, value| value}
79
90
  end
80
91
 
92
+ # @api private
81
93
  def current_rule_path
82
94
  @stack.map(&:name).join(' ')
83
95
  end
84
96
  end
85
97
 
98
+ # Internal class that is designed to keep rules of matching XML elements.
99
+ # @api private
86
100
  class Rules
87
101
  attr_accessor :rules, :recursive
88
102
  def initialize
@@ -1,3 +1,5 @@
1
1
  module SXRB
2
+ # SXRB::TagMismatchError is raised whenever parser encounters closing tag of
3
+ # never opened element.
2
4
  class TagMismatchError < StandardError; end
3
5
  end
@@ -1,16 +1,27 @@
1
1
  module SXRB
2
+ # Node class is simple DOM-like element, which allows easy travesing through
3
+ # restricted part of document structure with #children and #parent methods.
2
4
  class Node < Struct.new(:name, :attributes, :prefix, :uri, :namespaces, :parent)
3
5
  attr_accessor :children
6
+ # Internal method used to build DOM-like structure.
7
+ # @api private
4
8
  def initialize(*args, &block)
5
9
  super(*args, &block)
6
10
  @children = []
7
11
  end
8
12
 
13
+ # Internal method used to build DOM-like structure.
14
+ # @api private
9
15
  def append(node)
10
16
  node.parent = self
11
17
  @children << node
12
18
  end
13
19
 
20
+
21
+ # Returns text content of a node (recursively), skipping all markup.
22
+ # @return [String]
23
+ # Text content of this node and all it's descendants is returned,
24
+ # concatenated.
14
25
  def content
15
26
  children.map {|child| child.is_a?(TextNode)? child.text : child.content}.flatten.join('')
16
27
  end
@@ -2,28 +2,90 @@ require 'sxrb/callbacks'
2
2
  require 'sxrb/proxy'
3
3
 
4
4
  module SXRB
5
+ # Main class of gem, which allows parsing XML data.
5
6
  class Parser
7
+ # Create parser object and parse provided input.
8
+ # @param [Filename, IO, String] input
9
+ # Data stream to be parsed.
10
+ # @option opts [Symbol] :mode (:string)
11
+ # Instructs SXRB how to treat input parameter. Possible values are:
12
+ # :string, :file, :io. Please note, that in case of :file mode
13
+ # input should be filename.
14
+ # @deprecated
15
+ # This method should not be used anymore. In version 1.0 it will work
16
+ # completely different so it is preferable to migrate to use parse_*
17
+ # methods right now.
6
18
  def initialize(input, opts = {}, &block)
7
19
  raise ArgumentError.new("Block expected") if block.nil?
8
- options = {:mode => :string}.merge(opts)
20
+ case opts[:mode]
21
+ when :file
22
+ self.class.parse_file(input, &block)
23
+ when :io
24
+ self.class.parse_io(input, &block)
25
+ else
26
+ self.class.parse_string(input, &block)
27
+ end
28
+ end
9
29
 
10
- # Create parser according to options
30
+ # Define set of reusable rules for SXRB parser.
31
+ # @yield Proxy
32
+ # See Proxy documentation for details on available methods and defining
33
+ # rules.
34
+ # @return [Callbacks]
35
+ # Set of rules which can be feeded to parse_* methods.
36
+ def self.define_rules(&block)
37
+ Callbacks.new.tap do |cb|
38
+ yield Proxy.new(cb)
39
+ end
40
+ end
11
41
 
12
- parser = case options[:mode]
13
- when :string
14
- LibXML::XML::SaxParser.string(input)
15
- when :file
16
- LibXML::XML::SaxParser.file(input)
17
- when :io
18
- LibXML::XML::SaxParser.io(input)
19
- end
42
+ # Parse string containing XML.
43
+ # @param [String] string
44
+ # Input string
45
+ # @param [optional, Callbacks] callbacks
46
+ # Set of rules generated by define_rules.
47
+ # @yield [Proxy]
48
+ # If callbacks parameter is not provided rules have to be defined directly in provided block.
49
+ # @return [nil]
50
+ def self.parse_string(string, callbacks = nil, &block)
51
+ raise ArgumentError unless !!callbacks ^ !!block
52
+ LibXML::XML::SaxParser.string(string).tap do |parser|
53
+ parser.callbacks = callbacks || define_rules(&block)
54
+ parser.parse
55
+ end
56
+ nil
57
+ end
20
58
 
21
- callbacks = Callbacks.new.tap do |cb|
22
- yield Proxy.new(cb)
59
+ # Parse file containing XML.
60
+ # @param [String] filename
61
+ # Path to file to be parsed.
62
+ # @param [optional, Callbacks] callbacks
63
+ # Set of rules generated by define_rules.
64
+ # @yield [Proxy]
65
+ # If callbacks parameter is not provided rules have to be defined directly in provided block.
66
+ # @return [nil]
67
+ def self.parse_file(filename, callbacks = nil, &block)
68
+ raise ArgumentError unless !!callbacks ^ !!block
69
+ LibXML::XML::SaxParser.file(filename).tap do |parser|
70
+ parser.callbacks = callbacks || define_rules(&block)
71
+ parser.parse
23
72
  end
73
+ end
24
74
 
25
- parser.callbacks = callbacks
26
- parser.parse
75
+ # Parse IO containing XML.
76
+ # @param [IO] io
77
+ # Path to stream to be parsed.
78
+ # @param [optional, Callbacks] callbacks
79
+ # Set of rules generated by define_rules.
80
+ # @yield [Proxy]
81
+ # If callbacks parameter is not provided rules have to be defined directly in provided block.
82
+ # @return [nil]
83
+ def self.parse_io(io, callbacks = nil, &block)
84
+ raise ArgumentError unless !!callbacks ^ !!block
85
+ LibXML::XML::SaxParser.io(io).tap do |parser|
86
+ parser.callbacks = callbacks || define_rules(&block)
87
+ parser.parse
88
+ end
27
89
  end
28
90
  end
29
91
  end
@@ -1,18 +1,25 @@
1
1
  module SXRB
2
+ # Objects of Proxy class are part of SXRB DSL and their methods are meant to
3
+ # be used to define set of rules needed to parse XML document. They have no
4
+ # other meaning and should not be used outside of that scope.
5
+ # @api public
2
6
  class Proxy
7
+ # Proxy objects are generated by the SXRB itself, and are passed to blocks
8
+ # to be used as DSL. They should not be created in any other context.
9
+ # Implementation might change without prior notice.
10
+ #
3
11
  # @api private
4
12
  def initialize(callback_tree, current_path = '')
5
13
  @callback_tree = callback_tree
6
14
  @current_path = current_path
7
15
  end
8
16
 
9
- # Defines child (a direct descendant) of an element defined in current.
10
- # block.
11
- # @param [String] *tags
17
+ # Defines child (a direct descendant) of an element defined in current block.
18
+ # @param [String] tags
12
19
  # names of tags that should be matched
13
20
  #
14
21
  # @yield [Proxy]
15
- # block receives Proxy element representing matched elements
22
+ # block receives Proxy element representing matched elements.
16
23
  #
17
24
  # @return [nil]
18
25
  #
@@ -28,19 +35,19 @@ module SXRB
28
35
  end
29
36
 
30
37
  # Defines descendant of an element defined in current block.
31
- # @param [String] *tags
38
+ # @param [String] tags
32
39
  # names of tags that should be matched
33
40
  #
34
41
  # @yield [Proxy]
35
- # block receives Proxy element representing matched elements
42
+ # block receives Proxy element representing matched elements.
36
43
  #
37
44
  # @return [nil]
38
45
  #
39
46
  # @api public
40
47
  #
41
- # @todo Add Regexp and other selectors support in addition to Strings.
42
- def descendant(*args, &block)
43
- args.each do |tag|
48
+ # @todo Add Regexp and other selectors support in addition to strings.
49
+ def descendant(*tags, &block)
50
+ tags.each do |tag|
44
51
  @callback_tree.add_rule(tag, @current_path, :recursive => true).tap do |new_path|
45
52
  block.call(Proxy.new(@callback_tree, new_path))
46
53
  end
@@ -49,21 +56,28 @@ module SXRB
49
56
 
50
57
  # Defines callback method invoked when matching element is completely
51
58
  # parsed.
52
- # @yield [Node] block receives whole parsed element with children.
59
+ #
60
+ # @yield [Node]
61
+ # block receives whole parsed element with children.
53
62
  #
54
63
  # @api public
55
64
  #
56
- # @note `on_element` should not be used for items that are expected to have
57
- # large node subtrees.
65
+ # @return [nil]
66
+ #
67
+ # @note
68
+ # `on_element` should not be used for items that are expected to have
69
+ # large node subtrees.
58
70
  def on_element(&block)
59
71
  @callback_tree.add_callback(:element, @current_path, &block)
60
72
  end
61
73
 
62
74
  # Defines a callback that is invoked whenever start tag is encountered.
63
75
  #
64
- # @yield [Node] block receives parsed node without any nested elements. All
65
- # inline attributes are available though.
76
+ # @yield [Node]
77
+ # block receives parsed node without any nested elements. All inline
78
+ # attributes are available though.
66
79
  #
80
+ # @return [nil]
67
81
  # @api public
68
82
  def on_start(&block)
69
83
  @callback_tree.add_callback(:start, @current_path, &block)
@@ -72,8 +86,10 @@ module SXRB
72
86
  # Defines a callback that is invoked whenever anonymous text node within
73
87
  # self is encountered.
74
88
  #
75
- # @yield [String] block receives raw content of parsed data in form of
76
- # String object.
89
+ # @yield [String]
90
+ # block receives raw content of parsed data in form of string object.
91
+ #
92
+ # @return [nil]
77
93
  #
78
94
  # @api public
79
95
  def on_characters(&block)
@@ -82,9 +98,11 @@ module SXRB
82
98
 
83
99
  # Defines a callback that is invoked whenever end tag is encountered.
84
100
  #
85
- # @yield [Node] block receives parsed node without any nested elements. All
86
- # inline attributes are available though.
101
+ # @yield [Node]
102
+ # block receives parsed node without any nested elements. All inline
103
+ # attributes are available though.
87
104
  #
105
+ # @return [nil]
88
106
  # @api public
89
107
  def on_end(&block)
90
108
  @callback_tree.add_callback(:end, @current_path, &block)
@@ -1,13 +1,19 @@
1
1
  module SXRB
2
+ # Class representing special case of DOM nodes which contain only text, and
3
+ # don't represent any particular element.
2
4
  class TextNode < Node
5
+ # @api private
3
6
  def initialize(text)
4
7
  @text = text || ""
5
8
  end
6
9
 
10
+ # @api private
7
11
  def append_text(text)
8
12
  @text << text
9
13
  end
10
14
 
15
+ # Accessor for text data kept in TextNode object.
16
+ # @return [String]
11
17
  def text
12
18
  @text
13
19
  end
@@ -1,92 +1,125 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
3
  describe SXRB::Parser do
4
- it 'should fail when created without block' do
5
- expect {
6
- SXRB::Parser.new("<xmlstring/>")
7
- }.to raise_error(ArgumentError)
4
+ context 'constructors' do
5
+ it 'should fail when created without block' do
6
+ expect {
7
+ SXRB::Parser.new("<xmlstring/>")
8
+ }.to raise_error(ArgumentError)
9
+ end
10
+
11
+ it 'defined rules should be reusable' do
12
+ @handler = double('handler')
13
+ @handler.should_receive(:msg).twice
14
+ rules = SXRB::Parser.define_rules do |root|
15
+ root.child("el") do |el|
16
+ el.on_element {@handler.msg}
17
+ end
18
+ end
19
+ SXRB::Parser.parse_string('<el></el>', rules)
20
+ SXRB::Parser.parse_string('<el></el>', rules)
21
+ end
8
22
  end
9
23
 
10
- context 'callbacks' do
11
- it 'should call defined start callback for child element' do
12
- handler = double('handler')
13
- handler.should_receive(:msg).once
24
+ context 'matchers' do
25
+ before(:each) do
26
+ @handler = double('handler')
27
+ end
14
28
 
29
+ it 'should call defined start callback for child element' do
30
+ @handler.should_receive(:msg).once
15
31
  SXRB::Parser.new("<testelement>content</testelement>") do |xml|
16
32
  xml.child 'testelement' do |test_element|
17
- test_element.on_start do |element|
18
- handler.msg
19
- end
33
+ test_element.on_start {@handler.msg}
20
34
  end
21
35
  end
22
36
  end
23
37
 
24
38
  it 'should call defined end callback for child element' do
25
- handler = double('handler')
26
- handler.should_receive(:msg).once
27
-
39
+ @handler.should_receive(:msg).once
28
40
  SXRB::Parser.new("<testelement>content</testelement>") do |xml|
29
41
  xml.child 'testelement' do |test_element|
30
- test_element.on_end do |element|
31
- handler.msg
32
- end
42
+ test_element.on_end {@handler.msg}
33
43
  end
34
44
  end
35
45
  end
36
46
 
37
47
  it 'should call defined characters callback for child element' do
38
- handler = double('handler')
39
- handler.should_receive(:msg).once
40
-
48
+ @handler.should_receive(:msg).once
41
49
  SXRB::Parser.new("<testelement>content</testelement>") do |xml|
42
50
  xml.child 'testelement' do |test_element|
43
- test_element.on_characters do |element|
44
- handler.msg
45
- end
51
+ test_element.on_characters {@handler.msg}
46
52
  end
47
53
  end
48
54
  end
49
55
 
50
56
 
51
57
  it 'should call defined element callback for child element' do
52
- handler = double('handler')
53
- handler.should_receive(:msg).once
54
-
58
+ @handler.should_receive(:msg).once
55
59
  SXRB::Parser.new("<testelement>content</testelement>") do |xml|
56
60
  xml.child 'testelement' do |test_element|
57
- test_element.on_element do |element|
58
- handler.msg
59
- end
61
+ test_element.on_element {@handler.msg}
60
62
  end
61
63
  end
62
64
  end
63
65
 
64
66
  it 'should call defined element callback for child element only' do
65
- handler = double('handler')
66
- handler.should_receive(:msg).once
67
-
67
+ @handler.should_receive(:msg).once
68
68
  SXRB::Parser.new("<testelement><testelement>content</testelement></testelement>") do |xml|
69
69
  xml.child 'testelement' do |test_element|
70
- test_element.on_element do |element|
71
- handler.msg
72
- end
70
+ test_element.on_element {@handler.msg}
73
71
  end
74
72
  end
75
73
  end
76
74
 
77
75
  it 'should call defined element callback for all descendants' do
78
- handler = double('handler')
79
- handler.should_receive(:msg).twice
80
-
76
+ @handler.should_receive(:msg).twice
81
77
  SXRB::Parser.new("<testelement><testelement>content</testelement></testelement>") do |xml|
82
78
  xml.descendant 'testelement' do |test_element|
83
- test_element.on_element do |element|
84
- handler.msg
85
- end
79
+ test_element.on_element {@handler.msg}
80
+ end
81
+ end
82
+ end
83
+
84
+ it 'should call callback for element regardless of nested elements' do
85
+ @handler.should_receive(:msg).once
86
+ SXRB::Parser.new("<testelement><a>a-content</a></testelement>") do |xml|
87
+ xml.child 'testelement' do |test_element|
88
+ test_element.on_element {@handler.msg}
89
+ end
90
+ end
91
+ end
92
+
93
+ it 'should not invoke callback for child which isn\'t direct descendant' do
94
+ @handler.should_not_receive(:msg)
95
+ SXRB::Parser.new("<testelement><a>a-content</a></testelement>") do |xml|
96
+ xml.child 'a' do |a|
97
+ a.on_element {@handler.msg}
86
98
  end
87
99
  end
88
100
  end
89
101
 
102
+ it 'should not find element with non-matching name' do
103
+ @handler.should_not_receive(:msg)
104
+ SXRB::Parser.new("<testelement>content</testelement>") do |xml|
105
+ xml.child 'othername' do |test_element|
106
+ test_element.on_element {@handler.msg}
107
+ end
108
+ end
109
+ end
110
+
111
+ it 'should find element by regexp' do
112
+ pending "feature not ready yet"
113
+ SXRB::Parser.new("<testelement>content</testelement>") do |xml|
114
+ xml.child /testel/ do |test_element|
115
+ test_element.on_element {@handler.msg}
116
+ end
117
+ end
118
+ end
119
+ end
120
+
121
+ context 'passed values' do
122
+
90
123
  it 'should pass empty hash to callback when no attributes are given' do
91
124
  SXRB::Parser.new("<testelement>content</testelement>") do |xml|
92
125
  xml.child 'testelement' do |test_element|
@@ -97,32 +130,51 @@ describe SXRB::Parser do
97
130
  end
98
131
  end
99
132
 
100
- it 'should pass value properly to callback to on_element' do
101
- SXRB::Parser.new("<testelement>content</testelement>") do |xml|
133
+ it 'should pass attributes properly to on_start callback' do
134
+ SXRB::Parser.new('<testelement foo="bar">content</testelement>') do |xml|
135
+ xml.child 'testelement' do |test_element|
136
+ test_element.on_start do |element|
137
+ element.attributes.should == {'foo' => 'bar'}
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ it 'should pass attributes properly to on_element callback' do
144
+ SXRB::Parser.new('<testelement foo="bar">content</testelement>') do |xml|
102
145
  xml.child 'testelement' do |test_element|
103
146
  test_element.on_element do |element|
104
- element.children.first.text == 'content'
147
+ element.attributes.should == {'foo' => 'bar'}
105
148
  end
106
149
  end
107
150
  end
108
151
  end
109
152
 
110
- it 'should not find element with non-matching name' do
111
- SXRB::Parser.new("<testelement>content</testelement>") do |xml|
112
- xml.child 'othername' do |test_element|
113
- test_element.on_element do |attrs, value|
114
- value.should == 'content'
153
+ it 'should pass attributes properly to on_end callback' do
154
+ SXRB::Parser.new('<testelement foo="bar">content</testelement>') do |xml|
155
+ xml.child 'testelement' do |test_element|
156
+ test_element.on_end do |element|
157
+ element.attributes.should == {'foo' => 'bar'}
115
158
  end
116
159
  end
117
160
  end
118
161
  end
119
162
 
120
- it 'should find element by regexp' do
121
- pending "feature not ready yet"
163
+ it 'should pass concatenated content' do
164
+ SXRB::Parser.new("<testelement><a>con</a>tent</testelement>") do |xml|
165
+ xml.child 'testelement' do |test_element|
166
+ test_element.on_element do |element|
167
+ element.content == 'content'
168
+ end
169
+ end
170
+ end
171
+ end
172
+
173
+ it 'should pass value properly to callback to on_element' do
122
174
  SXRB::Parser.new("<testelement>content</testelement>") do |xml|
123
- xml.child /testel/ do |test_element|
124
- test_element.on_element do |attrs, value|
125
- value.should == 'content'
175
+ xml.child 'testelement' do |test_element|
176
+ test_element.on_element do |element|
177
+ element.content == 'content'
126
178
  end
127
179
  end
128
180
  end
@@ -133,20 +185,18 @@ describe SXRB::Parser do
133
185
  xml.child 'testelement' do |test_element|
134
186
  test_element.child 'a' do |a|
135
187
  a.on_element do |element|
136
- element.children.first.text == 'a-content'
188
+ element.content == 'a-content'
137
189
  end
138
190
  end
139
191
  end
140
192
  end
141
193
  end
142
194
 
143
- it 'should call callback for element regardless of nested elements' do
144
- handler = double('handler')
145
- handler.should_receive(:msg).once
195
+ it 'should pass nested elements content on_element callback' do
146
196
  SXRB::Parser.new("<testelement><a>a-content</a></testelement>") do |xml|
147
197
  xml.child 'testelement' do |test_element|
148
- test_element.on_element do |element|
149
- handler.msg
198
+ test_element.on_element do |node|
199
+ node.content.should == 'a-content'
150
200
  end
151
201
  end
152
202
  end
@@ -158,7 +208,7 @@ describe SXRB::Parser do
158
208
  test_element.on_element do |element|
159
209
  element.children.first.tap do |a|
160
210
  a.name.should == 'a'
161
- a.children.first.text.should == 'a-content'
211
+ a.content.should == 'a-content'
162
212
  end
163
213
  end
164
214
  end
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'sxrb'
4
+ require 'rspec'
5
+ require 'rspec/autorun'
6
+
7
+ RSpec.configure do |config|
8
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sxrb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-07 00:00:00.000000000 Z
12
+ date: 2012-08-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: libxml-ruby
@@ -40,7 +40,9 @@ files:
40
40
  - lib/sxrb/errors.rb
41
41
  - lib/sxrb/proxy.rb
42
42
  - lib/sxrb.rb
43
+ - CHANGELOG
43
44
  - spec/parser_spec.rb
45
+ - spec/spec_helper.rb
44
46
  homepage: http://rubygems.org/gems/sxrb
45
47
  licenses:
46
48
  - MIT
@@ -68,4 +70,5 @@ specification_version: 3
68
70
  summary: Smart XML parser
69
71
  test_files:
70
72
  - spec/parser_spec.rb
73
+ - spec/spec_helper.rb
71
74
  has_rdoc: